summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Wolff <oliver.wolff@qt.io>2019-08-05 11:28:30 +0200
committerOliver Wolff <oliver.wolff@qt.io>2019-08-12 08:09:19 +0200
commitcfc5eaa6904354fc3084659691a6f28a51bf2269 (patch)
treeda49c1c9717a03cdc2e69970ad4848e989e6bb8c
parent8b7b52d66f2616040ca4aaae3f2732be96e19ab8 (diff)
parent99db6526341e6f0f2a4798088c1f954cff013b7b (diff)
Merge "Merge remote-tracking branch 'origin/dev' into wip/win"
-rw-r--r--.qmake.conf4
-rw-r--r--config.tests/bluez/main.cpp5
-rw-r--r--dist/changes-5.12.261
-rw-r--r--dist/changes-5.12.342
-rw-r--r--dist/changes-5.12.439
-rw-r--r--dist/changes-5.13.059
-rw-r--r--examples/bluetooth/btchat/main.cpp1
-rw-r--r--examples/bluetooth/btchat/remoteselector.cpp10
-rw-r--r--examples/bluetooth/btfiletransfer/main.cpp1
-rw-r--r--examples/bluetooth/btfiletransfer/pindisplay.h2
-rw-r--r--examples/bluetooth/btfiletransfer/progress.h6
-rw-r--r--examples/bluetooth/btfiletransfer/remoteselector.cpp25
-rw-r--r--examples/bluetooth/btfiletransfer/remoteselector.h4
-rw-r--r--examples/bluetooth/btscanner/device.cpp8
-rw-r--r--examples/bluetooth/btscanner/device.h2
-rw-r--r--examples/bluetooth/btscanner/main.cpp1
-rw-r--r--examples/bluetooth/btscanner/service.h2
-rw-r--r--examples/bluetooth/chat/qmlchat.cpp1
-rw-r--r--examples/bluetooth/heartrate-game/main.cpp1
-rw-r--r--examples/bluetooth/lowenergyscanner/device.cpp12
-rw-r--r--examples/bluetooth/lowenergyscanner/main.cpp1
-rw-r--r--examples/bluetooth/picturetransfer/filetransfer.h2
-rw-r--r--examples/bluetooth/picturetransfer/main.cpp1
-rw-r--r--examples/bluetooth/pingpong/main.cpp1
-rw-r--r--examples/bluetooth/scanner/qmlscanner.cpp1
-rw-r--r--examples/nfc/corkboard/android/AndroidManifest.xml2
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java61
-rw-r--r--src/bluetooth/android/devicediscoverybroadcastreceiver.cpp4
-rw-r--r--src/bluetooth/android/servicediscoverybroadcastreceiver.cpp3
-rw-r--r--src/bluetooth/bluetooth.pro34
-rw-r--r--src/bluetooth/doc/qtbluetooth.qdocconf1
-rw-r--r--src/bluetooth/doc/src/bluetooth-index.qdoc2
-rw-r--r--src/bluetooth/osx/btdelegates.cpp (renamed from src/bluetooth/osx/osxbtchanneldelegate.mm)30
-rw-r--r--src/bluetooth/osx/btdelegates_p.h149
-rw-r--r--src/bluetooth/osx/btraii.mm (renamed from src/bluetooth/osx/osxbtchanneldelegate_p.h)85
-rw-r--r--src/bluetooth/osx/btraii_p.h (renamed from src/bluetooth/qbluetoothserver_osx_p.h)121
-rw-r--r--src/bluetooth/osx/osxbt.pri15
-rw-r--r--src/bluetooth/osx/osxbtcentralmanager.mm49
-rw-r--r--src/bluetooth/osx/osxbtdeviceinquiry.mm24
-rw-r--r--src/bluetooth/osx/osxbtdeviceinquiry_p.h24
-rw-r--r--src/bluetooth/osx/osxbtl2capchannel.mm8
-rw-r--r--src/bluetooth/osx/osxbtl2capchannel_p.h6
-rw-r--r--src/bluetooth/osx/osxbtledeviceinquiry.mm87
-rw-r--r--src/bluetooth/osx/osxbtnotifier_p.h2
-rw-r--r--src/bluetooth/osx/osxbtperipheralmanager.mm4
-rw-r--r--src/bluetooth/osx/osxbtrfcommchannel.mm8
-rw-r--r--src/bluetooth/osx/osxbtrfcommchannel_p.h6
-rw-r--r--src/bluetooth/osx/osxbtsdpinquiry.mm9
-rw-r--r--src/bluetooth/osx/osxbtsdpinquiry_p.h14
-rw-r--r--src/bluetooth/osx/osxbtsocketlistener.mm21
-rw-r--r--src/bluetooth/osx/osxbtsocketlistener_p.h17
-rw-r--r--src/bluetooth/qbluetooth.cpp1
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent.cpp2
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp3
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm (renamed from src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm)327
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm458
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_p.h69
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp177
-rw-r--r--src/bluetooth/qbluetoothdeviceinfo.cpp1
-rw-r--r--src/bluetooth/qbluetoothdeviceinfo.h3
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_android.cpp15
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_p.cpp10
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_p.h36
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_winrt.cpp202
-rw-r--r--src/bluetooth/qbluetoothserver.cpp2
-rw-r--r--src/bluetooth/qbluetoothserver_osx.mm224
-rw-r--r--src/bluetooth/qbluetoothserver_p.h62
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent.cpp19
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_android.cpp133
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_osx.mm416
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_p.h21
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp40
-rw-r--r--src/bluetooth/qbluetoothserviceinfo.cpp14
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_bluez.cpp37
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_osx.mm375
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_p.h22
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_winrt.cpp8
-rw-r--r--src/bluetooth/qbluetoothsocket.cpp29
-rw-r--r--src/bluetooth/qbluetoothsocket.h16
-rw-r--r--src/bluetooth/qbluetoothsocket_android.cpp78
-rw-r--r--src/bluetooth/qbluetoothsocket_android_p.h2
-rw-r--r--src/bluetooth/qbluetoothsocket_bluez.cpp3
-rw-r--r--src/bluetooth/qbluetoothsocket_bluezdbus.cpp2
-rw-r--r--src/bluetooth/qbluetoothsocket_osx.mm839
-rw-r--r--src/bluetooth/qbluetoothsocket_osx_p.h82
-rw-r--r--src/bluetooth/qbluetoothsocket_winrt.cpp126
-rw-r--r--src/bluetooth/qbluetoothsocket_winrt_p.h15
-rw-r--r--src/bluetooth/qbluetoothsocketbase_p.h21
-rw-r--r--src/bluetooth/qbluetoothutils_winrt.cpp25
-rw-r--r--src/bluetooth/qbluetoothutils_winrt_p.h16
-rw-r--r--src/bluetooth/qlowenergycharacteristic.h2
-rw-r--r--src/bluetooth/qlowenergycontroller.cpp41
-rw-r--r--src/bluetooth/qlowenergycontroller.h8
-rw-r--r--src/bluetooth/qlowenergycontroller_android_p.h16
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez.cpp8
-rw-r--r--src/bluetooth/qlowenergycontroller_bluezdbus.cpp13
-rw-r--r--src/bluetooth/qlowenergycontroller_darwin.mm (renamed from src/bluetooth/qlowenergycontroller_osx.mm)1022
-rw-r--r--src/bluetooth/qlowenergycontroller_darwin_p.h (renamed from src/bluetooth/qlowenergycontroller_osx_p.h)112
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt.cpp131
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt_new.cpp1342
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt_new_p.h36
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt_p.h6
-rw-r--r--src/bluetooth/qlowenergycontrollerbase.cpp5
-rw-r--r--src/bluetooth/qlowenergycontrollerbase_p.h22
-rw-r--r--src/bluetooth/qlowenergydescriptor.h2
-rw-r--r--src/bluetooth/qlowenergyservice.cpp19
-rw-r--r--src/bluetooth/qlowenergyservice.h1
-rw-r--r--src/bluetooth/qlowenergyservice_osx.mm277
-rw-r--r--src/imports/bluetooth/plugins.qmltypes4
-rw-r--r--src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp16
-rw-r--r--src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h10
-rw-r--r--src/imports/nfc/plugins.qmltypes4
-rw-r--r--src/nfc/doc/qtnfc.qdocconf1
-rw-r--r--src/nfc/qnearfieldmanager.h2
-rw-r--r--src/nfc/qnearfieldmanager_emulator.cpp9
-rw-r--r--src/nfc/qnearfieldtagtype2.cpp7
-rw-r--r--src/nfc/qnearfieldtarget.cpp13
-rw-r--r--src/nfc/qnearfieldtarget_emulator.cpp7
-rw-r--r--src/nfc/qnearfieldtarget_emulator_p.h2
-rw-r--r--src/nfc/qqmlndefrecord.cpp5
-rw-r--r--tests/auto/bic/data/QtBluetooth.5.13.0.linux-gcc-amd64.txt5423
-rw-r--r--tests/auto/bic/data/QtNfc.5.13.0.linux-gcc-amd64.txt5189
-rw-r--r--tests/auto/qbluetoothdeviceinfo/tst_qbluetoothdeviceinfo.cpp10
-rw-r--r--tests/auto/qbluetoothserviceinfo/tst_qbluetoothserviceinfo.cpp45
-rw-r--r--tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp11
-rw-r--r--tests/bttestui/btlocaldevice.cpp96
126 files changed, 14546 insertions, 4380 deletions
diff --git a/.qmake.conf b/.qmake.conf
index f8cda0e7..f6895bb0 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,3 +1,5 @@
load(qt_build_config)
-MODULE_VERSION = 5.13.0
+DEFINES += QT_NO_FOREACH QT_NO_JAVA_STYLE_ITERATORS QT_NO_LINKED_LIST
+
+MODULE_VERSION = 5.14.0
diff --git a/config.tests/bluez/main.cpp b/config.tests/bluez/main.cpp
index 2e978b85..63d7f8eb 100644
--- a/config.tests/bluez/main.cpp
+++ b/config.tests/bluez/main.cpp
@@ -35,5 +35,10 @@ int main()
bacmp(&anyTmp, &localTmp);
+ uint32_t field0 = 1;
+ uint16_t field1 = 1;
+
+ field0 = htonl(field0);
+ field1 = htons(field1);
return 0;
}
diff --git a/dist/changes-5.12.2 b/dist/changes-5.12.2
new file mode 100644
index 00000000..9e0f7fa0
--- /dev/null
+++ b/dist/changes-5.12.2
@@ -0,0 +1,61 @@
+Qt 5.12.2 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.12.0 through 5.12.1.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.12 series is binary compatible with the 5.11.x series.
+Applications compiled for 5.11 will continue to run with 5.12.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+***************************************************************************
+* Qt 5.12.2 Changes *
+***************************************************************************
+
+QtBluetooth
+-----------
+
+ - Added documentation improvements to QBluetoothServiceDiscoveryAgent.
+
+QtNfc
+-----
+
+ - Fixed exceptions on Android WearOS devices because those devices not
+ supporting NFC.
+
+***************************************************************************
+* Platform Specific Changes *
+***************************************************************************
+
+Android
+-------
+
+ - [QTBUG-72681] Fixed wrong reversing of service uuids when calling
+ QBLuetoothSocket::connectToService().
+
+ - Fixed a crash when destroying QBluetoothDeviceDisocveryAgent during an
+ ongoing scan.
+
+ - [QTBUG-73571] Fixed tst_QBluetoothServiceDiscoveryAgent::tst_invalidBtAddress()
+ which was failing on Android.
+
+iOS/macOS
+---------
+
+ - [QTBUG-73140] Fixed a crash in QBluetoothDeviceDiscoveryAgent when the user
+ turns off Bluetooth while a scan is running.
+
+Linux/BlueZ
+-----------
+
+ - [QTBUG-72800] Addressed bug where a discovered custom uuid was not returned
+ via BluetoothServiceInfo::serviceUuid() but as serviceClassUuids().
diff --git a/dist/changes-5.12.3 b/dist/changes-5.12.3
new file mode 100644
index 00000000..2341dae0
--- /dev/null
+++ b/dist/changes-5.12.3
@@ -0,0 +1,42 @@
+Qt 5.12.3 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.12.0 through 5.12.2.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.12 series is binary compatible with the 5.11.x series.
+Applications compiled for 5.11 will continue to run with 5.12.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Qt 5.12.3 Changes *
+****************************************************************************
+
+QtBluetooth
+-----------
+
+ - Fixed crash at calling QLowEnergyController::disconnectFromDevice while
+ not connected.
+
+ - [QTBUG-74513] Fixed missing emission of QBluetoothSocket::bytesWritten() signal on
+ Bluez v5.46+.
+
+ - Fixed NullPointerException on Android when discovering BTLE services while an
+ unexpected device connect is triggered.
+
+ - Applied a variety of minor code cleanups.
+
+QtNfc
+-----
+
+ - [QTBUG-74538] Addressed a compile error in qnearfieldtarget_emulator_p.h
+ when using gcc 4.8.
diff --git a/dist/changes-5.12.4 b/dist/changes-5.12.4
new file mode 100644
index 00000000..cb7ef2bf
--- /dev/null
+++ b/dist/changes-5.12.4
@@ -0,0 +1,39 @@
+Qt 5.12.4 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.12.0 through 5.12.3.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.12 series is binary compatible with the 5.11.x series.
+Applications compiled for 5.11 will continue to run with 5.12.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Qt 5.12.3 Changes *
+****************************************************************************
+
+QtBluetooth
+-----------
+
+ - Fixed a memory leak in QBluetoothServiceDiscoveryAgent on Android.
+
+ - [QTBUG-75035] Improved likelihood of
+ QBluetoothSocket::connectToService(QBluetoothServiceInfo,..) succeeding when
+ QBluetoothServiceInfo::socketProtocol() returns a non-RFCOMM type. Since Android
+ does not support anything but RFCOMM it always assumes RFCOMM.
+
+ - Fixed reading of descriptor values on WinRT.
+
+ - [QTBUG-75043] Fixed behavior when a peripheral changes its service list at runtime
+
+ - [QTBUG-75278] Fixed socket leak when running QLowEnergyController Peripheral mode
+ on Linux.
diff --git a/dist/changes-5.13.0 b/dist/changes-5.13.0
new file mode 100644
index 00000000..921b45a9
--- /dev/null
+++ b/dist/changes-5.13.0
@@ -0,0 +1,59 @@
+Qt 5.13 introduces many new features and improvements as well as bugfixes
+over the 5.12.x series. For more details, refer to the online documentation
+included in this distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.13 series is binary compatible with the 5.12.x series.
+Applications compiled for 5.12 will continue to run with 5.13.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Qt 5.13.0 Changes *
+****************************************************************************
+
+QtBluetooth
+-----------
+
+ - [QTBUG-58660] Added ability to connect to BLE devices on WinRT without
+ pairing.
+
+ - [QTBUG-69954] Fixed potential crash due to late callbacks on WinRT.
+
+ - Improved WinRT implementation signficantly. This incorporates a large
+ number of patches (each improving the stability and general robustness of
+ the code base). During the process the number of potential asserts was
+ reduced as well.
+
+ - Deprecated QBluetoothDeviceInfo::DataCompleteness related APIs.
+
+ - Replaced QBluetoothDeviceInfo::LanAccessDevice with QBluetoothDeviceInfo::NetworkDevice.
+ LanAccessDevice was deprecated.
+
+ - Implemented support for QBluetoothDeviceDiscoveryAgent::deviceUpdated() on Apple and WinRT
+ platforms.
+
+ - [QTBUG-71943] Implemented RSSI and manufacturer data discovery on WinRT.
+
+ - [QTBUG-74394] Fixed broken QLowEnergyController::disconnectFromDevice() on WinRT.
+
+ - Added a compile fix for g++ 8.
+
+ - [QTBUG-73717] Fixed warnings in QDeclarativeBluetoothDiscoveryModel.
+
+QtNfc
+-----
+
+ - QNearFieldManager:
+ * adapterStateChanged() now has a fully qualified parameter
+ QNearFieldManager::AdapterState. This can cause a problem if the
+ connection/method invocation was done with just AdapterState as the
+ parameter type, in which case these need to be changed to use
+ QNearFieldManager::AdapaterState instead.
diff --git a/examples/bluetooth/btchat/main.cpp b/examples/bluetooth/btchat/main.cpp
index 5c7bbf75..e728efd2 100644
--- a/examples/bluetooth/btchat/main.cpp
+++ b/examples/bluetooth/btchat/main.cpp
@@ -56,6 +56,7 @@
int main(int argc, char *argv[])
{
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
Chat d;
diff --git a/examples/bluetooth/btchat/remoteselector.cpp b/examples/bluetooth/btchat/remoteselector.cpp
index 2bd1efcc..ec5d207c 100644
--- a/examples/bluetooth/btchat/remoteselector.cpp
+++ b/examples/bluetooth/btchat/remoteselector.cpp
@@ -114,17 +114,15 @@ void RemoteSelector::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo)
<< serviceInfo.protocolServiceMultiplexer();
qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel();
#endif
- QMapIterator<QListWidgetItem *, QBluetoothServiceInfo> i(m_discoveredServices);
- while (i.hasNext()){
- i.next();
- if (serviceInfo.device().address() == i.value().device().address()){
+ const QBluetoothAddress address = serviceInfo.device().address();
+ for (const QBluetoothServiceInfo &info : qAsConst(m_discoveredServices)) {
+ if (info.device().address() == address)
return;
- }
}
QString remoteName;
if (serviceInfo.device().name().isEmpty())
- remoteName = serviceInfo.device().address().toString();
+ remoteName = address.toString();
else
remoteName = serviceInfo.device().name();
diff --git a/examples/bluetooth/btfiletransfer/main.cpp b/examples/bluetooth/btfiletransfer/main.cpp
index 2c2b6df5..1871e207 100644
--- a/examples/bluetooth/btfiletransfer/main.cpp
+++ b/examples/bluetooth/btfiletransfer/main.cpp
@@ -54,6 +54,7 @@
int main(int argc, char *argv[])
{
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
RemoteSelector d;
diff --git a/examples/bluetooth/btfiletransfer/pindisplay.h b/examples/bluetooth/btfiletransfer/pindisplay.h
index b7ad8866..7acc517e 100644
--- a/examples/bluetooth/btfiletransfer/pindisplay.h
+++ b/examples/bluetooth/btfiletransfer/pindisplay.h
@@ -64,7 +64,7 @@ class pinDisplay : public QDialog
Q_OBJECT
public:
- explicit pinDisplay(QString title, QString pin, QWidget *parent = 0);
+ explicit pinDisplay(QString title, QString pin, QWidget *parent = nullptr);
~pinDisplay();
void setOkCancel();
diff --git a/examples/bluetooth/btfiletransfer/progress.h b/examples/bluetooth/btfiletransfer/progress.h
index 64a19ca0..afd72153 100644
--- a/examples/bluetooth/btfiletransfer/progress.h
+++ b/examples/bluetooth/btfiletransfer/progress.h
@@ -52,7 +52,7 @@
#define PROGRESS_H
#include <QDialog>
-#include <QTime>
+#include <QElapsedTimer>
QT_FORWARD_DECLARE_CLASS(QBluetoothTransferReply)
@@ -69,7 +69,7 @@ class Progress : public QDialog
Q_OBJECT
public:
- explicit Progress(QWidget *parent = 0);
+ explicit Progress(QWidget *parent = nullptr);
~Progress();
void setStatus(QString title, QString filename);
@@ -81,7 +81,7 @@ public Q_SLOTS:
private:
Ui::Progress *ui;
- QTime start;
+ QElapsedTimer start;
};
#endif // PROGRESS_H
diff --git a/examples/bluetooth/btfiletransfer/remoteselector.cpp b/examples/bluetooth/btfiletransfer/remoteselector.cpp
index 766bd028..b3c60cb3 100644
--- a/examples/bluetooth/btfiletransfer/remoteselector.cpp
+++ b/examples/bluetooth/btfiletransfer/remoteselector.cpp
@@ -171,18 +171,17 @@ void RemoteSelector::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo)
// new QListWidgetItem(QString::fromLatin1("%1\t%2\t%3").arg(serviceInfo.device().address().toString(),
// serviceInfo.device().name(), serviceInfo.serviceName()));
- QMutableMapIterator<int, QBluetoothServiceInfo> i(m_discoveredServices);
- while (i.hasNext()){
- i.next();
- if (serviceInfo.device().address() == i.value().device().address()){
- i.setValue(serviceInfo);
+ const QBluetoothAddress address = serviceInfo.device().address();
+ for (QBluetoothServiceInfo &info : m_discoveredServices) {
+ if (info.device().address() == address){
+ info = serviceInfo;
return;
}
}
int row = ui->remoteDevices->rowCount();
ui->remoteDevices->insertRow(row);
- QTableWidgetItem *item = new QTableWidgetItem(serviceInfo.device().address().toString());
+ QTableWidgetItem *item = new QTableWidgetItem(address.toString());
ui->remoteDevices->setItem(row, 0, item);
item = new QTableWidgetItem(serviceInfo.device().name());
ui->remoteDevices->setItem(row, 1, item);
@@ -190,9 +189,7 @@ void RemoteSelector::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo)
ui->remoteDevices->setItem(row, 2, item);
- QBluetoothLocalDevice::Pairing p;
-
- p = m_localDevice->pairingStatus(serviceInfo.device().address());
+ QBluetoothLocalDevice::Pairing p = m_localDevice->pairingStatus(address);
ui->remoteDevices->blockSignals(true);
@@ -275,13 +272,11 @@ void RemoteSelector::on_stopButton_clicked()
m_discoveryAgent->stop();
}
-QString RemoteSelector::addressToName(const QBluetoothAddress &address)
+QString RemoteSelector::addressToName(const QBluetoothAddress &address) const
{
- QMapIterator<int, QBluetoothServiceInfo> i(m_discoveredServices);
- while (i.hasNext()){
- i.next();
- if (i.value().device().address() == address)
- return i.value().device().name();
+ for (const QBluetoothServiceInfo &info : m_discoveredServices) {
+ if (info.device().address() == address)
+ return info.device().name();
}
return address.toString();
}
diff --git a/examples/bluetooth/btfiletransfer/remoteselector.h b/examples/bluetooth/btfiletransfer/remoteselector.h
index b0850c41..8266c8c4 100644
--- a/examples/bluetooth/btfiletransfer/remoteselector.h
+++ b/examples/bluetooth/btfiletransfer/remoteselector.h
@@ -78,7 +78,7 @@ class RemoteSelector : public QDialog
Q_OBJECT
public:
- explicit RemoteSelector(QWidget *parent = 0);
+ explicit RemoteSelector(QWidget *parent = nullptr);
~RemoteSelector();
void startDiscovery(const QBluetoothUuid &uuid);
@@ -95,7 +95,7 @@ private:
QPointer<pinDisplay> m_pindisplay;
bool m_pairingError;
- QString addressToName(const QBluetoothAddress &address);
+ QString addressToName(const QBluetoothAddress &address) const;
public Q_SLOTS:
void startDiscovery();
diff --git a/examples/bluetooth/btscanner/device.cpp b/examples/bluetooth/btscanner/device.cpp
index e97c0637..b6a07db4 100644
--- a/examples/bluetooth/btscanner/device.cpp
+++ b/examples/bluetooth/btscanner/device.cpp
@@ -109,9 +109,9 @@ void DeviceDiscoveryDialog::addDevice(const QBluetoothDeviceInfo &info)
QListWidgetItem *item = new QListWidgetItem(label);
QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(info.address());
if (pairingStatus == QBluetoothLocalDevice::Paired || pairingStatus == QBluetoothLocalDevice::AuthorizedPaired )
- item->setTextColor(QColor(Qt::green));
+ item->setForeground(QColor(Qt::green));
else
- item->setTextColor(QColor(Qt::black));
+ item->setForeground(QColor(Qt::black));
ui->list->addItem(item);
}
@@ -218,12 +218,12 @@ void DeviceDiscoveryDialog::pairingDone(const QBluetoothAddress &address, QBluet
if (pairing == QBluetoothLocalDevice::Paired || pairing == QBluetoothLocalDevice::AuthorizedPaired ) {
for (int var = 0; var < items.count(); ++var) {
QListWidgetItem *item = items.at(var);
- item->setTextColor(QColor(Qt::green));
+ item->setForeground(QColor(Qt::green));
}
} else {
for (int var = 0; var < items.count(); ++var) {
QListWidgetItem *item = items.at(var);
- item->setTextColor(QColor(Qt::red));
+ item->setForeground(QColor(Qt::red));
}
}
}
diff --git a/examples/bluetooth/btscanner/device.h b/examples/bluetooth/btscanner/device.h
index 7111e1ec..35dc7965 100644
--- a/examples/bluetooth/btscanner/device.h
+++ b/examples/bluetooth/btscanner/device.h
@@ -67,7 +67,7 @@ class DeviceDiscoveryDialog : public QDialog
Q_OBJECT
public:
- DeviceDiscoveryDialog(QWidget *parent = 0);
+ DeviceDiscoveryDialog(QWidget *parent = nullptr);
~DeviceDiscoveryDialog();
public slots:
diff --git a/examples/bluetooth/btscanner/main.cpp b/examples/bluetooth/btscanner/main.cpp
index ca762802..a84dcda9 100644
--- a/examples/bluetooth/btscanner/main.cpp
+++ b/examples/bluetooth/btscanner/main.cpp
@@ -54,6 +54,7 @@
int main(int argc, char *argv[])
{
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
DeviceDiscoveryDialog d;
diff --git a/examples/bluetooth/btscanner/service.h b/examples/bluetooth/btscanner/service.h
index 94748dad..93d1e12b 100644
--- a/examples/bluetooth/btscanner/service.h
+++ b/examples/bluetooth/btscanner/service.h
@@ -66,7 +66,7 @@ class ServiceDiscoveryDialog : public QDialog
Q_OBJECT
public:
- ServiceDiscoveryDialog(const QString &name, const QBluetoothAddress &address, QWidget *parent = 0);
+ ServiceDiscoveryDialog(const QString &name, const QBluetoothAddress &address, QWidget *parent = nullptr);
~ServiceDiscoveryDialog();
public slots:
diff --git a/examples/bluetooth/chat/qmlchat.cpp b/examples/bluetooth/chat/qmlchat.cpp
index e7ce3f3a..6c8d2fa7 100644
--- a/examples/bluetooth/chat/qmlchat.cpp
+++ b/examples/bluetooth/chat/qmlchat.cpp
@@ -62,6 +62,7 @@
int main(int argc, char *argv[])
{
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication application(argc, argv);
QList<QBluetoothHostInfo> infos = QBluetoothLocalDevice::allDevices();
diff --git a/examples/bluetooth/heartrate-game/main.cpp b/examples/bluetooth/heartrate-game/main.cpp
index 099f82a7..05557c05 100644
--- a/examples/bluetooth/heartrate-game/main.cpp
+++ b/examples/bluetooth/heartrate-game/main.cpp
@@ -60,6 +60,7 @@
int main(int argc, char *argv[])
{
QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
ConnectionHandler connectionHandler;
diff --git a/examples/bluetooth/lowenergyscanner/device.cpp b/examples/bluetooth/lowenergyscanner/device.cpp
index 82179db1..d860457e 100644
--- a/examples/bluetooth/lowenergyscanner/device.cpp
+++ b/examples/bluetooth/lowenergyscanner/device.cpp
@@ -152,12 +152,12 @@ void Device::scanServices(const QString &address)
// We need the current device for service discovery.
for (auto d: qAsConst(devices)) {
- auto device = qobject_cast<DeviceInfo *>(d);
- if (!device)
- continue;
-
- if (device->getAddress() == address )
- currentDevice.setDevice(device->getDevice());
+ if (auto device = qobject_cast<DeviceInfo *>(d)) {
+ if (device->getAddress() == address ) {
+ currentDevice.setDevice(device->getDevice());
+ break;
+ }
+ }
}
if (!currentDevice.getDevice().isValid()) {
diff --git a/examples/bluetooth/lowenergyscanner/main.cpp b/examples/bluetooth/lowenergyscanner/main.cpp
index 351ab13a..f223b028 100644
--- a/examples/bluetooth/lowenergyscanner/main.cpp
+++ b/examples/bluetooth/lowenergyscanner/main.cpp
@@ -59,6 +59,7 @@
int main(int argc, char *argv[])
{
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
Device d;
diff --git a/examples/bluetooth/picturetransfer/filetransfer.h b/examples/bluetooth/picturetransfer/filetransfer.h
index 5e2e08f9..4dee32fe 100644
--- a/examples/bluetooth/picturetransfer/filetransfer.h
+++ b/examples/bluetooth/picturetransfer/filetransfer.h
@@ -59,7 +59,7 @@ class FileTransfer : public QObject
Q_OBJECT
Q_PROPERTY(float progress READ getProgress NOTIFY progressChanged)
public:
- explicit FileTransfer(QObject *parent = 0);
+ explicit FileTransfer(QObject *parent = nullptr);
float getProgress() { return m_progress;}
signals:
diff --git a/examples/bluetooth/picturetransfer/main.cpp b/examples/bluetooth/picturetransfer/main.cpp
index b4a1e670..4622e87e 100644
--- a/examples/bluetooth/picturetransfer/main.cpp
+++ b/examples/bluetooth/picturetransfer/main.cpp
@@ -58,6 +58,7 @@
int main(int argc, char *argv[])
{
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication application(argc, argv);
//! [Transfer-2]
QQuickView view;
diff --git a/examples/bluetooth/pingpong/main.cpp b/examples/bluetooth/pingpong/main.cpp
index fc1029de..7c34b135 100644
--- a/examples/bluetooth/pingpong/main.cpp
+++ b/examples/bluetooth/pingpong/main.cpp
@@ -58,6 +58,7 @@
int main(int argc, char *argv[])
{
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
PingPong pingPong;
QQmlApplicationEngine engine;
diff --git a/examples/bluetooth/scanner/qmlscanner.cpp b/examples/bluetooth/scanner/qmlscanner.cpp
index 4ead2364..2dbc0c27 100644
--- a/examples/bluetooth/scanner/qmlscanner.cpp
+++ b/examples/bluetooth/scanner/qmlscanner.cpp
@@ -56,6 +56,7 @@
int main(int argc, char *argv[])
{
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication application(argc, argv);
const QString mainQmlApp(QStringLiteral("qrc:/scanner.qml"));
QQuickView view;
diff --git a/examples/nfc/corkboard/android/AndroidManifest.xml b/examples/nfc/corkboard/android/AndroidManifest.xml
index 68566b1b..ac0c5a67 100644
--- a/examples/nfc/corkboard/android/AndroidManifest.xml
+++ b/examples/nfc/corkboard/android/AndroidManifest.xml
@@ -72,7 +72,7 @@
</application>
- <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16"/>
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java
index dc48514a..c6ffbbf4 100644
--- a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java
+++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java
@@ -1,6 +1,6 @@
/****************************************************************************
**
- ** Copyright (C) 2016 The Qt Company Ltd.
+ ** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
@@ -47,6 +47,11 @@ import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
+import android.bluetooth.le.BluetoothLeScanner;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanFilter;
+import android.bluetooth.le.ScanResult;
+import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
@@ -90,6 +95,9 @@ public class QtBluetoothLE {
private final int RUNNABLE_TIMEOUT = 3000; // 3 seconds
private final Handler timeoutHandler = new Handler(Looper.getMainLooper());
+ /* New BTLE scanner setup since Android SDK v21 */
+ private BluetoothLeScanner mBluetoothLeScanner = null;
+
private class TimeoutRunnable implements Runnable {
public TimeoutRunnable(int handle) { pendingJobHandle = handle; }
@Override
@@ -123,6 +131,7 @@ public class QtBluetoothLE {
@SuppressWarnings("WeakerAccess")
public QtBluetoothLE() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
}
public QtBluetoothLE(final String remoteAddress, Context context) {
@@ -131,7 +140,6 @@ public class QtBluetoothLE {
mRemoteGattAddress = remoteAddress;
}
-
/*************************************************************/
/* Device scan */
/*************************************************************/
@@ -144,27 +152,45 @@ public class QtBluetoothLE {
return true;
if (isEnabled) {
- mLeScanRunning = mBluetoothAdapter.startLeScan(leScanCallback);
+ Log.d(TAG, "New BTLE scanning API");
+ ScanSettings.Builder settingsBuilder = new ScanSettings.Builder();
+ settingsBuilder = settingsBuilder.setScanMode(ScanSettings.SCAN_MODE_BALANCED);
+ ScanSettings settings = settingsBuilder.build();
+
+ List<ScanFilter> filterList = new ArrayList<ScanFilter>(2);
+
+ mBluetoothLeScanner.startScan(filterList, settings, leScanCallback21);
+ mLeScanRunning = true;
} else {
- mBluetoothAdapter.stopLeScan(leScanCallback);
+ mBluetoothLeScanner.stopScan(leScanCallback21);
mLeScanRunning = false;
}
return (mLeScanRunning == isEnabled);
}
- // Device scan callback
- private final BluetoothAdapter.LeScanCallback leScanCallback =
- new BluetoothAdapter.LeScanCallback() {
+ // Device scan callback (SDK v21+)
+ private final ScanCallback leScanCallback21 = new ScanCallback() {
+ @Override
+ public void onScanResult(int callbackType, ScanResult result) {
+ super.onScanResult(callbackType, result);
+ leScanResult(qtObject, result.getDevice(), result.getRssi(), result.getScanRecord().getBytes());
+ }
- @Override
- public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
- if (qtObject == 0)
- return;
+ @Override
+ public void onBatchScanResults(List<ScanResult> results) {
+ super.onBatchScanResults(results);
+ for (ScanResult result : results)
+ leScanResult(qtObject, result.getDevice(), result.getRssi(), result.getScanRecord().getBytes());
- leScanResult(qtObject, device, rssi, scanRecord);
- }
- };
+ }
+
+ @Override
+ public void onScanFailed(int errorCode) {
+ super.onScanFailed(errorCode);
+ Log.d(TAG, "BTLE device scan failed with " + errorCode);
+ }
+ };
public native void leScanResult(long qtObject, BluetoothDevice device, int rssi, byte[] scanRecord);
@@ -203,7 +229,6 @@ public class QtBluetoothLE {
case BluetoothGatt.GATT_FAILURE: // Android's equivalent of "do not know what error it is"
errorCode = 1; break; //QLowEnergyController::UnknownError
case 8: // BLE_HCI_CONNECTION_TIMEOUT
- case 22: // BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION
Log.w(TAG, "Connection Error: Try to delay connect() call after previous activity");
errorCode = 5; break; //QLowEnergyController::ConnectionError
case 19: // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION
@@ -212,6 +237,9 @@ public class QtBluetoothLE {
Log.w(TAG, "The remote host closed the connection");
errorCode = 7; //QLowEnergyController::RemoteHostClosedError
break;
+ case 22: // BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION
+ // Internally, Android maps PIN_OR_KEY_MISSING to GATT_CONN_TERMINATE_LOCAL_HOST
+ errorCode = 8; break; //QLowEnergyController::AuthorizationError
default:
Log.w(TAG, "Unhandled error code on connectionStateChanged: " + status + " " + newState);
errorCode = status; break; //TODO deal with all errors
@@ -839,6 +867,9 @@ public class QtBluetoothLE {
*/
public String includedServices(String serviceUuid)
{
+ if (mBluetoothGatt == null)
+ return null;
+
UUID uuid;
try {
uuid = UUID.fromString(serviceUuid);
diff --git a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
index 99245af3..f1f50516 100644
--- a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
+++ b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
@@ -516,7 +516,7 @@ QBluetoothDeviceInfo DeviceDiscoveryBroadcastReceiver::retrieveDeviceInfo(JNIEnv
const char *scanRecordBuffer = reinterpret_cast<const char *>(elems);
const int scanRecordLength = env->GetArrayLength(scanRecord);
- QList<QBluetoothUuid> serviceUuids;
+ QVector<QBluetoothUuid> serviceUuids;
int i = 0;
// Spec 4.2, Vol 3, Part C, Chapter 11
@@ -567,7 +567,7 @@ QBluetoothDeviceInfo DeviceDiscoveryBroadcastReceiver::retrieveDeviceInfo(JNIEnv
serviceUuids.append(foundService);
}
- info.setServiceUuids(serviceUuids, QBluetoothDeviceInfo::DataIncomplete);
+ info.setServiceUuids(serviceUuids);
env->ReleaseByteArrayElements(scanRecord, elems, JNI_ABORT);
}
diff --git a/src/bluetooth/android/servicediscoverybroadcastreceiver.cpp b/src/bluetooth/android/servicediscoverybroadcastreceiver.cpp
index be1953d5..283db623 100644
--- a/src/bluetooth/android/servicediscoverybroadcastreceiver.cpp
+++ b/src/bluetooth/android/servicediscoverybroadcastreceiver.cpp
@@ -99,7 +99,6 @@ QList<QBluetoothUuid> ServiceDiscoveryBroadcastReceiver::convertParcelableArray(
{
QList<QBluetoothUuid> result;
QAndroidJniEnvironment env;
- QAndroidJniObject p;
jobjectArray parcels = parcelUuidArray.object<jobjectArray>();
if (!parcels)
@@ -107,7 +106,7 @@ QList<QBluetoothUuid> ServiceDiscoveryBroadcastReceiver::convertParcelableArray(
jint size = env->GetArrayLength(parcels);
for (int i = 0; i < size; i++) {
- p = env->GetObjectArrayElement(parcels, i);
+ auto p = QAndroidJniObject::fromLocalRef(env->GetObjectArrayElement(parcels, i));
QBluetoothUuid uuid(p.callObjectMethod<jstring>("toString").toString());
//qCDebug(QT_BT_ANDROID) << uuid.toString();
diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro
index a2fd617d..e1e4d7a2 100644
--- a/src/bluetooth/bluetooth.pro
+++ b/src/bluetooth/bluetooth.pro
@@ -162,42 +162,27 @@ qtConfig(bluez) {
include(osx/osxbt.pri)
OBJECTIVE_SOURCES += \
qbluetoothlocaldevice_osx.mm \
- qbluetoothdevicediscoveryagent_osx.mm \
+ qbluetoothdevicediscoveryagent_darwin.mm \
qbluetoothserviceinfo_osx.mm \
qbluetoothservicediscoveryagent_osx.mm \
qbluetoothsocket_osx.mm \
qbluetoothserver_osx.mm \
qbluetoothtransferreply_osx.mm \
- qlowenergycontroller_osx.mm \
- qlowenergyservice_osx.mm
+ qlowenergycontroller_darwin.mm
PRIVATE_HEADERS += qbluetoothsocket_osx_p.h \
- qbluetoothserver_osx_p.h \
qbluetoothtransferreply_osx_p.h \
- qbluetoothtransferreply_osx_p.h \
- qlowenergycontroller_osx_p.h
-
- SOURCES -= qbluetoothdevicediscoveryagent.cpp
- SOURCES -= qbluetoothserviceinfo.cpp
- SOURCES -= qbluetoothservicediscoveryagent.cpp
- SOURCES -= qbluetoothsocket.cpp
- SOURCES -= qbluetoothsocketbase.cpp
- SOURCES -= qbluetoothserver.cpp
- SOURCES -= qlowenergyservice_p.cpp
- SOURCES -= qlowenergyservice.cpp
- SOURCES -= qlowenergycontroller.cpp
- SOURCES -= qlowenergycontrollerbase.cpp
+ qlowenergycontroller_darwin_p.h
} else:ios|tvos {
DEFINES += QT_IOS_BLUETOOTH
LIBS_PRIVATE += -framework Foundation -framework CoreBluetooth
OBJECTIVE_SOURCES += \
- qbluetoothdevicediscoveryagent_ios.mm \
- qlowenergycontroller_osx.mm \
- qlowenergyservice_osx.mm
+ qbluetoothdevicediscoveryagent_darwin.mm \
+ qlowenergycontroller_darwin.mm
PRIVATE_HEADERS += \
- qlowenergycontroller_osx_p.h \
+ qlowenergycontroller_darwin_p.h \
qbluetoothsocket_dummy_p.h
include(osx/osxbt.pri)
@@ -207,11 +192,6 @@ qtConfig(bluez) {
qbluetoothservicediscoveryagent_p.cpp \
qbluetoothsocket_dummy.cpp \
qbluetoothserver_p.cpp
-
- SOURCES -= qbluetoothdevicediscoveryagent.cpp
- SOURCES -= qlowenergyservice.cpp
- SOURCES -= qlowenergycontroller.cpp
- SOURCES -= qlowenergycontrollerbase.cpp
} else: qtConfig(winrt_bt) {
DEFINES += QT_WINRT_BLUETOOTH
!winrt {
@@ -224,7 +204,7 @@ qtConfig(bluez) {
SOURCES += \
qbluetoothdevicediscoveryagent_winrt.cpp \
- qbluetoothlocaldevice_p.cpp \
+ qbluetoothlocaldevice_winrt.cpp \
qbluetoothserver_winrt.cpp \
qbluetoothservicediscoveryagent_winrt.cpp \
qbluetoothserviceinfo_winrt.cpp \
diff --git a/src/bluetooth/doc/qtbluetooth.qdocconf b/src/bluetooth/doc/qtbluetooth.qdocconf
index a994652b..9ee5a567 100644
--- a/src/bluetooth/doc/qtbluetooth.qdocconf
+++ b/src/bluetooth/doc/qtbluetooth.qdocconf
@@ -1,4 +1,5 @@
include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
+include($QT_INSTALL_DOCS/config/exampleurl-qtconnectivity.qdocconf)
project = QtBluetooth
description = Qt Bluetooth Reference Documentation
diff --git a/src/bluetooth/doc/src/bluetooth-index.qdoc b/src/bluetooth/doc/src/bluetooth-index.qdoc
index 2a4f72bc..a0e2a048 100644
--- a/src/bluetooth/doc/src/bluetooth-index.qdoc
+++ b/src/bluetooth/doc/src/bluetooth-index.qdoc
@@ -41,7 +41,7 @@ Currently, the API is supported on the following platforms:
\li \l {Qt for Android}{Android}
\li \l {Qt for iOS}{iOS}
\li \l {Qt for Linux/X11}{Linux (BlueZ 4.x/5.x)}
- \li \l {Qt for OS X}{macOS}
+ \li \l \macos
\li \l {Qt for WinRT}{WinRT}
\li \l {Qt for Windows}{Win32}
\row
diff --git a/src/bluetooth/osx/osxbtchanneldelegate.mm b/src/bluetooth/osx/btdelegates.cpp
index 822e9d4e..531ca1df 100644
--- a/src/bluetooth/osx/osxbtchanneldelegate.mm
+++ b/src/bluetooth/osx/btdelegates.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
@@ -37,16 +37,40 @@
**
****************************************************************************/
-#include "osxbtchanneldelegate_p.h"
+#include "btdelegates_p.h"
+
+#if defined(Q_OS_MACOS)
QT_BEGIN_NAMESPACE
-namespace OSXBluetooth {
+namespace DarwinBluetooth {
+
+DeviceInquiryDelegate::~DeviceInquiryDelegate()
+{
+}
+
+PairingDelegate::~PairingDelegate()
+{
+}
+
+SDPInquiryDelegate::~SDPInquiryDelegate()
+{
+}
ChannelDelegate::~ChannelDelegate()
{
}
+ConnectionMonitor::~ConnectionMonitor()
+{
+}
+
+SocketListener::~SocketListener()
+{
}
+} // namespace DarwinBluetooth
+
QT_END_NAMESPACE
+
+#endif
diff --git a/src/bluetooth/osx/btdelegates_p.h b/src/bluetooth/osx/btdelegates_p.h
new file mode 100644
index 00000000..11fbcc28
--- /dev/null
+++ b/src/bluetooth/osx/btdelegates_p.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BTDELEGATES_P_H
+#define BTDELEGATES_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qbluetoothdevicediscoveryagent.h"
+#include "qlowenergycontroller.h"
+#include "qbluetooth.h"
+
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qglobal.h>
+
+#if defined(Q_OS_MACOS)
+
+#include <IOKit/IOReturn.h>
+
+#include <cstdint>
+
+QT_BEGIN_NAMESPACE
+
+class QLowEnergyServicePrivate;
+class QBluetoothAddress;
+class QByteArray;
+
+namespace DarwinBluetooth {
+
+class DeviceInquiryDelegate
+{
+public:
+ virtual ~DeviceInquiryDelegate();
+
+ virtual void inquiryFinished() = 0;
+ virtual void error(IOReturn error) = 0;
+ virtual void classicDeviceFound(void *ioBluetoothDevice) = 0;
+};
+
+class PairingDelegate
+{
+public:
+ using BluetoothNumericValue = uint32_t;
+ using BluetoothPasskey = BluetoothNumericValue;
+
+ virtual ~PairingDelegate();
+
+ virtual void connecting(void *pair) = 0;
+ virtual void requestPIN(void *pair) = 0;
+ virtual void requestUserConfirmation(void *pair,
+ BluetoothNumericValue) = 0;
+ virtual void passkeyNotification(void *pair,
+ BluetoothPasskey passkey) = 0;
+ virtual void error(void *pair, IOReturn errorCode) = 0;
+ virtual void pairingFinished(void *pair) = 0;
+};
+
+class SDPInquiryDelegate {
+public:
+ virtual ~SDPInquiryDelegate();
+
+ virtual void SDPInquiryFinished(void *ioBluetoothDevice) = 0;
+ virtual void SDPInquiryError(void *ioBluetoothDevice, IOReturn errorCode) = 0;
+};
+
+// L2CAP and RFCOMM.
+class ChannelDelegate
+{
+public:
+ virtual ~ChannelDelegate();
+
+ virtual void setChannelError(IOReturn errorCode) = 0;
+ virtual void channelOpenComplete() = 0;
+ virtual void channelClosed() = 0;
+
+ virtual void readChannelData(void *data, std::size_t size) = 0;
+ virtual void writeComplete() = 0;
+};
+
+class ConnectionMonitor {
+public:
+ virtual ~ConnectionMonitor();
+
+ virtual void deviceConnected(const QBluetoothAddress &address) = 0;
+ virtual void deviceDisconnected(const QBluetoothAddress &address) = 0;
+};
+
+class SocketListener
+{
+public:
+ virtual ~SocketListener();
+
+ virtual void openNotifyRFCOMM(void *rfcommChannel) = 0;
+ virtual void openNotifyL2CAP(void *l2capChannel) = 0;
+};
+
+
+} // namespace DarwinBluetooth
+
+QT_END_NAMESPACE
+
+#endif // Q_OS_MACOS
+
+#endif // DARWINBTDELEGATES_P_H
diff --git a/src/bluetooth/osx/osxbtchanneldelegate_p.h b/src/bluetooth/osx/btraii.mm
index 1102e935..a1bf2a8d 100644
--- a/src/bluetooth/osx/osxbtchanneldelegate_p.h
+++ b/src/bluetooth/osx/btraii.mm
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
@@ -37,43 +37,74 @@
**
****************************************************************************/
-#ifndef OSXBTCHANNELDELEGATE_P_H
-#define OSXBTCHANNELDELEGATE_P_H
+#include "btraii_p.h"
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
+#include <qdebug.h>
-#include <QtCore/qglobal.h>
+#include <Foundation/Foundation.h>
-#include <IOKit/IOReturn.h>
+#include <utility>
QT_BEGIN_NAMESPACE
-namespace OSXBluetooth {
+namespace DarwinBluetooth {
-class ChannelDelegate
+StrongReference::StrongReference(void *object, RetainPolicy policy)
+ : objCInstance(object)
{
-public:
- virtual ~ChannelDelegate();
+ if (policy == RetainPolicy::doInitialRetain)
+ objCInstance = [getAs<NSObject>() retain];
+}
- virtual void setChannelError(IOReturn errorCode) = 0;
- virtual void channelOpenComplete() = 0;
- virtual void channelClosed() = 0;
+StrongReference::StrongReference(const StrongReference &other)
+{
+ objCInstance = [other.getAs<NSObject>() retain];
+}
- virtual void readChannelData(void *data, std::size_t size) = 0;
- virtual void writeComplete() = 0;
-};
+StrongReference::StrongReference(StrongReference &&other)
+{
+ std::swap(objCInstance, other.objCInstance);
+}
+StrongReference::~StrongReference()
+{
+ [getAs<NSObject>() release];
}
-QT_END_NAMESPACE
+StrongReference &StrongReference::operator = (const StrongReference &other) noexcept
+{
+ if (this != &other) {
+ [getAs<NSObject>() release];
+ objCInstance = [other.getAs<NSObject>() retain];
+ }
+
+ return *this;
+}
+
+StrongReference &StrongReference::operator = (StrongReference &&other) noexcept
+{
+ swap(other);
+ return *this;
+}
+
+void StrongReference::reset()
+{
+ [getAs<NSObject>() release];
+ objCInstance = nullptr;
+}
-#endif
+void StrongReference::reset(void *obj, RetainPolicy policy)
+{
+ [getAs<NSObject>() release];
+ objCInstance = obj;
+
+ if (policy == RetainPolicy::doInitialRetain) {
+ auto newInstance = static_cast<NSObject *>(obj);
+ Q_ASSERT(newInstance);
+ objCInstance = [newInstance retain];
+ }
+}
+
+} // namespace DarwinBluetooth
+
+QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothserver_osx_p.h b/src/bluetooth/osx/btraii_p.h
index 3116ca02..6053d63b 100644
--- a/src/bluetooth/qbluetoothserver_osx_p.h
+++ b/src/bluetooth/osx/btraii_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QBLUETOOTHSERVER_OSX_P_H
-#define QBLUETOOTHSERVER_OSX_P_H
+#ifndef BTRAII_P_H
+#define BTRAII_P_H
//
// W A R N I N G
@@ -51,77 +51,86 @@
// We mean it.
//
-#ifdef QT_OSX_BLUETOOTH
-
-#include "osx/osxbtsocketlistener_p.h"
-#include "qbluetoothserviceinfo.h"
-#include "osx/osxbtutility_p.h"
-#include "qbluetoothserver.h"
-
#include <QtCore/qglobal.h>
-#include <QtCore/qlist.h>
+
+#include <utility>
QT_BEGIN_NAMESPACE
-class QMutex;
+namespace DarwinBluetooth {
-class QBluetoothServerPrivate : public OSXBluetooth::SocketListener
+enum class RetainPolicy
{
- friend class QBluetoothServer;
- friend class QBluetoothServiceInfoPrivate;
+ noInitialRetain,
+ doInitialRetain
+};
+// The class StrongReference and its descendant ScopedGuard
+// are RAII classes dealing with raw pointers to NSObject class
+// and its descendants (and thus hiding Objective-C's retain/
+// release semantics). The header itself is meant to be included
+// into *.cpp files so it's a pure C++ code without any Objective-C
+// syntax. Thus it's a bit clunky - the type information is 'erased'
+// and has to be enforced by the code using these smart pointers.
+// That's because these types are Objective-C classes - thus require
+// Objective-C compiler to work. Member-function template 'getAs' is
+// a convenience shortcut giving the desired pointer type in
+// Objective-C++ files (*.mm).
+
+// TODO: on top of these classes I can build ObjCStrongReference (it's
+// now inside osxbtutils_p.h, a template class that does have type
+// information needed but works only in Objective-C++ environment.
+class StrongReference
+{
public:
- QBluetoothServerPrivate(QBluetoothServiceInfo::Protocol type, QBluetoothServer *q);
- ~QBluetoothServerPrivate();
-
- void _q_newConnection();
-private:
- bool startListener(quint16 realPort);
- void stopListener();
-
- // SocketListener (delegate):
- void openNotify(IOBluetoothRFCOMMChannel *channel) override;
- void openNotify(IOBluetoothL2CAPChannel *channel) override;
+ StrongReference() = default;
+ StrongReference(void *object, RetainPolicy policy);
+ StrongReference(const StrongReference &other);
+ StrongReference(StrongReference &&other);
- QBluetoothServiceInfo::Protocol serverType;
- QBluetoothServer *q_ptr;
- QBluetoothServer::Error lastError;
+ ~StrongReference();
- // Either a "temporary" channelID/PSM assigned by QBluetoothServer::listen,
- // or a real channelID/PSM returned by IOBluetooth after we've registered
- // a service.
- quint16 port;
+ StrongReference &operator = (const StrongReference &other) noexcept;
+ StrongReference &operator = (StrongReference &&other) noexcept;
- typedef OSXBluetooth::ObjCScopedPointer<ObjCListener> Listener;
- Listener listener;
+ void swap(StrongReference &other) noexcept
+ {
+ std::swap(objCInstance, other.objCInstance);
+ }
- int maxPendingConnections;
+ void reset();
+ void reset(void *newInstance, RetainPolicy policy);
- // These static functions below
- // deal with differences between bluetooth sockets
- // (bluez and QtBluetooth's API) and IOBluetooth, where it's not possible
- // to have a real PSM/channelID _before_ a service is registered,
- // the solution - "fake" ports.
- // These functions require external locking - using channelMapMutex.
- static QMutex &channelMapMutex();
+ template<class ObjCType>
+ ObjCType *getAs() const
+ {
+ return static_cast<ObjCType *>(objCInstance);
+ }
- static bool channelIsBusy(quint16 channelID);
- static quint16 findFreeChannel();
+ operator bool() const
+ {
+ return !!objCInstance;
+ }
- static bool psmIsBusy(quint16 psm);
- static quint16 findFreePSM();
-
- static void registerServer(QBluetoothServerPrivate *server, quint16 port);
- static QBluetoothServerPrivate *registeredServer(quint16 port, QBluetoothServiceInfo::Protocol protocol);
- static void unregisterServer(QBluetoothServerPrivate *server);
+private:
+ void *objCInstance = nullptr;
+};
- typedef OSXBluetooth::ObjCStrongReference<NSObject> PendingConnection;
- QList<PendingConnection> pendingConnections;
+class ScopedPointer final : public StrongReference
+{
+public:
+ ScopedPointer() = default;
+ ScopedPointer(void *instance, RetainPolicy policy)
+ : StrongReference(instance, policy)
+ {
+ }
+private:
+ Q_DISABLE_COPY_MOVE(ScopedPointer)
};
-QT_END_NAMESPACE
+} // namespace DarwinBluetooth
-#endif //QT_OSX_BLUETOOTH
+QT_END_NAMESPACE
-#endif
+#endif // BTRAII_P_H
diff --git a/src/bluetooth/osx/osxbt.pri b/src/bluetooth/osx/osxbt.pri
index b7ac0535..8f6ea0d1 100644
--- a/src/bluetooth/osx/osxbt.pri
+++ b/src/bluetooth/osx/osxbt.pri
@@ -1,8 +1,15 @@
-SOURCES += osx/uistrings.cpp osx/osxbtnotifier.cpp
+SOURCES += osx/uistrings.cpp \
+ osx/osxbtnotifier.cpp \
+ osx/btdelegates.cpp
+
PRIVATE_HEADERS += osx/uistrings_p.h \
- osx/osxbtgcdtimer_p.h
+ osx/osxbtgcdtimer_p.h \
+ osx/btraii_p.h \
+ osx/btdelegates_p.h
+
-OBJECTIVE_SOURCES += osx/osxbtgcdtimer.mm
+OBJECTIVE_SOURCES += osx/osxbtgcdtimer.mm \
+ osx/btraii.mm
#QMAKE_CXXFLAGS_WARN_ON += -Wno-nullability-completeness
CONFIG(osx) {
@@ -13,7 +20,6 @@ CONFIG(osx) {
osx/osxbtsdpinquiry_p.h \
osx/osxbtrfcommchannel_p.h \
osx/osxbtl2capchannel_p.h \
- osx/osxbtchanneldelegate_p.h \
osx/osxbtservicerecord_p.h \
osx/osxbtsocketlistener_p.h \
osx/osxbtobexsession_p.h \
@@ -30,7 +36,6 @@ CONFIG(osx) {
osx/osxbtsdpinquiry.mm \
osx/osxbtrfcommchannel.mm \
osx/osxbtl2capchannel.mm \
- osx/osxbtchanneldelegate.mm \
osx/osxbtservicerecord.mm \
osx/osxbtsocketlistener.mm \
osx/osxbtobexsession.mm \
diff --git a/src/bluetooth/osx/osxbtcentralmanager.mm b/src/bluetooth/osx/osxbtcentralmanager.mm
index cadabbaf..b9a1ae0f 100644
--- a/src/bluetooth/osx/osxbtcentralmanager.mm
+++ b/src/bluetooth/osx/osxbtcentralmanager.mm
@@ -39,6 +39,7 @@
#include "qlowenergyserviceprivate_p.h"
#include "qlowenergycharacteristic.h"
+#include "qlowenergycontroller.h"
#include "osxbtcentralmanager_p.h"
#include "osxbtnotifier_p.h"
@@ -132,6 +133,7 @@ QT_USE_NAMESPACE
- (CBDescriptor *)descriptor:(const QBluetoothUuid &)dUuid
forCharacteristic:(CBCharacteristic *)ch;
- (bool)cacheWriteValue:(const QByteArray &)value for:(NSObject *)obj;
+- (void)handleReadWriteError:(NSError *)error;
- (void)reset;
@end
@@ -1202,6 +1204,21 @@ QT_USE_NAMESPACE
// TODO: also serviceToVisit/VisitNext and visitedServices ?
}
+- (void)handleReadWriteError:(NSError *)error
+{
+ Q_ASSERT(notifier);
+
+ switch (error.code) {
+ case 0x05: // GATT_INSUFFICIENT_AUTHORIZATION
+ case 0x0F: // GATT_INSUFFICIENT_ENCRYPTION
+ emit notifier->CBManagerError(QLowEnergyController::AuthorizationError);
+ [self detach];
+ break;
+ default:
+ break;
+ }
+}
+
// CBCentralManagerDelegate (the real one).
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
@@ -1245,6 +1262,7 @@ QT_USE_NAMESPACE
if (notifier)
emit notifier->CBManagerError(QLowEnergyController::InvalidBluetoothAdapterError);
}
+ [self stopWatchers];
return;
}
@@ -1266,6 +1284,7 @@ QT_USE_NAMESPACE
if (notifier)
emit notifier->CBManagerError(QLowEnergyController::InvalidBluetoothAdapterError);
}
+ [self stopWatchers];
return;
}
@@ -1280,7 +1299,7 @@ QT_USE_NAMESPACE
}
} else {
// We actually handled all known states, but .. Core Bluetooth can change?
- Q_ASSERT_X(0, Q_FUNC_INFO, "invalid centra's state");
+ Q_ASSERT_X(0, Q_FUNC_INFO, "invalid central's state");
}
#pragma clang diagnostic pop
@@ -1371,6 +1390,30 @@ QT_USE_NAMESPACE
[self discoverIncludedServices];
}
+- (void)peripheral:(CBPeripheral *)aPeripheral
+ didModifyServices:(NSArray<CBService *> *)invalidatedServices
+{
+ Q_UNUSED(aPeripheral)
+ Q_UNUSED(invalidatedServices)
+
+ qCWarning(QT_BT_OSX) << "The peripheral has modified its services.";
+ // "This method is invoked whenever one or more services of a peripheral have changed.
+ // A peripheral’s services have changed if:
+ // * A service is removed from the peripheral’s database
+ // * A new service is added to the peripheral’s database
+ // * A service that was previously removed from the peripheral’s
+ // database is readded to the database at a different location"
+
+ // In case new services were added - we have to discover them.
+ // In case some were removed - we can end up with dangling pointers
+ // (see our 'watchdogs', for example). To handle the situation
+ // we stop all current operations here, report to QLowEnergyController
+ // so that it can trigger re-discovery.
+ [self reset];
+ managerState = OSXBluetooth::CentralManagerIdle;
+ if (notifier)
+ emit notifier->servicesWereModified();
+}
- (void)peripheral:(CBPeripheral *)aPeripheral didDiscoverIncludedServicesForService:(CBService *)service
error:(NSError *)error
@@ -1514,6 +1557,7 @@ QT_USE_NAMESPACE
currentReadHandle = 0;
requestPending = false;
emit notifier->CBManagerError(qtUuid, QLowEnergyService::CharacteristicReadError);
+ [self handleReadWriteError:error];
[self performNextRequest];
}
return;
@@ -1632,6 +1676,7 @@ QT_USE_NAMESPACE
currentReadHandle = 0;
requestPending = false;
emit notifier->CBManagerError(qtUuid, QLowEnergyService::DescriptorReadError);
+ [self handleReadWriteError:error];
[self performNextRequest];
}
return;
@@ -1721,6 +1766,7 @@ QT_USE_NAMESPACE
NSLog(@"%s failed with error %@", Q_FUNC_INFO, error);
emit notifier->CBManagerError(qt_uuid(characteristic.service.UUID),
QLowEnergyService::CharacteristicWriteError);
+ [self handleReadWriteError:error];
} else {
const QLowEnergyHandle cHandle = charMap.key(characteristic);
emit notifier->characteristicWritten(cHandle, valueToReport);
@@ -1755,6 +1801,7 @@ QT_USE_NAMESPACE
NSLog(@"%s failed with error %@", Q_FUNC_INFO, error);
emit notifier->CBManagerError(qt_uuid(descriptor.characteristic.service.UUID),
QLowEnergyService::DescriptorWriteError);
+ [self handleReadWriteError:error];
} else {
const QLowEnergyHandle dHandle = descMap.key(descriptor);
Q_ASSERT_X(dHandle, Q_FUNC_INFO, "descriptor not found in the descriptors map");
diff --git a/src/bluetooth/osx/osxbtdeviceinquiry.mm b/src/bluetooth/osx/osxbtdeviceinquiry.mm
index 57cd73e1..3a77c1f7 100644
--- a/src/bluetooth/osx/osxbtdeviceinquiry.mm
+++ b/src/bluetooth/osx/osxbtdeviceinquiry.mm
@@ -43,30 +43,16 @@
#include <QtCore/qloggingcategory.h>
#include <QtCore/qdebug.h>
-QT_BEGIN_NAMESPACE
-
-namespace OSXBluetooth {
-
-DeviceInquiryDelegate::~DeviceInquiryDelegate()
-{
-}
-
-}
-
-
-QT_END_NAMESPACE
-
QT_USE_NAMESPACE
-
@implementation QT_MANGLE_NAMESPACE(OSXBTDeviceInquiry)
{
IOBluetoothDeviceInquiry *m_inquiry;
bool m_active;
- QT_PREPEND_NAMESPACE(OSXBluetooth::DeviceInquiryDelegate) *m_delegate;//C++ "delegate"
+ DarwinBluetooth::DeviceInquiryDelegate *m_delegate;//C++ "delegate"
}
-- (id)initWithDelegate:(OSXBluetooth::DeviceInquiryDelegate *)delegate
+- (id)initWithDelegate:(DarwinBluetooth::DeviceInquiryDelegate *)delegate
{
if (self = [super init]) {
Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid device inquiry delegate (null)");
@@ -158,9 +144,9 @@ QT_USE_NAMESPACE
// QtBluetooth has not too many error codes, 'UnknownError' is not really
// useful, report the actual error code here:
qCWarning(QT_BT_OSX) << "IOKit error code: " << error;
- m_delegate->error(sender, error);
+ m_delegate->error(error);
} else {
- m_delegate->inquiryFinished(sender);
+ m_delegate->inquiryFinished();
}
}
@@ -171,7 +157,7 @@ QT_USE_NAMESPACE
return;
Q_ASSERT_X(m_delegate, Q_FUNC_INFO, "invalid device inquiry delegate (null)");
- m_delegate->deviceFound(sender, device);
+ m_delegate->classicDeviceFound(device);
}
- (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry *)sender
diff --git a/src/bluetooth/osx/osxbtdeviceinquiry_p.h b/src/bluetooth/osx/osxbtdeviceinquiry_p.h
index 0fec2db2..86ed3fdf 100644
--- a/src/bluetooth/osx/osxbtdeviceinquiry_p.h
+++ b/src/bluetooth/osx/osxbtdeviceinquiry_p.h
@@ -52,36 +52,16 @@
//
#include "osxbluetooth_p.h"
+#include "btdelegates_p.h"
#include <QtCore/qglobal.h>
#include <Foundation/Foundation.h>
#include <IOKit/IOReturn.h>
-@class QT_MANGLE_NAMESPACE(OSXBTDeviceInquiry);
-
-QT_BEGIN_NAMESPACE
-
-namespace OSXBluetooth {
-
-class DeviceInquiryDelegate {
-public:
- typedef QT_MANGLE_NAMESPACE(OSXBTDeviceInquiry) DeviceInquiryObjC;
-
- virtual ~DeviceInquiryDelegate();
-
- virtual void inquiryFinished(IOBluetoothDeviceInquiry *inq) = 0;
- virtual void error(IOBluetoothDeviceInquiry *inq, IOReturn error) = 0;
- virtual void deviceFound(IOBluetoothDeviceInquiry *inq, IOBluetoothDevice *device) = 0;
-};
-
-}
-
-QT_END_NAMESPACE
-
@interface QT_MANGLE_NAMESPACE(OSXBTDeviceInquiry) : NSObject<IOBluetoothDeviceInquiryDelegate>
-- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth::DeviceInquiryDelegate) *)delegate;
+- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth::DeviceInquiryDelegate) *)delegate;
- (void)dealloc;
- (bool)isActive;
diff --git a/src/bluetooth/osx/osxbtl2capchannel.mm b/src/bluetooth/osx/osxbtl2capchannel.mm
index dc8468a0..03e3a982 100644
--- a/src/bluetooth/osx/osxbtl2capchannel.mm
+++ b/src/bluetooth/osx/osxbtl2capchannel.mm
@@ -37,10 +37,10 @@
**
****************************************************************************/
-#include "osxbtchanneldelegate_p.h"
#include "osxbtl2capchannel_p.h"
#include "qbluetoothaddress.h"
#include "osxbtutility_p.h"
+#include "btdelegates_p.h"
#include <QtCore/qloggingcategory.h>
#include <QtCore/qdebug.h>
@@ -49,13 +49,13 @@ QT_USE_NAMESPACE
@implementation QT_MANGLE_NAMESPACE(OSXBTL2CAPChannel)
{
- QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *delegate;
+ QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *delegate;
IOBluetoothDevice *device;
IOBluetoothL2CAPChannel *channel;
bool connected;
}
-- (id)initWithDelegate:(OSXBluetooth::ChannelDelegate *)aDelegate
+- (id)initWithDelegate:(DarwinBluetooth::ChannelDelegate *)aDelegate
{
Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)");
@@ -69,7 +69,7 @@ QT_USE_NAMESPACE
return self;
}
-- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth::ChannelDelegate) *)aDelegate
+- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth::ChannelDelegate) *)aDelegate
channel:(IOBluetoothL2CAPChannel *)aChannel
{
// This type of channel does not require connect, it's created with
diff --git a/src/bluetooth/osx/osxbtl2capchannel_p.h b/src/bluetooth/osx/osxbtl2capchannel_p.h
index 512087b4..42eec8e7 100644
--- a/src/bluetooth/osx/osxbtl2capchannel_p.h
+++ b/src/bluetooth/osx/osxbtl2capchannel_p.h
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
class QBluetoothAddress;
-namespace OSXBluetooth {
+namespace DarwinBluetooth {
class ChannelDelegate;
@@ -73,8 +73,8 @@ QT_END_NAMESPACE
@interface QT_MANGLE_NAMESPACE(OSXBTL2CAPChannel) : NSObject<IOBluetoothL2CAPChannelDelegate>
-- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *)aDelegate;
-- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *)aDelegate
+- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *)aDelegate;
+- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *)aDelegate
channel:(IOBluetoothL2CAPChannel *)aChannel;
- (void)dealloc;
diff --git a/src/bluetooth/osx/osxbtledeviceinquiry.mm b/src/bluetooth/osx/osxbtledeviceinquiry.mm
index c56b6da3..70b96ab7 100644
--- a/src/bluetooth/osx/osxbtledeviceinquiry.mm
+++ b/src/bluetooth/osx/osxbtledeviceinquiry.mm
@@ -121,6 +121,11 @@ QT_END_NAMESPACE
QT_USE_NAMESPACE
+@interface QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry)(PrivateAPI)
+- (void)stopScanSafe;
+- (void)stopNotifier;
+@end
+
@implementation QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry)
{
LECBManagerNotifier *notifier;
@@ -147,17 +152,10 @@ QT_USE_NAMESPACE
- (void)dealloc
{
- if (manager) {
- [manager setDelegate:nil];
- if (internalState == InquiryActive)
- [manager stopScan];
- }
-
- if (notifier) {
- notifier->disconnect();
- notifier->deleteLater();
- }
-
+ [self stopScanSafe];
+ [manager setDelegate:nil];
+ [elapsedTimer cancelTimer];
+ [self stopNotifier];
[super dealloc];
}
@@ -166,7 +164,7 @@ QT_USE_NAMESPACE
Q_UNUSED(sender)
if (internalState == InquiryActive) {
- [manager stopScan];
+ [self stopScanSafe];
[manager setDelegate:nil];
internalState = InquiryFinished;
Q_ASSERT(notifier);
@@ -228,7 +226,7 @@ QT_USE_NAMESPACE
} else if (state == CBCentralManagerStateUnsupported || state == CBCentralManagerStateUnauthorized) {
#endif
if (internalState == InquiryActive) {
- [manager stopScan];
+ [self stopScanSafe];
// Not sure how this is possible at all,
// probably, can never happen.
internalState = ErrorPoweredOff;
@@ -244,8 +242,9 @@ QT_USE_NAMESPACE
#else
} else if (state == CBCentralManagerStatePoweredOff) {
#endif
+
+#ifndef Q_OS_MACOS
if (internalState == InquiryStarting) {
-#ifndef Q_OS_OSX
// On iOS a user can see at this point an alert asking to
// enable Bluetooth in the "Settings" app. If a user does so,
// we'll receive 'PoweredOn' state update later.
@@ -254,17 +253,19 @@ QT_USE_NAMESPACE
elapsedTimer.resetWithoutRetain([[GCDTimerObjC alloc] initWithDelegate:self]);
[elapsedTimer startWithTimeout:powerOffTimeoutMS step:300];
return;
+ }
#else
Q_UNUSED(powerOffTimeoutMS)
-#endif
- internalState = ErrorPoweredOff;
- emit notifier->CBManagerError(QBluetoothDeviceDiscoveryAgent::PoweredOffError);
- } else {
- [manager stopScan];
- emit notifier->CBManagerError(QBluetoothDeviceDiscoveryAgent::PoweredOffError);
- }
-
+#endif // Q_OS_MACOS
+ [elapsedTimer cancelTimer];
+ [self stopScanSafe];
[manager setDelegate:nil];
+ internalState = ErrorPoweredOff;
+ // On macOS we report PoweredOffError and our C++ owner will delete us
+ // (here we're kwnon as 'self'). Connection is Qt::QueuedConnection so we
+ // are apparently safe to call -stopNotifier after the signal.
+ emit notifier->CBManagerError(QBluetoothDeviceDiscoveryAgent::PoweredOffError);
+ [self stopNotifier];
} else {
// The following two states we ignore (from Apple's docs):
//"
@@ -281,19 +282,45 @@ QT_USE_NAMESPACE
#pragma clang diagnostic pop
}
-- (void)stop
+- (void)stopScanSafe
{
- if (internalState == InquiryActive)
- [manager stopScan];
+ // CoreBluetooth warns about API misused if we call stopScan in a state
+ // other than powered on. Hence this 'Safe' ...
+ if (!manager)
+ return;
- [elapsedTimer cancelTimer];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability-new"
+
+ if (internalState == InquiryActive) {
+ const auto state = manager.data().state;
+ #if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0) || QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13)
+ if (state == CBManagerStatePoweredOn)
+ #else
+ if (state == CBCentralManagerStatePoweredOn)
+ #endif
+ [manager stopScan];
+ }
+
+#pragma clang diagnostic pop
+}
+
+- (void)stopNotifier
+{
+ if (notifier) {
+ notifier->disconnect();
+ notifier->deleteLater();
+ notifier = nullptr;
+ }
+}
+- (void)stop
+{
+ [self stopScanSafe];
[manager setDelegate:nil];
+ [elapsedTimer cancelTimer];
+ [self stopNotifier];
internalState = InquiryCancelled;
-
- notifier->disconnect();
- notifier->deleteLater();
- notifier = nullptr;
}
- (void)centralManager:(CBCentralManager *)central
diff --git a/src/bluetooth/osx/osxbtnotifier_p.h b/src/bluetooth/osx/osxbtnotifier_p.h
index 47ee6ba1..397214d0 100644
--- a/src/bluetooth/osx/osxbtnotifier_p.h
+++ b/src/bluetooth/osx/osxbtnotifier_p.h
@@ -89,13 +89,13 @@ Q_SIGNALS:
void descriptorRead(QLowEnergyHandle descHandle, const QByteArray &value);
void descriptorWritten(QLowEnergyHandle descHandle, const QByteArray &value);
void notificationEnabled(QLowEnergyHandle charHandle, bool enabled);
+ void servicesWereModified();
void LEnotSupported();
void CBManagerError(QBluetoothDeviceDiscoveryAgent::Error error);
void CBManagerError(QLowEnergyController::Error error);
void CBManagerError(const QBluetoothUuid &serviceUuid, QLowEnergyController::Error error);
void CBManagerError(const QBluetoothUuid &serviceUuid, QLowEnergyService::ServiceError error);
-
};
}
diff --git a/src/bluetooth/osx/osxbtperipheralmanager.mm b/src/bluetooth/osx/osxbtperipheralmanager.mm
index 1998340a..39f9808c 100644
--- a/src/bluetooth/osx/osxbtperipheralmanager.mm
+++ b/src/bluetooth/osx/osxbtperipheralmanager.mm
@@ -340,7 +340,7 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data)
- (void)startAdvertising
{
state = PeripheralState::waitingForPowerOn;
- if (manager)
+ if (manager.data())
[manager setDelegate:nil];
manager.reset([[CBPeripheralManager alloc] initWithDelegate:self
queue:OSXBluetooth::qt_LE_queue()]);
@@ -405,7 +405,7 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data)
- (void) addServicesToPeripheral
{
- Q_ASSERT(manager);
+ Q_ASSERT(manager.data());
if (nextServiceToAdd < services.size())
[manager addService:services[nextServiceToAdd++]];
diff --git a/src/bluetooth/osx/osxbtrfcommchannel.mm b/src/bluetooth/osx/osxbtrfcommchannel.mm
index 00b67ee0..d2d3e2f8 100644
--- a/src/bluetooth/osx/osxbtrfcommchannel.mm
+++ b/src/bluetooth/osx/osxbtrfcommchannel.mm
@@ -37,22 +37,22 @@
**
****************************************************************************/
-#include "osxbtchanneldelegate_p.h"
#include "osxbtrfcommchannel_p.h"
#include "qbluetoothaddress.h"
#include "osxbtutility_p.h"
+#include "btdelegates_p.h"
QT_USE_NAMESPACE
@implementation QT_MANGLE_NAMESPACE(OSXBTRFCOMMChannel)
{
- QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *delegate;
+ QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *delegate;
IOBluetoothDevice *device;
IOBluetoothRFCOMMChannel *channel;
bool connected;
}
-- (id)initWithDelegate:(OSXBluetooth::ChannelDelegate *)aDelegate
+- (id)initWithDelegate:(DarwinBluetooth::ChannelDelegate *)aDelegate
{
Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)");
@@ -66,7 +66,7 @@ QT_USE_NAMESPACE
return self;
}
-- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth::ChannelDelegate) *)aDelegate
+- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth::ChannelDelegate) *)aDelegate
channel:(IOBluetoothRFCOMMChannel *)aChannel
{
// This type of channel does not require connect, it's created with
diff --git a/src/bluetooth/osx/osxbtrfcommchannel_p.h b/src/bluetooth/osx/osxbtrfcommchannel_p.h
index 775999ed..44416cce 100644
--- a/src/bluetooth/osx/osxbtrfcommchannel_p.h
+++ b/src/bluetooth/osx/osxbtrfcommchannel_p.h
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
class QBluetoothAddress;
-namespace OSXBluetooth {
+namespace DarwinBluetooth {
class ChannelDelegate;
@@ -73,8 +73,8 @@ QT_END_NAMESPACE
@interface QT_MANGLE_NAMESPACE(OSXBTRFCOMMChannel) : NSObject<IOBluetoothRFCOMMChannelDelegate>
-- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *)aDelegate;
-- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *)aDelegate
+- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *)aDelegate;
+- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *)aDelegate
channel:(IOBluetoothRFCOMMChannel *)aChannel;
- (void)dealloc;
diff --git a/src/bluetooth/osx/osxbtsdpinquiry.mm b/src/bluetooth/osx/osxbtsdpinquiry.mm
index a7bdc2c4..a2b02b1a 100644
--- a/src/bluetooth/osx/osxbtsdpinquiry.mm
+++ b/src/bluetooth/osx/osxbtsdpinquiry.mm
@@ -41,6 +41,7 @@
#include "osxbtsdpinquiry_p.h"
#include "qbluetoothuuid.h"
#include "osxbtutility_p.h"
+#include "btdelegates_p.h"
#include <QtCore/qvariant.h>
#include <QtCore/qstring.h>
@@ -49,10 +50,6 @@ QT_BEGIN_NAMESPACE
namespace OSXBluetooth {
-SDPInquiryDelegate::~SDPInquiryDelegate()
-{
-}
-
namespace {
QBluetoothUuid sdp_element_to_uuid(IOBluetoothSDPDataElement *element)
@@ -213,12 +210,12 @@ using namespace OSXBluetooth;
@implementation QT_MANGLE_NAMESPACE(OSXBTSDPInquiry)
{
- QT_PREPEND_NAMESPACE(OSXBluetooth::SDPInquiryDelegate) *delegate;
+ QT_PREPEND_NAMESPACE(DarwinBluetooth::SDPInquiryDelegate) *delegate;
IOBluetoothDevice *device;
bool isActive;
}
-- (id)initWithDelegate:(SDPInquiryDelegate *)aDelegate
+- (id)initWithDelegate:(DarwinBluetooth::SDPInquiryDelegate *)aDelegate
{
Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)");
diff --git a/src/bluetooth/osx/osxbtsdpinquiry_p.h b/src/bluetooth/osx/osxbtsdpinquiry_p.h
index dd38a28b..e2658670 100644
--- a/src/bluetooth/osx/osxbtsdpinquiry_p.h
+++ b/src/bluetooth/osx/osxbtsdpinquiry_p.h
@@ -68,17 +68,13 @@ QT_BEGIN_NAMESPACE
class QBluetoothServiceInfo;
class QVariant;
-namespace OSXBluetooth {
+namespace DarwinBluetooth {
-class SDPInquiryDelegate {
-public:
- typedef QT_MANGLE_NAMESPACE(OSXBTSDPInquiry) ObjCServiceInquiry;
+class SDPInquiryDelegate;
- virtual ~SDPInquiryDelegate();
+}
- virtual void SDPInquiryFinished(IOBluetoothDevice *device) = 0;
- virtual void SDPInquiryError(IOBluetoothDevice *device, IOReturn errorCode) = 0;
-};
+namespace OSXBluetooth {
void extract_service_record(IOBluetoothSDPServiceRecord *record, QBluetoothServiceInfo &serviceInfo);
QVariant extract_attribute_value(IOBluetoothSDPDataElement *dataElement);
@@ -90,7 +86,7 @@ QT_END_NAMESPACE
@interface QT_MANGLE_NAMESPACE(OSXBTSDPInquiry) : NSObject
-- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth::SDPInquiryDelegate) *)aDelegate;
+- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth::SDPInquiryDelegate) *)aDelegate;
- (void)dealloc;
- (IOReturn)performSDPQueryWithDevice:(const QBluetoothAddress &)address;
diff --git a/src/bluetooth/osx/osxbtsocketlistener.mm b/src/bluetooth/osx/osxbtsocketlistener.mm
index 517b7f2d..10526b0f 100644
--- a/src/bluetooth/osx/osxbtsocketlistener.mm
+++ b/src/bluetooth/osx/osxbtsocketlistener.mm
@@ -39,31 +39,20 @@
#include "osxbtsocketlistener_p.h"
#include "osxbtutility_p.h"
+#include "btdelegates_p.h"
#include <QtCore/qdebug.h>
-QT_BEGIN_NAMESPACE
-
-namespace OSXBluetooth {
-
-SocketListener::~SocketListener()
-{
-}
-
-}
-
-QT_END_NAMESPACE
-
QT_USE_NAMESPACE
@implementation QT_MANGLE_NAMESPACE(OSXBTSocketListener)
{
IOBluetoothUserNotification *connectionNotification;
- QT_PREPEND_NAMESPACE(OSXBluetooth::SocketListener) *delegate;
+ QT_PREPEND_NAMESPACE(DarwinBluetooth::SocketListener) *delegate;
quint16 port;
}
-- (id)initWithListener:(OSXBluetooth::SocketListener *)aDelegate
+- (id)initWithListener:(DarwinBluetooth::SocketListener *)aDelegate
{
Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)");
if (self = [super init]) {
@@ -119,7 +108,7 @@ QT_USE_NAMESPACE
Q_UNUSED(notification)
Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
- delegate->openNotify(newChannel);
+ delegate->openNotifyRFCOMM(newChannel);
}
- (void)l2capOpenNotification:(IOBluetoothUserNotification *)notification
@@ -128,7 +117,7 @@ QT_USE_NAMESPACE
Q_UNUSED(notification)
Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
- delegate->openNotify(newChannel);
+ delegate->openNotifyL2CAP(newChannel);
}
- (quint16)port
diff --git a/src/bluetooth/osx/osxbtsocketlistener_p.h b/src/bluetooth/osx/osxbtsocketlistener_p.h
index cac0b7c4..3bbce24e 100644
--- a/src/bluetooth/osx/osxbtsocketlistener_p.h
+++ b/src/bluetooth/osx/osxbtsocketlistener_p.h
@@ -57,22 +57,15 @@
#include <Foundation/Foundation.h>
+// TODO: use the special macros we have to create an
+// alias for a mangled name.
@class QT_MANGLE_NAMESPACE(OSXBTSocketListener);
QT_BEGIN_NAMESPACE
-namespace OSXBluetooth {
+namespace DarwinBluetooth {
-class SocketListener
-{
-public:
- typedef QT_MANGLE_NAMESPACE(OSXBTSocketListener) ObjCListener;
-
- virtual ~SocketListener();
-
- virtual void openNotify(IOBluetoothRFCOMMChannel *channel) = 0;
- virtual void openNotify(IOBluetoothL2CAPChannel *channel) = 0;
-};
+class SocketListener;
}
@@ -83,7 +76,7 @@ QT_END_NAMESPACE
@interface QT_MANGLE_NAMESPACE(OSXBTSocketListener) : NSObject
-- (id)initWithListener:(QT_PREPEND_NAMESPACE(OSXBluetooth::SocketListener) *)aDelegate;
+- (id)initWithListener:(QT_PREPEND_NAMESPACE(DarwinBluetooth::SocketListener) *)aDelegate;
- (void)dealloc;
- (bool)listenRFCOMMConnectionsWithChannelID:(BluetoothRFCOMMChannelID)channelID;
diff --git a/src/bluetooth/qbluetooth.cpp b/src/bluetooth/qbluetooth.cpp
index 7b5fd266..1e8ce0b8 100644
--- a/src/bluetooth/qbluetooth.cpp
+++ b/src/bluetooth/qbluetooth.cpp
@@ -104,5 +104,6 @@ Q_LOGGING_CATEGORY(QT_BT_ANDROID, "qt.bluetooth.android")
Q_LOGGING_CATEGORY(QT_BT_BLUEZ, "qt.bluetooth.bluez")
Q_LOGGING_CATEGORY(QT_BT_WINDOWS, "qt.bluetooth.windows")
Q_LOGGING_CATEGORY(QT_BT_WINRT, "qt.bluetooth.winrt")
+Q_LOGGING_CATEGORY(QT_BT_WINRT_SERVICE_THREAD, "qt.bluetooth.winrt.service.thread")
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent.cpp
index b132a3a6..fb14850e 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent.cpp
@@ -176,8 +176,6 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT)
\sa QBluetoothDeviceInfo::rssi(), lowEnergyDiscoveryTimeout()
*/
-// TODO deviceUpdated() signal not implemented on WinRT
-
/*!
\fn void QBluetoothDeviceDiscoveryAgent::finished()
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
index 443be14d..2f0524d4 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
@@ -363,7 +363,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::processDiscoveredDevices(
discoveredDevices.append(info);
qCDebug(QT_BT_ANDROID) << "Device found: " << info.name() << info.address().toString()
- << "isLeScanResult:" << isLeResult;
+ << "isLeScanResult:" << isLeResult
+ << "Manufacturer data size:" << info.manufacturerData().size();
emit q->deviceDiscovered(info);
}
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm b/src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm
index f62ca0dd..d9883d28 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm
@@ -37,11 +37,14 @@
**
****************************************************************************/
+#include "qbluetoothdevicediscoveryagent_p.h"
#include "qbluetoothdevicediscoveryagent.h"
+
#include "osx/osxbtledeviceinquiry_p.h"
+#ifdef Q_OS_MACOS
#include "osx/osxbtdeviceinquiry_p.h"
-#include "qbluetoothlocaldevice.h"
#include "osx/osxbtsdpinquiry_p.h"
+#endif // Q_OS_MACOS
#include "qbluetoothdeviceinfo.h"
#include "osx/osxbtnotifier_p.h"
#include "osx/osxbtutility_p.h"
@@ -51,13 +54,14 @@
#include "qbluetoothaddress.h"
#include "osx/uistrings_p.h"
#include "qbluetoothuuid.h"
+#include "osx/btraii_p.h"
#include <QtCore/qloggingcategory.h>
#include <QtCore/qscopedpointer.h>
+#include <QtCore/qvector.h>
#include <QtCore/qglobal.h>
#include <QtCore/qstring.h>
#include <QtCore/qdebug.h>
-#include <QtCore/qlist.h>
#include <Foundation/Foundation.h>
@@ -75,108 +79,42 @@ void registerQDeviceDiscoveryMetaType()
initDone = true;
}
}
+#ifdef Q_OS_MACOS
+using InquiryObjC = QT_MANGLE_NAMESPACE(OSXBTDeviceInquiry);
+#endif // Q_OS_MACOS
-}//namespace
-
-class QBluetoothDeviceDiscoveryAgentPrivate : public QObject,
- public OSXBluetooth::DeviceInquiryDelegate
-{
- friend class QBluetoothDeviceDiscoveryAgent;
-public:
- template<class T>
- using ObjCScopedPointer = OSXBluetooth::ObjCScopedPointer<T>;
- using LEDeviceInquiryObjC = QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry);
-
- QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress & address,
- QBluetoothDeviceDiscoveryAgent *q);
-
- ~QBluetoothDeviceDiscoveryAgentPrivate() override;
-
- bool isValid() const;
- bool isActive() const;
-
- void start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods);
- void startClassic();
- void startLE();
- void stop();
-
-private:
- enum AgentState {
- NonActive,
- ClassicScan,
- LEScan
- };
-
- // DeviceInquiryDelegate:
- void inquiryFinished(IOBluetoothDeviceInquiry *inq) override;
- void error(IOBluetoothDeviceInquiry *inq, IOReturn error) override;
- void deviceFound(IOBluetoothDeviceInquiry *inq, IOBluetoothDevice *device) override;
-
- void LEinquiryFinished();
- void LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error);
- void LEnotSupported();
-
- // Check if it's a really new device/updated info and emit
- // q_ptr->deviceDiscovered.
- void deviceFound(const QBluetoothDeviceInfo &newDeviceInfo);
-
- void setError(IOReturn error, const QString &text = QString());
- void setError(QBluetoothDeviceDiscoveryAgent::Error,
- const QString &text = QString());
-
- QBluetoothDeviceDiscoveryAgent *q_ptr;
- AgentState agentState;
-
- QBluetoothAddress adapterAddress;
+using LEInquiryObjC = QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry);
- bool startPending;
- bool stopPending;
-
- QBluetoothDeviceDiscoveryAgent::Error lastError;
- QString errorString;
-
- QBluetoothDeviceDiscoveryAgent::InquiryType inquiryType;
-
- using DeviceInquiry = ObjCScopedPointer<DeviceInquiryObjC>;
- DeviceInquiry inquiry;
-
- using LEDeviceInquiry = ObjCScopedPointer<LEDeviceInquiryObjC>;
- LEDeviceInquiry inquiryLE;
-
- using HostController = ObjCScopedPointer<IOBluetoothHostController>;
- HostController hostController;
-
- using DevicesList = QList<QBluetoothDeviceInfo>;
- DevicesList discoveredDevices;
-
- int lowEnergySearchTimeout;
- QBluetoothDeviceDiscoveryAgent::DiscoveryMethods requestedMethods;
-};
+} //namespace
QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress &adapter,
QBluetoothDeviceDiscoveryAgent *q) :
- q_ptr(q),
+ inquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry),
+ lastError(QBluetoothDeviceDiscoveryAgent::NoError),
agentState(NonActive),
adapterAddress(adapter),
startPending(false),
stopPending(false),
- lastError(QBluetoothDeviceDiscoveryAgent::NoError),
- inquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry),
lowEnergySearchTimeout(OSXBluetooth::defaultLEScanTimeoutMS),
- requestedMethods(QBluetoothDeviceDiscoveryAgent::ClassicMethod
- | QBluetoothDeviceDiscoveryAgent::LowEnergyMethod)
+#ifdef Q_OS_MACOS
+ requestedMethods(QBluetoothDeviceDiscoveryAgent::ClassicMethod | QBluetoothDeviceDiscoveryAgent::LowEnergyMethod),
+#else
+ requestedMethods(QBluetoothDeviceDiscoveryAgent::ClassicMethod),
+#endif // Q_OS_MACOS
+ q_ptr(q)
{
registerQDeviceDiscoveryMetaType();
Q_ASSERT_X(q != nullptr, Q_FUNC_INFO, "invalid q_ptr (null)");
- HostController controller([[IOBluetoothHostController defaultController] retain]);
- if (!controller || [controller powerState] != kBluetoothHCIPowerStateON) {
+#ifdef Q_OS_MACOS
+ IOBluetoothHostController *hostController = [IOBluetoothHostController defaultController];
+ if (!hostController || [hostController powerState] != kBluetoothHCIPowerStateON) {
qCCritical(QT_BT_OSX) << "no default host controller or adapter is off";
return;
}
-
- hostController.reset(controller.take());
+ controller.reset(hostController, DarwinBluetooth::RetainPolicy::doInitialRetain);
+#endif
}
QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
@@ -185,7 +123,7 @@ QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
// We want the LE scan to stop as soon as possible.
if (dispatch_queue_t leQueue = OSXBluetooth::qt_LE_queue()) {
// Local variable to be retained ...
- LEDeviceInquiryObjC *inq = inquiryLE.data();
+ LEInquiryObjC *inq = inquiryLE.getAs<LEInquiryObjC>();
dispatch_sync(leQueue, ^{
[inq stop];
});
@@ -193,11 +131,6 @@ QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
}
}
-bool QBluetoothDeviceDiscoveryAgentPrivate::isValid() const
-{
- return hostController && [hostController powerState] == kBluetoothHCIPowerStateON;
-}
-
bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const
{
if (startPending)
@@ -211,12 +144,19 @@ bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const
void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods)
{
- Q_ASSERT(isValid());
Q_ASSERT(!isActive());
Q_ASSERT(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError);
Q_ASSERT(methods & (QBluetoothDeviceDiscoveryAgent::ClassicMethod
| QBluetoothDeviceDiscoveryAgent::LowEnergyMethod));
+#ifdef Q_OS_MACOS
+ if (!controller) {
+ setError(QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError);
+ emit q_ptr->error(lastError);
+ return;
+ }
+#endif // Q_OS_MACOS
+
requestedMethods = methods;
if (stopPending) {
@@ -230,16 +170,18 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
agentState = NonActive;
discoveredDevices.clear();
setError(QBluetoothDeviceDiscoveryAgent::NoError);
-
+#ifdef Q_OS_MACOS
if (requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod)
return startClassic();
+#endif // Q_OS_MACOS
startLE();
}
+#ifdef Q_OS_MACOS
+
void QBluetoothDeviceDiscoveryAgentPrivate::startClassic()
{
- Q_ASSERT(isValid());
Q_ASSERT(!isActive());
Q_ASSERT(lastError == QBluetoothDeviceDiscoveryAgent::NoError);
Q_ASSERT(requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod);
@@ -249,7 +191,9 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startClassic()
if (!inquiry) {
// The first Classic scan for this DDA.
- inquiry.reset([[DeviceInquiryObjC alloc]initWithDelegate:this]);
+ inquiry.reset([[InquiryObjC alloc] initWithDelegate:this],
+ DarwinBluetooth::RetainPolicy::noInitialRetain);
+
if (!inquiry) {
qCCritical(QT_BT_OSX) << "failed to initialize an Classic device inquiry";
setError(QBluetoothDeviceDiscoveryAgent::UnknownError,
@@ -261,7 +205,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startClassic()
agentState = ClassicScan;
- const IOReturn res = [inquiry start];
+ const IOReturn res = [inquiry.getAs<InquiryObjC>() start];
if (res != kIOReturnSuccess) {
setError(res, QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STARTED));
agentState = NonActive;
@@ -269,9 +213,10 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startClassic()
}
}
+#endif // Q_OS_MACOS
+
void QBluetoothDeviceDiscoveryAgentPrivate::startLE()
{
- Q_ASSERT(isValid());
Q_ASSERT(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError);
Q_ASSERT(requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
@@ -291,7 +236,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startLE()
this, DeviceMemFunPtr(&QBluetoothDeviceDiscoveryAgentPrivate::deviceFound));
// Check queue and create scanner:
- inquiryLE.reset([[LEDeviceInquiryObjC alloc] initWithNotifier:notifier.data()]);
+ inquiryLE.reset([[LEInquiryObjC alloc] initWithNotifier:notifier.data()],
+ DarwinBluetooth::RetainPolicy::noInitialRetain);
if (inquiryLE)
notifier.take(); // Whatever happens next, inquiryLE is already the owner ...
@@ -307,7 +253,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startLE()
// Now start in on LE queue:
agentState = LEScan;
// We need the local variable so that it's retained ...
- LEDeviceInquiryObjC *inq = inquiryLE.data();
+ LEInquiryObjC *inq = inquiryLE.getAs<LEInquiryObjC>();
dispatch_async(leQueue, ^{
[inq startWithTimeout:lowEnergySearchTimeout];
});
@@ -315,7 +261,6 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startLE()
void QBluetoothDeviceDiscoveryAgentPrivate::stop()
{
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "called on invalid device discovery agent");
Q_ASSERT_X(isActive(), Q_FUNC_INFO, "called whithout active inquiry");
Q_ASSERT_X(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError,
Q_FUNC_INFO, "called with invalid bluetooth adapter");
@@ -328,8 +273,9 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop()
setError(QBluetoothDeviceDiscoveryAgent::NoError);
+#ifdef Q_OS_MACOS
if (agentState == ClassicScan) {
- const IOReturn res = [inquiry stop];
+ const IOReturn res = [inquiry.getAs<InquiryObjC>() stop];
if (res != kIOReturnSuccess) {
qCWarning(QT_BT_OSX) << "failed to stop";
startPending = prevStart;
@@ -338,10 +284,14 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop()
emit q_ptr->error(lastError);
}
} else {
+#else
+ {
+ Q_UNUSED(prevStart)
+#endif // Q_OS_MACOS
dispatch_queue_t leQueue(qt_LE_queue());
Q_ASSERT(leQueue);
// We need the local variable so that it's retained ...
- LEDeviceInquiryObjC *inq = inquiryLE.data();
+ LEInquiryObjC *inq = inquiryLE.getAs<LEInquiryObjC>();
dispatch_sync(leQueue, ^{
[inq stop];
});
@@ -351,12 +301,10 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop()
}
}
-void QBluetoothDeviceDiscoveryAgentPrivate::inquiryFinished(IOBluetoothDeviceInquiry *inq)
-{
- Q_UNUSED(inq)
-
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid device discovery agent"); //We can never be here.
+#ifdef Q_OS_MACOS
+void QBluetoothDeviceDiscoveryAgentPrivate::inquiryFinished()
+{
// The subsequent start(LE) function (if any)
// will (re)set the correct state.
agentState = NonActive;
@@ -381,12 +329,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::inquiryFinished(IOBluetoothDeviceInq
}
}
-void QBluetoothDeviceDiscoveryAgentPrivate::error(IOBluetoothDeviceInquiry *inq, IOReturn error)
+void QBluetoothDeviceDiscoveryAgentPrivate::error(IOReturn error)
{
- Q_UNUSED(inq)
-
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid device discovery agent");
-
startPending = false;
stopPending = false;
@@ -395,12 +339,11 @@ void QBluetoothDeviceDiscoveryAgentPrivate::error(IOBluetoothDeviceInquiry *inq,
emit q_ptr->error(lastError);
}
-void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(IOBluetoothDeviceInquiry *inq, IOBluetoothDevice *device)
+void QBluetoothDeviceDiscoveryAgentPrivate::classicDeviceFound(void *obj)
{
- Q_UNUSED(inq)
-
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid device discovery agent");
+ auto device = static_cast<IOBluetoothDevice *>(obj);
Q_ASSERT_X(device, Q_FUNC_INFO, "invalid IOBluetoothDevice (nil)");
+
Q_ASSERT_X(agentState == ClassicScan, Q_FUNC_INFO,
"invalid agent state (expected classic scan)");
@@ -417,7 +360,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(IOBluetoothDeviceInquiry
if (device.name)
deviceName = QString::fromNSString(device.name);
- const qint32 classOfDevice(device.classOfDevice);
+ const auto classOfDevice = qint32(device.classOfDevice);
QBluetoothDeviceInfo deviceInfo(deviceAddress, deviceName, classOfDevice);
deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration);
@@ -439,6 +382,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::setError(IOReturn error, const QStri
setError(QBluetoothDeviceDiscoveryAgent::UnknownError, text);
}
+#endif // Q_OS_MACOS
+
void QBluetoothDeviceDiscoveryAgentPrivate::setError(QBluetoothDeviceDiscoveryAgent::Error error, const QString &text)
{
lastError = error;
@@ -459,14 +404,14 @@ void QBluetoothDeviceDiscoveryAgentPrivate::setError(QBluetoothDeviceDiscoveryAg
case QBluetoothDeviceDiscoveryAgent::InputOutputError:
errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_IO);
break;
+ case QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError:
+ errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_NOTSUPPORTED);
+ break;
case QBluetoothDeviceDiscoveryAgent::UnknownError:
default:
errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_UNKNOWN_ERROR);
}
}
-
- if (lastError != QBluetoothDeviceDiscoveryAgent::NoError)
- qCDebug(QT_BT_OSX) << "error set:"<<errorString;
}
void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error)
@@ -487,6 +432,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::LEnotSupported()
{
qCDebug(QT_BT_OSX) << "no Bluetooth LE support";
+#ifdef Q_OS_MACOS
if (requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod) {
// Having both Classic | LE means this is not an error.
LEinquiryFinished();
@@ -497,6 +443,13 @@ void QBluetoothDeviceDiscoveryAgentPrivate::LEnotSupported()
// as UnsupportedDiscoveryMethod.
LEinquiryError(QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod);
}
+#else
+ inquiryLE.reset();
+ startPending = false;
+ stopPending = false;
+ setError(QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError);
+ emit q_ptr->error(lastError);
+#endif
}
void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryFinished()
@@ -522,8 +475,12 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(const QBluetoothDeviceIn
// Core Bluetooth does not allow us to access addresses, we have to use uuid instead.
// This uuid has nothing to do with uuids in Bluetooth in general (it's generated by
// Apple's framework using some algorithm), but it's a 128-bit uuid after all.
- const bool isLE = newDeviceInfo.coreConfigurations() == QBluetoothDeviceInfo::LowEnergyCoreConfiguration;
-
+ const bool isLE =
+#ifdef Q_OS_MACOS
+ newDeviceInfo.coreConfigurations() == QBluetoothDeviceInfo::LowEnergyCoreConfiguration;
+#else
+ true;
+#endif // Q_OS_MACOS
for (int i = 0, e = discoveredDevices.size(); i < e; ++i) {
if (isLE) {
if (discoveredDevices[i].deviceUuid() == newDeviceInfo.deviceUuid()) {
@@ -564,6 +521,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(const QBluetoothDeviceIn
return;
}
} else {
+#ifdef Q_OS_MACOS
if (discoveredDevices[i].address() == newDeviceInfo.address()) {
if (discoveredDevices[i] == newDeviceInfo)
return;
@@ -572,6 +530,9 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(const QBluetoothDeviceIn
emit q_ptr->deviceDiscovered(newDeviceInfo);
return;
}
+#else
+ Q_UNREACHABLE();
+#endif // Q_OS_MACOS
}
}
@@ -579,125 +540,13 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(const QBluetoothDeviceIn
emit q_ptr->deviceDiscovered(newDeviceInfo);
}
-QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent(QObject *parent) :
- QObject(parent),
- d_ptr(new QBluetoothDeviceDiscoveryAgentPrivate(QBluetoothAddress(), this))
-{
-}
-
-QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent(
- const QBluetoothAddress &deviceAdapter, QObject *parent) :
- QObject(parent),
- d_ptr(new QBluetoothDeviceDiscoveryAgentPrivate(deviceAdapter, this))
-{
- if (!deviceAdapter.isNull()) {
- const QList<QBluetoothHostInfo> localDevices = QBluetoothLocalDevice::allDevices();
- for (const QBluetoothHostInfo &hostInfo : localDevices) {
- if (hostInfo.address() == deviceAdapter)
- return;
- }
- d_ptr->setError(InvalidBluetoothAdapterError);
- }
-}
-
-QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent()
-{
- delete d_ptr;
-}
-
-QBluetoothDeviceDiscoveryAgent::InquiryType QBluetoothDeviceDiscoveryAgent::inquiryType() const
-{
- return d_ptr->inquiryType;
-}
-
-void QBluetoothDeviceDiscoveryAgent::setInquiryType(InquiryType type)
-{
- d_ptr->inquiryType = type;
-}
-
-QList<QBluetoothDeviceInfo> QBluetoothDeviceDiscoveryAgent::discoveredDevices() const
-{
- return d_ptr->discoveredDevices;
-}
-
QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods()
{
+#ifdef Q_OS_MACOS
return ClassicMethod | LowEnergyMethod;
-}
-
-void QBluetoothDeviceDiscoveryAgent::start()
-{
- start(supportedDiscoveryMethods());
-}
-
-void QBluetoothDeviceDiscoveryAgent::start(DiscoveryMethods methods)
-{
- if (methods == NoMethod)
- return;
-
- if ((supportedDiscoveryMethods() & methods) != methods) {
- d_ptr->lastError = UnsupportedDiscoveryMethod;
- d_ptr->errorString = tr("One or more device discovery methods "
- "are not supported on this platform");
- emit error(d_ptr->lastError);
- return;
- }
-
- if (d_ptr->lastError != InvalidBluetoothAdapterError) {
- if (d_ptr->isValid()) {
- if (!isActive())
- d_ptr->start(methods);
- } else {
- // We previously failed to initialize d_ptr correctly:
- // either some memory allocation problem or
- // no BT adapter found.
- d_ptr->setError(InvalidBluetoothAdapterError);
- emit error(InvalidBluetoothAdapterError);
- }
- }
-}
-
-void QBluetoothDeviceDiscoveryAgent::stop()
-{
- if (d_ptr->isValid()) {
- if (isActive() && d_ptr->lastError != InvalidBluetoothAdapterError)
- d_ptr->stop();
- }
-}
-
-bool QBluetoothDeviceDiscoveryAgent::isActive() const
-{
- if (d_ptr->isValid())
- return d_ptr->isActive();
-
- return false;
-}
-
-QBluetoothDeviceDiscoveryAgent::Error QBluetoothDeviceDiscoveryAgent::error() const
-{
- return d_ptr->lastError;
-}
-
-QString QBluetoothDeviceDiscoveryAgent::errorString() const
-{
- return d_ptr->errorString;
-}
-
-void QBluetoothDeviceDiscoveryAgent::setLowEnergyDiscoveryTimeout(int timeout)
-{
- // cannot deliberately turn it off
- if (timeout < 0) {
- qCDebug(QT_BT_OSX) << "The Bluetooth Low Energy device discovery timeout cannot be negative.";
- return;
- }
-
- d_ptr->lowEnergySearchTimeout = timeout;
- return;
-}
-
-int QBluetoothDeviceDiscoveryAgent::lowEnergyDiscoveryTimeout() const
-{
- return d_ptr->lowEnergySearchTimeout;
+#else
+ return LowEnergyMethod;
+#endif // Q_OS_MACOS
}
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm b/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm
deleted file mode 100644
index 059f244d..00000000
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm
+++ /dev/null
@@ -1,458 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtBluetooth module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qbluetoothdevicediscoveryagent.h"
-#include "osx/osxbtledeviceinquiry_p.h"
-#include "qbluetoothlocaldevice.h"
-#include "qbluetoothdeviceinfo.h"
-#include "osx/osxbtnotifier_p.h"
-#include "osx/osxbtutility_p.h"
-#include "osx/uistrings_p.h"
-#include "qbluetoothuuid.h"
-
-#include <QtCore/qloggingcategory.h>
-#include <QtCore/qobject.h>
-#include <QtCore/qglobal.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qdebug.h>
-#include <QtCore/qlist.h>
-
-#include <CoreBluetooth/CoreBluetooth.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace
-{
-
-void registerQDeviceDiscoveryMetaType()
-{
- static bool initDone = false;
- if (!initDone) {
- qRegisterMetaType<QBluetoothDeviceInfo>();
- qRegisterMetaType<QBluetoothDeviceDiscoveryAgent::Error>();
- initDone = true;
- }
-}
-
-}//namespace
-
-class QBluetoothDeviceDiscoveryAgentPrivate : public QObject
-{
- friend class QBluetoothDeviceDiscoveryAgent;
-
-public:
- QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress &address,
- QBluetoothDeviceDiscoveryAgent *q);
- virtual ~QBluetoothDeviceDiscoveryAgentPrivate();
-
- bool isActive() const;
-
- void start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods m);
- void stop();
-
-private:
- using LEDeviceInquiryObjC = QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry);
-
- void LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error);
- void LEnotSupported();
- void LEdeviceFound(const QBluetoothDeviceInfo &info);
- void LEinquiryFinished();
-
- void setError(QBluetoothDeviceDiscoveryAgent::Error, const QString &text = QString());
-
- QBluetoothDeviceDiscoveryAgent *q_ptr;
-
- QBluetoothDeviceDiscoveryAgent::Error lastError;
- QString errorString;
-
- QBluetoothDeviceDiscoveryAgent::InquiryType inquiryType;
-
- using LEDeviceInquiry = OSXBluetooth::ObjCScopedPointer<LEDeviceInquiryObjC>;
- LEDeviceInquiry inquiryLE;
-
- using DevicesList = QList<QBluetoothDeviceInfo>;
- DevicesList discoveredDevices;
-
- bool startPending;
- bool stopPending;
-
- int lowEnergySearchTimeout;
-};
-
-QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress &adapter,
- QBluetoothDeviceDiscoveryAgent *q) :
- q_ptr(q),
- lastError(QBluetoothDeviceDiscoveryAgent::NoError),
- inquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry),
- startPending(false),
- stopPending(false),
- lowEnergySearchTimeout(OSXBluetooth::defaultLEScanTimeoutMS)
-{
- Q_UNUSED(adapter);
-
- registerQDeviceDiscoveryMetaType();
- Q_ASSERT_X(q != nullptr, Q_FUNC_INFO, "invalid q_ptr (null)");
-}
-
-QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
-{
- if (inquiryLE) {
- // We want the LE scan to stop as soon as possible.
- if (dispatch_queue_t leQueue = OSXBluetooth::qt_LE_queue()) {
- // Local variable to be retained ...
- LEDeviceInquiryObjC *inq = inquiryLE.data();
- dispatch_sync(leQueue, ^{
- [inq stop];
- });
- }
- }
-}
-
-bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const
-{
- if (startPending)
- return true;
- if (stopPending)
- return false;
-
- return inquiryLE;
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods /*methods*/)
-{
- Q_ASSERT_X(!isActive(), Q_FUNC_INFO, "called on active device discovery agent");
-
- if (stopPending) {
- startPending = true;
- return;
- }
-
- using namespace OSXBluetooth;
-
- QScopedPointer<LECBManagerNotifier> notifier(new LECBManagerNotifier);
- // Connections:
- using ErrMemFunPtr = void (LECBManagerNotifier::*)(QBluetoothDeviceDiscoveryAgent::Error);
- notifier->connect(notifier.data(), ErrMemFunPtr(&LECBManagerNotifier::CBManagerError),
- this, &QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryError);
- notifier->connect(notifier.data(), &LECBManagerNotifier::LEnotSupported,
- this, &QBluetoothDeviceDiscoveryAgentPrivate::LEnotSupported);
- notifier->connect(notifier.data(), &LECBManagerNotifier::discoveryFinished,
- this, &QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryFinished);
- notifier->connect(notifier.data(), &LECBManagerNotifier::deviceDiscovered,
- this, &QBluetoothDeviceDiscoveryAgentPrivate::LEdeviceFound);
-
- inquiryLE.reset([[LEDeviceInquiryObjC alloc] initWithNotifier:notifier.data()]);
- if (inquiryLE)
- notifier.take(); // Whatever happens next, inquiryLE is already the owner ...
-
- dispatch_queue_t leQueue(qt_LE_queue());
- if (!leQueue || !inquiryLE) {
- setError(QBluetoothDeviceDiscoveryAgent::UnknownError,
- QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STARTED));
- emit q_ptr->error(lastError);
- return;
- }
-
- discoveredDevices.clear();
- setError(QBluetoothDeviceDiscoveryAgent::NoError);
-
- // Create a local variable - to have a strong referece in a block.
- LEDeviceInquiryObjC *inq = inquiryLE.data();
- dispatch_async(leQueue, ^{
- [inq startWithTimeout:lowEnergySearchTimeout];
- });
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::stop()
-{
- Q_ASSERT_X(isActive(), Q_FUNC_INFO, "called whithout active inquiry");
-
- startPending = false;
- stopPending = true;
-
- dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- Q_ASSERT(leQueue);
-
- setError(QBluetoothDeviceDiscoveryAgent::NoError);
-
- // Create a local variable - to have a strong referece in a block.
- LEDeviceInquiryObjC *inq = inquiryLE.data();
- dispatch_sync(leQueue, ^{
- [inq stop];
- });
- // We consider LE scan to be stopped immediately and
- // do not care about this LEDeviceInquiry object anymore.
- LEinquiryFinished();
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error)
-{
- // At the moment the only error reported by osxbtledeviceinquiry
- // can be 'powered off' error, it happens
- // after the LE scan started (so we have LE support and this is
- // a real PoweredOffError).
- Q_ASSERT_X(error == QBluetoothDeviceDiscoveryAgent::PoweredOffError,
- Q_FUNC_INFO, "unexpected error");
-
- inquiryLE.reset();
-
- startPending = false;
- stopPending = false;
- setError(error);
- emit q_ptr->error(lastError);
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::LEnotSupported()
-{
- inquiryLE.reset();
-
- startPending = false;
- stopPending = false;
- setError(QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError);
- emit q_ptr->error(lastError);
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::LEdeviceFound(const QBluetoothDeviceInfo &newDeviceInfo)
-{
- // Update, append or discard.
- for (int i = 0, e = discoveredDevices.size(); i < e; ++i) {
- if (discoveredDevices[i].deviceUuid() == newDeviceInfo.deviceUuid()) {
- QBluetoothDeviceInfo::Fields updatedFields = QBluetoothDeviceInfo::Field::None;
- if (discoveredDevices[i].rssi() != newDeviceInfo.rssi()) {
- qCDebug(QT_BT_OSX) << "Updating RSSI for" << newDeviceInfo.address()
- << newDeviceInfo.rssi();
- discoveredDevices[i].setRssi(newDeviceInfo.rssi());
- updatedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI);
- }
-
- if (discoveredDevices[i].manufacturerData() != newDeviceInfo.manufacturerData()) {
- qCDebug(QT_BT_OSX) << "Updating manufacturer data for" << newDeviceInfo.address();
- const QVector<quint16> keys = newDeviceInfo.manufacturerIds();
- for (auto key: keys)
- discoveredDevices[i].setManufacturerData(key, newDeviceInfo.manufacturerData(key));
- updatedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData);
- }
-
- if (lowEnergySearchTimeout > 0) {
- if (discoveredDevices[i] != newDeviceInfo) {
- discoveredDevices.replace(i, newDeviceInfo);
- emit q_ptr->deviceDiscovered(newDeviceInfo);
- } else {
- if (!updatedFields.testFlag(QBluetoothDeviceInfo::Field::None))
- emit q_ptr->deviceUpdated(discoveredDevices[i], updatedFields);
- }
-
- return;
- }
-
- discoveredDevices.replace(i, newDeviceInfo);
- emit q_ptr->deviceDiscovered(newDeviceInfo);
-
- if (!updatedFields.testFlag(QBluetoothDeviceInfo::Field::None))
- emit q_ptr->deviceUpdated(discoveredDevices[i], updatedFields);
-
- return;
- }
- }
-
- discoveredDevices.append(newDeviceInfo);
- emit q_ptr->deviceDiscovered(newDeviceInfo);
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryFinished()
-{
- inquiryLE.reset();
-
- if (stopPending && !startPending) {
- stopPending = false;
- emit q_ptr->canceled();
- } else if (startPending) {
- startPending = false;
- stopPending = false;
- // always the same method for start() on iOS
- // classic search not supported
- start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
- } else {
- emit q_ptr->finished();
- }
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::setError(QBluetoothDeviceDiscoveryAgent::Error error,
- const QString &text)
-{
- lastError = error;
-
- if (text.length() > 0) {
- errorString = text;
- } else {
- switch (lastError) {
- case QBluetoothDeviceDiscoveryAgent::NoError:
- errorString = QString();
- break;
- case QBluetoothDeviceDiscoveryAgent::PoweredOffError:
- errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_POWERED_OFF);
- break;
- case QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError:
- errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_INVALID_ADAPTER);
- break;
- case QBluetoothDeviceDiscoveryAgent::InputOutputError:
- errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_IO);
- break;
- case QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError:
- errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_NOTSUPPORTED);
- break;
- case QBluetoothDeviceDiscoveryAgent::UnknownError:
- default:
- errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_UNKNOWN_ERROR);
- }
- }
-}
-
-QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent(QObject *parent) :
- QObject(parent),
- d_ptr(new QBluetoothDeviceDiscoveryAgentPrivate(QBluetoothAddress(), this))
-{
-}
-
-QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent(
- const QBluetoothAddress &deviceAdapter, QObject *parent) :
- QObject(parent),
- d_ptr(new QBluetoothDeviceDiscoveryAgentPrivate(deviceAdapter, this))
-{
- if (!deviceAdapter.isNull()) {
- qCWarning(QT_BT_OSX) << "local device address is "
- "not available, provided address is ignored";
- d_ptr->setError(InvalidBluetoothAdapterError);
- }
-}
-
-QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent()
-{
- delete d_ptr;
-}
-
-QBluetoothDeviceDiscoveryAgent::InquiryType QBluetoothDeviceDiscoveryAgent::inquiryType() const
-{
- return d_ptr->inquiryType;
-}
-
-void QBluetoothDeviceDiscoveryAgent::setInquiryType(QBluetoothDeviceDiscoveryAgent::InquiryType type)
-{
- d_ptr->inquiryType = type;
-}
-
-QList<QBluetoothDeviceInfo> QBluetoothDeviceDiscoveryAgent::discoveredDevices() const
-{
- return d_ptr->discoveredDevices;
-}
-
-QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods()
-{
- return LowEnergyMethod;
-}
-
-void QBluetoothDeviceDiscoveryAgent::start()
-{
- if (d_ptr->lastError != InvalidBluetoothAdapterError) {
- if (!isActive())
- d_ptr->start(supportedDiscoveryMethods());
- else
- qCDebug(QT_BT_OSX) << "already started";
- }
-}
-
-void QBluetoothDeviceDiscoveryAgent::start(DiscoveryMethods methods)
-{
- if (methods == NoMethod)
- return;
-
- DiscoveryMethods supported =
- QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods();
-
- if (!((supported & methods) == methods)) {
- d_ptr->lastError = UnsupportedDiscoveryMethod;
- d_ptr->errorString = QBluetoothDeviceDiscoveryAgent::tr("One or more device discovery methods "
- "are not supported on this platform");
- emit error(d_ptr->lastError);
- return;
- }
-
- if (!isActive() && d_ptr->lastError != InvalidBluetoothAdapterError)
- d_ptr->start(methods);
-}
-
-void QBluetoothDeviceDiscoveryAgent::stop()
-{
- if (isActive() && d_ptr->lastError != InvalidBluetoothAdapterError)
- d_ptr->stop();
-}
-
-bool QBluetoothDeviceDiscoveryAgent::isActive() const
-{
- return d_ptr->isActive();
-}
-
-QBluetoothDeviceDiscoveryAgent::Error QBluetoothDeviceDiscoveryAgent::error() const
-{
- return d_ptr->lastError;
-}
-
-QString QBluetoothDeviceDiscoveryAgent::errorString() const
-{
- return d_ptr->errorString;
-}
-
-int QBluetoothDeviceDiscoveryAgent::lowEnergyDiscoveryTimeout() const
-{
- return d_ptr->lowEnergySearchTimeout;
-}
-
-void QBluetoothDeviceDiscoveryAgent::setLowEnergyDiscoveryTimeout(int timeout)
-{
- // cannot deliberately turn it off
- if (timeout < 0) {
- qCDebug(QT_BT_OSX) << "The Bluetooth Low Energy device discovery timeout cannot be negative.";
- return;
- }
-
- d_ptr->lowEnergySearchTimeout = timeout;
- return;
-}
-
-QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
index 97beced3..be3a8863 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
@@ -59,6 +59,11 @@
#include <QtCore/QTimer>
#endif
+#ifdef Q_OS_DARWIN
+#include "osx/btdelegates_p.h"
+#include "osx/btraii_p.h"
+#endif // Q_OS_DARWIN
+
#include <QtCore/QVariantMap>
#include <QtBluetooth/QBluetoothAddress>
@@ -95,6 +100,9 @@ QT_END_NAMESPACE
#elif defined(QT_WINRT_BLUETOOTH)
#include <QtCore/QPointer>
#include <QtCore/QTimer>
+
+using ManufacturerData = QHash<quint16, QByteArray>;
+Q_DECLARE_METATYPE(ManufacturerData)
#endif
QT_BEGIN_NAMESPACE
@@ -104,11 +112,15 @@ class QWinRTBluetoothDeviceDiscoveryWorker;
#endif
class QBluetoothDeviceDiscoveryAgentPrivate
-#if defined(QT_ANDROID_BLUETOOTH) || defined(QT_WINRT_BLUETOOTH) || defined(QT_WIN_BLUETOOTH)
+#if defined(QT_ANDROID_BLUETOOTH) || defined(QT_WINRT_BLUETOOTH) || defined(QT_WIN_BLUETOOTH) \
+ || defined(Q_OS_DARWIN)
: public QObject
+#if defined(Q_OS_MACOS)
+ , public DarwinBluetooth::DeviceInquiryDelegate
+#endif // Q_OS_MACOS
{
Q_OBJECT
-#else
+#else // BlueZ
{
#endif
Q_DECLARE_PUBLIC(QBluetoothDeviceDiscoveryAgent)
@@ -208,6 +220,8 @@ private:
#ifdef QT_WINRT_BLUETOOTH
private slots:
void registerDevice(const QBluetoothDeviceInfo &info);
+ void updateDeviceData(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields fields,
+ qint16 rssi, ManufacturerData manufacturerData);
void onScanFinished();
private:
@@ -216,6 +230,57 @@ private:
QTimer *leScanTimer;
#endif
+#ifdef Q_OS_DARWIN
+
+ void startLE();
+
+#ifdef Q_OS_MACOS
+
+ void startClassic();
+
+ // Classic (IOBluetooth) inquiry delegate's methods:
+ void inquiryFinished() override;
+ void error(IOReturn error) override;
+ void classicDeviceFound(void *device) override;
+ // Classic (IOBluetooth) errors:
+ void setError(IOReturn error, const QString &text = QString());
+
+#endif // Q_OS_MACOS
+
+ // LE scan delegates (CoreBluetooth, all Darwin OSes):
+ void LEinquiryFinished();
+ void LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error);
+ void LEnotSupported();
+
+ // LE errors:
+ void setError(QBluetoothDeviceDiscoveryAgent::Error,
+ const QString &text = QString());
+
+ // Both LE and Classic devices go there:
+ void deviceFound(const QBluetoothDeviceInfo &newDeviceInfo);
+
+ enum AgentState {
+ NonActive,
+ ClassicScan, // macOS (IOBluetooth) only
+ LEScan
+ } agentState;
+
+ QBluetoothAddress adapterAddress;
+
+ bool startPending;
+ bool stopPending;
+
+#ifdef Q_OS_MACOS
+
+ DarwinBluetooth::ScopedPointer controller;
+ DarwinBluetooth::ScopedPointer inquiry;
+
+#endif // Q_OS_MACOS
+
+ DarwinBluetooth::ScopedPointer inquiryLE;
+
+#endif // Q_OS_DARWIN
+
int lowEnergySearchTimeout;
QBluetoothDeviceDiscoveryAgent::DiscoveryMethods requestedMethods;
QBluetoothDeviceDiscoveryAgent *q_ptr;
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
index a353f5e3..9d306053 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
@@ -52,6 +52,7 @@
#include <QtCore/QLoggingCategory>
#include <QtCore/private/qeventdispatcher_winrt_p.h>
+#include <robuffer.h>
#include <wrl.h>
#include <windows.devices.enumeration.h>
#include <windows.devices.bluetooth.h>
@@ -68,6 +69,7 @@ using namespace ABI::Windows::Devices;
using namespace ABI::Windows::Devices::Bluetooth;
using namespace ABI::Windows::Devices::Bluetooth::Advertisement;
using namespace ABI::Windows::Devices::Enumeration;
+using namespace ABI::Windows::Storage::Streams;
QT_BEGIN_NAMESPACE
@@ -79,6 +81,39 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT)
ret; \
}
+#define WARN_AND_CONTINUE_IF_FAILED(msg) \
+ if (FAILED(hr)) { \
+ qCWarning(QT_BT_WINRT) << msg; \
+ continue; \
+ }
+
+static ManufacturerData extractManufacturerData(ComPtr<IBluetoothLEAdvertisement> ad)
+{
+ ManufacturerData ret;
+ ComPtr<IVector<BluetoothLEManufacturerData*>> data;
+ HRESULT hr = ad->get_ManufacturerData(&data);
+ WARN_AND_RETURN_IF_FAILED("Could not obtain list of manufacturer data.", return ret);
+ quint32 size;
+ hr = data->get_Size(&size);
+ WARN_AND_RETURN_IF_FAILED("Could not obtain manufacturer data's list size.", return ret);
+ for (quint32 i = 0; i < size; ++i) {
+ ComPtr<IBluetoothLEManufacturerData> d;
+ hr = data->GetAt(i, &d);
+ WARN_AND_CONTINUE_IF_FAILED("Could not obtain manufacturer data.");
+ quint16 id;
+ hr = d->get_CompanyId(&id);
+ WARN_AND_CONTINUE_IF_FAILED("Could not obtain manufacturer data company id.");
+ ComPtr<IBuffer> buffer;
+ hr = d->get_Data(&buffer);
+ WARN_AND_CONTINUE_IF_FAILED("Could not obtain manufacturer data set.");
+ const QByteArray bufferData = byteArrayFromBuffer(buffer);
+ if (ret.contains(id))
+ qCWarning(QT_BT_WINRT) << "Company ID already present in manufacturer data.";
+ ret.insert(id, bufferData);
+ }
+ return ret;
+}
+
class QWinRTBluetoothDeviceDiscoveryWorker : public QObject
{
Q_OBJECT
@@ -86,7 +121,7 @@ public:
explicit QWinRTBluetoothDeviceDiscoveryWorker(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods);
~QWinRTBluetoothDeviceDiscoveryWorker();
void start();
- void stop();
+ void stopLEWatcher();
private:
void startDeviceDiscovery(QBluetoothDeviceDiscoveryAgent::DiscoveryMethod mode);
@@ -117,6 +152,8 @@ public slots:
Q_SIGNALS:
void deviceFound(const QBluetoothDeviceInfo &info);
+ void deviceDataChanged(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields,
+ qint16 rssi, ManufacturerData manufacturerData);
void scanFinished();
public:
@@ -127,9 +164,15 @@ private:
EventRegistrationToken m_leDeviceAddedToken;
#if QT_CONFIG(winrt_btle_no_pairing)
QMutex m_foundDevicesMutex;
- QMap<quint64, QVector<QBluetoothUuid>> m_foundLEDevicesMap;
+ struct LEAdvertisingInfo {
+ QVector<QBluetoothUuid> services;
+ qint16 rssi = 0;
+ };
+
+ QMap<quint64, LEAdvertisingInfo> m_foundLEDevicesMap;
#endif
- QVector<quint64> m_foundLEDevices;
+ QMap<quint64, qint16> m_foundLEDevices;
+ QMap<quint64, ManufacturerData> m_foundLEManufacturerData;
int m_pendingPairedDevices;
ComPtr<IBluetoothDeviceStatics> m_deviceStatics;
@@ -141,6 +184,8 @@ QWinRTBluetoothDeviceDiscoveryWorker::QWinRTBluetoothDeviceDiscoveryWorker(QBlue
, m_pendingPairedDevices(0)
{
qRegisterMetaType<QBluetoothDeviceInfo>();
+ qRegisterMetaType<QBluetoothDeviceInfo::Fields>();
+ qRegisterMetaType<ManufacturerData>();
#ifdef CLASSIC_APP_BUILD
CoInitialize(NULL);
@@ -153,7 +198,7 @@ QWinRTBluetoothDeviceDiscoveryWorker::QWinRTBluetoothDeviceDiscoveryWorker(QBlue
QWinRTBluetoothDeviceDiscoveryWorker::~QWinRTBluetoothDeviceDiscoveryWorker()
{
- stop();
+ stopLEWatcher();
#ifdef CLASSIC_APP_BUILD
CoUninitialize();
#endif
@@ -175,7 +220,7 @@ void QWinRTBluetoothDeviceDiscoveryWorker::start()
qCDebug(QT_BT_WINRT) << "Worker started";
}
-void QWinRTBluetoothDeviceDiscoveryWorker::stop()
+void QWinRTBluetoothDeviceDiscoveryWorker::stopLEWatcher()
{
if (m_leWatcher) {
HRESULT hr = m_leWatcher->Stop();
@@ -250,7 +295,8 @@ void QWinRTBluetoothDeviceDiscoveryWorker::gatherMultipleDeviceInformation(quint
{
for (quint32 i = 0; i < deviceCount; ++i) {
ComPtr<IDeviceInformation> device;
- HRESULT hr = devices->GetAt(i, &device);
+ HRESULT hr;
+ hr = devices->GetAt(i, &device);
Q_ASSERT_SUCCEEDED(hr);
gatherDeviceInformation(device.Get(), mode);
}
@@ -271,11 +317,23 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher()
HRESULT hr;
hr = args->get_BluetoothAddress(&address);
Q_ASSERT_SUCCEEDED(hr);
+ qint16 rssi;
+ hr = args->get_RawSignalStrengthInDBm(&rssi);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IBluetoothLEAdvertisement> ad;
+ hr = args->get_Advertisement(&ad);
+ Q_ASSERT_SUCCEEDED(hr);
+ const ManufacturerData manufacturerData = extractManufacturerData(ad);
+ QBluetoothDeviceInfo::Fields changedFields = QBluetoothDeviceInfo::Field::None;
+ if (!m_foundLEManufacturerData.contains(address)) {
+ m_foundLEManufacturerData.insert(address, manufacturerData);
+ changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData);
+ } else if (m_foundLEManufacturerData.value(address) != manufacturerData) {
+ m_foundLEManufacturerData[address] = manufacturerData;
+ changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData);
+ }
#if QT_CONFIG(winrt_btle_no_pairing)
if (supportsNewLEApi()) {
- ComPtr<IBluetoothLEAdvertisement> ad;
- hr = args->get_Advertisement(&ad);
- Q_ASSERT_SUCCEEDED(hr);
ComPtr<IVector<GUID>> guids;
hr = ad->get_ServiceUuids(&guids);
Q_ASSERT_SUCCEEDED(hr);
@@ -295,7 +353,12 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher()
if (m_foundLEDevicesMap.contains(address)) {
if (size == 0)
return S_OK;
- QVector<QBluetoothUuid> foundServices = m_foundLEDevicesMap.value(address);
+ const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address);
+ QVector<QBluetoothUuid> foundServices = adInfo.services;
+ if (adInfo.rssi != rssi) {
+ m_foundLEDevicesMap[address].rssi = rssi;
+ changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI);
+ }
bool newServiceAdded = false;
for (const QBluetoothUuid &uuid : qAsConst(serviceUuids)) {
if (!foundServices.contains(uuid)) {
@@ -303,20 +366,43 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher()
newServiceAdded = true;
}
}
- if (!newServiceAdded)
+ if (!newServiceAdded) {
+ if (!changedFields.testFlag(QBluetoothDeviceInfo::Field::None)) {
+ QMetaObject::invokeMethod(this, "deviceDataChanged", Qt::AutoConnection,
+ Q_ARG(QBluetoothAddress, QBluetoothAddress(address)),
+ Q_ARG(QBluetoothDeviceInfo::Fields, changedFields),
+ Q_ARG(qint16, rssi),
+ Q_ARG(ManufacturerData, manufacturerData));
+ }
return S_OK;
- m_foundLEDevicesMap[address] = foundServices;
+ }
+ m_foundLEDevicesMap[address].services = foundServices;
} else {
- m_foundLEDevicesMap.insert(address, serviceUuids);
+ LEAdvertisingInfo info;
+ info.services = std::move(serviceUuids);
+ info.rssi = rssi;
+ m_foundLEDevicesMap.insert(address, info);
}
locker.unlock();
} else
#endif
{
- if (m_foundLEDevices.contains(address))
+ if (m_foundLEDevices.contains(address)) {
+ if (m_foundLEDevices.value(address) != rssi) {
+ m_foundLEDevices[address] = rssi;
+ changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI);
+ }
+ if (!changedFields.testFlag(QBluetoothDeviceInfo::Field::None)) {
+ QMetaObject::invokeMethod(this, "deviceDataChanged", Qt::AutoConnection,
+ Q_ARG(QBluetoothAddress, QBluetoothAddress(address)),
+ Q_ARG(QBluetoothDeviceInfo::Fields, changedFields),
+ Q_ARG(qint16, rssi),
+ Q_ARG(ManufacturerData, manufacturerData));
+ }
return S_OK;
- m_foundLEDevices.append(address);
+ }
+ m_foundLEDevices.insert(address, rssi);
}
leBluetoothInfoFromAddressAsync(address);
return S_OK;
@@ -329,6 +415,7 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher()
void QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery()
{
emit scanFinished();
+ stopLEWatcher();
deleteLater();
}
@@ -616,13 +703,19 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB
Q_ASSERT_SUCCEEDED(hr);
uuids.append(QBluetoothUuid(uuid));
}
+ const qint16 rssi = m_foundLEDevices.value(address);
+ const ManufacturerData manufacturerData = m_foundLEManufacturerData.value(address);
qCDebug(QT_BT_WINRT) << "Discovered BTLE device: " << QString::number(address) << btName
- << "Num UUIDs" << uuids.count();
+ << "Num UUIDs" << uuids.count() << "RSSI:" << rssi
+ << "Num manufacturer data" << manufacturerData.count();
QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0);
info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration);
info.setServiceUuids(uuids);
+ info.setRssi(rssi);
+ for (const quint16 key : manufacturerData.keys())
+ info.setManufacturerData(key, manufacturerData.value(key));
info.setCached(true);
QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection,
@@ -665,11 +758,13 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB
boolean isPaired;
hr = pairing->get_IsPaired(&isPaired);
Q_ASSERT_SUCCEEDED(hr);
- QList<QBluetoothUuid> uuids;
+ QVector<QBluetoothUuid> uuids;
+ const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address);
+ const qint16 rssi = adInfo.rssi;
// Use the services obtained from the advertisement data if the device is not paired
if (!isPaired) {
- uuids = m_foundLEDevicesMap.value(address).toList();
+ uuids = adInfo.services;
} else {
IVectorView <GenericAttributeProfile::GattDeviceService *> *deviceServices;
hr = device->get_GattServices(&deviceServices);
@@ -687,13 +782,18 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB
uuids.append(QBluetoothUuid(uuid));
}
}
+ const ManufacturerData manufacturerData = m_foundLEManufacturerData.value(address);
qCDebug(QT_BT_WINRT) << "Discovered BTLE device: " << QString::number(address) << btName
- << "Num UUIDs" << uuids.count();
+ << "Num UUIDs" << uuids.count() << "RSSI:" << rssi
+ << "Num manufacturer data" << manufacturerData.count();
QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0);
info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration);
- info.setServiceUuids(uuids, QBluetoothDeviceInfo::DataIncomplete);
+ info.setServiceUuids(uuids);
+ info.setRssi(rssi);
+ for (quint16 key : manufacturerData.keys())
+ info.setManufacturerData(key, manufacturerData.value(key));
info.setCached(true);
QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection,
@@ -739,6 +839,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
discoveredDevices.clear();
connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound,
this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice);
+ connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceDataChanged,
+ this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData);
connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished,
this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished);
worker->start();
@@ -759,7 +861,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop()
{
Q_Q(QBluetoothDeviceDiscoveryAgent);
if (worker) {
- worker->stop();
+ worker->stopLEWatcher();
disconnectAndClearWorker();
emit q->canceled();
}
@@ -793,6 +895,30 @@ void QBluetoothDeviceDiscoveryAgentPrivate::registerDevice(const QBluetoothDevic
emit q->deviceDiscovered(info);
}
+void QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData(const QBluetoothAddress &address,
+ QBluetoothDeviceInfo::Fields fields,
+ qint16 rssi,
+ ManufacturerData manufacturerData)
+{
+ if (fields.testFlag(QBluetoothDeviceInfo::Field::None))
+ return;
+
+ Q_Q(QBluetoothDeviceDiscoveryAgent);
+ for (QList<QBluetoothDeviceInfo>::iterator iter = discoveredDevices.begin();
+ iter != discoveredDevices.end(); ++iter) {
+ if (iter->address() == address) {
+ qCDebug(QT_BT_WINRT) << "Updating data for device" << iter->name() << iter->address();
+ if (fields.testFlag(QBluetoothDeviceInfo::Field::RSSI))
+ iter->setRssi(rssi);
+ if (fields.testFlag(QBluetoothDeviceInfo::Field::ManufacturerData))
+ for (quint16 key : manufacturerData.keys())
+ iter->setManufacturerData(key, manufacturerData.value(key));
+ emit q->deviceUpdated(*iter, fields);
+ return;
+ }
+ }
+}
+
void QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished()
{
Q_Q(QBluetoothDeviceDiscoveryAgent);
@@ -802,17 +928,18 @@ void QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished()
void QBluetoothDeviceDiscoveryAgentPrivate::disconnectAndClearWorker()
{
- Q_Q(QBluetoothDeviceDiscoveryAgent);
if (!worker)
return;
disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished,
- this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished);
+ this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished);
disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound,
- q, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered);
+ this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice);
+ disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceDataChanged,
+ this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData);
if (leScanTimer) {
disconnect(leScanTimer, &QTimer::timeout,
- worker, &QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery);
+ worker, &QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery);
}
worker.clear();
}
diff --git a/src/bluetooth/qbluetoothdeviceinfo.cpp b/src/bluetooth/qbluetoothdeviceinfo.cpp
index cc0d98a4..46df5c7b 100644
--- a/src/bluetooth/qbluetoothdeviceinfo.cpp
+++ b/src/bluetooth/qbluetoothdeviceinfo.cpp
@@ -647,7 +647,6 @@ QVector<quint16> QBluetoothDeviceInfo::manufacturerIds() const
*/
QByteArray QBluetoothDeviceInfo::manufacturerData(quint16 manufacturerId) const
{
- // TODO Currently not implemented on WinRT
Q_D(const QBluetoothDeviceInfo);
return d->manufacturerData.value(manufacturerId);
}
diff --git a/src/bluetooth/qbluetoothdeviceinfo.h b/src/bluetooth/qbluetoothdeviceinfo.h
index db0de7cd..11cb2bea 100644
--- a/src/bluetooth/qbluetoothdeviceinfo.h
+++ b/src/bluetooth/qbluetoothdeviceinfo.h
@@ -284,5 +284,8 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QBluetoothDeviceInfo::ServiceClasses)
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QBluetoothDeviceInfo)
+#ifdef QT_WINRT_BLUETOOTH
+Q_DECLARE_METATYPE(QBluetoothDeviceInfo::Fields)
+#endif
#endif
diff --git a/src/bluetooth/qbluetoothlocaldevice_android.cpp b/src/bluetooth/qbluetoothlocaldevice_android.cpp
index b46923eb..40e4c2d4 100644
--- a/src/bluetooth/qbluetoothlocaldevice_android.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_android.cpp
@@ -90,23 +90,16 @@ static QAndroidJniObject getDefaultAdapter()
QAndroidJniObject adapter = QAndroidJniObject::callStaticObjectMethod(
"android/bluetooth/BluetoothAdapter", "getDefaultAdapter",
"()Landroid/bluetooth/BluetoothAdapter;");
+ QAndroidJniExceptionCleaner exCleaner{QAndroidJniExceptionCleaner::OutputMode::Verbose};
if (!adapter.isValid()) {
- QAndroidJniEnvironment env;
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
+ exCleaner.clean();
// workaround stupid bt implementations where first call of BluetoothAdapter.getDefaultAdapter() always fails
adapter = QAndroidJniObject::callStaticObjectMethod(
"android/bluetooth/BluetoothAdapter", "getDefaultAdapter",
"()Landroid/bluetooth/BluetoothAdapter;");
- if (!adapter.isValid()) {
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
- }
+ if (!adapter.isValid())
+ exCleaner.clean();
}
return adapter;
}
diff --git a/src/bluetooth/qbluetoothlocaldevice_p.cpp b/src/bluetooth/qbluetoothlocaldevice_p.cpp
index 793a8311..fa4a509e 100644
--- a/src/bluetooth/qbluetoothlocaldevice_p.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_p.cpp
@@ -51,7 +51,7 @@ QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) :
QObject(parent),
d_ptr(new QBluetoothLocalDevicePrivate(this, QBluetoothAddress()))
{
-#if !defined(QT_IOS_BLUETOOTH) && !defined(QT_WINRT_BLUETOOTH)
+#if !defined(QT_IOS_BLUETOOTH)
printDummyWarning();
#endif
registerQBluetoothLocalDeviceMetaType();
@@ -85,11 +85,7 @@ void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode)
QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const
{
-#ifdef QT_WINRT_BLUETOOTH
- return HostConnectable;
-#else
return HostPoweredOff;
-#endif
}
QList<QBluetoothAddress> QBluetoothLocalDevice::connectedDevices() const
@@ -116,11 +112,7 @@ QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(
const QBluetoothAddress &address) const
{
Q_UNUSED(address);
-#ifdef QT_WINRT_BLUETOOTH
- return Paired;
-#else
return Unpaired;
-#endif
}
void QBluetoothLocalDevice::pairingConfirmation(bool confirmation)
diff --git a/src/bluetooth/qbluetoothlocaldevice_p.h b/src/bluetooth/qbluetoothlocaldevice_p.h
index e18169f9..28e7ed53 100644
--- a/src/bluetooth/qbluetoothlocaldevice_p.h
+++ b/src/bluetooth/qbluetoothlocaldevice_p.h
@@ -85,6 +85,21 @@ QT_END_NAMESPACE
#include <QtCore/QPair>
#endif
+#ifdef QT_WINRT_BLUETOOTH
+#include <wrl.h>
+
+namespace ABI {
+ namespace Windows {
+ namespace Devices {
+ namespace Bluetooth {
+ struct IBluetoothDeviceStatics;
+ struct IBluetoothLEDeviceStatics;
+ }
+ }
+ }
+}
+#endif
+
QT_BEGIN_NAMESPACE
extern void registerQBluetoothLocalDeviceMetaType();
@@ -232,7 +247,22 @@ public:
private:
QBluetoothLocalDevice *q_ptr;
};
-#elif !defined(QT_OSX_BLUETOOTH) // winrt and dummy backend
+#elif defined(QT_WINRT_BLUETOOTH)
+class QBluetoothLocalDevicePrivate : public QObject
+{
+ Q_DECLARE_PUBLIC(QBluetoothLocalDevice)
+public:
+ QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *q,
+ QBluetoothAddress = QBluetoothAddress());
+
+ bool isValid() const;
+
+private:
+ QBluetoothLocalDevice *q_ptr;
+ Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothDeviceStatics> mStatics;
+ Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothLEDeviceStatics> mLEStatics;
+};
+#elif !defined(QT_OSX_BLUETOOTH) // dummy backend
class QBluetoothLocalDevicePrivate : public QObject
{
public:
@@ -243,11 +273,7 @@ public:
bool isValid() const
{
-#ifndef QT_WINRT_BLUETOOTH
return false;
-#else
- return true;
-#endif
}
};
#endif
diff --git a/src/bluetooth/qbluetoothlocaldevice_winrt.cpp b/src/bluetooth/qbluetoothlocaldevice_winrt.cpp
new file mode 100644
index 00000000..ae794db0
--- /dev/null
+++ b/src/bluetooth/qbluetoothlocaldevice_winrt.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbluetoothlocaldevice.h"
+#include "qbluetoothaddress.h"
+
+#include "qbluetoothlocaldevice_p.h"
+
+#ifdef CLASSIC_APP_BUILD
+#define Q_OS_WINRT
+#endif
+#include <QtCore/qfunctions_winrt.h>
+
+#include <robuffer.h>
+#include <windows.devices.bluetooth.h>
+#include <wrl.h>
+
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Devices::Bluetooth;
+using namespace ABI::Windows::Devices::Enumeration;
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+
+QT_BEGIN_NAMESPACE
+
+template <class DeviceStatics, class OpResult, class Device, class Device2>
+ComPtr<IDeviceInformationPairing> getPairingInfo(ComPtr<DeviceStatics> deviceStatics,
+ const QBluetoothAddress &address)
+{
+ ComPtr<IAsyncOperation<OpResult *>> op;
+ if (!deviceStatics)
+ return nullptr;
+ HRESULT hr = deviceStatics->FromBluetoothAddressAsync(address.toUInt64(), &op);
+ RETURN_IF_FAILED("Could not obtain device from address", return nullptr);
+ ComPtr<Device> device;
+ hr = QWinRTFunctions::await(op, device.GetAddressOf(),
+ QWinRTFunctions::ProcessMainThreadEvents, 5000);
+ if (FAILED(hr) || !device) {
+ qErrnoWarning("Could not obtain device from address");
+ return nullptr;
+ }
+ ComPtr<Device2> device2;
+ hr = device.As(&device2);
+ RETURN_IF_FAILED("Could not cast device", return nullptr);
+ ComPtr<IDeviceInformation> deviceInfo;
+ hr = device2->get_DeviceInformation(&deviceInfo);
+ if (FAILED(hr) || !deviceInfo) {
+ qErrnoWarning("Could not obtain device information");
+ return nullptr;
+ }
+ ComPtr<IDeviceInformation2> deviceInfo2;
+ hr = deviceInfo.As(&deviceInfo2);
+ RETURN_IF_FAILED("Could not cast device information", return nullptr);
+ ComPtr<IDeviceInformationPairing> pairingInfo;
+ hr = deviceInfo2->get_Pairing(&pairingInfo);
+ RETURN_IF_FAILED("Could not obtain pairing information", return nullptr);
+ return pairingInfo;
+}
+
+QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) :
+ QObject(parent),
+ d_ptr(new QBluetoothLocalDevicePrivate(this, QBluetoothAddress()))
+{
+ registerQBluetoothLocalDeviceMetaType();
+}
+
+QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent) :
+ QObject(parent),
+ d_ptr(new QBluetoothLocalDevicePrivate(this, address))
+{
+ registerQBluetoothLocalDeviceMetaType();
+}
+
+QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *q, QBluetoothAddress)
+ : q_ptr(q)
+{
+ GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_BluetoothLEDevice).Get(), &mLEStatics);
+ GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_BluetoothDevice).Get(), &mStatics);
+}
+
+bool QBluetoothLocalDevicePrivate::isValid() const
+{
+ return (mStatics != nullptr && mLEStatics != nullptr);
+}
+
+void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing)
+{
+ Q_UNUSED(address);
+ Q_UNUSED(pairing);
+ QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ Q_ARG(QBluetoothLocalDevice::Error,
+ QBluetoothLocalDevice::PairingError));
+}
+
+QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(
+ const QBluetoothAddress &address) const
+{
+ if (!isValid() || address.isNull())
+ return QBluetoothLocalDevice::Unpaired;
+
+ ComPtr<IDeviceInformationPairing> pairingInfo = getPairingInfo<IBluetoothLEDeviceStatics,
+ BluetoothLEDevice, IBluetoothLEDevice, IBluetoothLEDevice2>(d_ptr->mLEStatics, address);
+ if (!pairingInfo)
+ pairingInfo = getPairingInfo<IBluetoothDeviceStatics, BluetoothDevice,
+ IBluetoothDevice, IBluetoothDevice2>(d_ptr->mStatics, address);
+ if (!pairingInfo)
+ return QBluetoothLocalDevice::Unpaired;
+ boolean isPaired;
+ HRESULT hr = pairingInfo->get_IsPaired(&isPaired);
+ RETURN_IF_FAILED("Could not obtain device pairing", return QBluetoothLocalDevice::Unpaired);
+ if (!isPaired)
+ return QBluetoothLocalDevice::Unpaired;
+
+ ComPtr<IDeviceInformationPairing2> pairingInfo2;
+ hr = pairingInfo.As(&pairingInfo2);
+ RETURN_IF_FAILED("Could not cast pairing info", return QBluetoothLocalDevice::Paired);
+ DevicePairingProtectionLevel protection = DevicePairingProtectionLevel_None;
+ hr = pairingInfo2->get_ProtectionLevel(&protection);
+ RETURN_IF_FAILED("Could not obtain pairing protection level", return QBluetoothLocalDevice::Paired);
+ if (protection == DevicePairingProtectionLevel_Encryption
+ || protection == DevicePairingProtectionLevel_EncryptionAndAuthentication)
+ return QBluetoothLocalDevice::AuthorizedPaired;
+ return QBluetoothLocalDevice::Paired;
+}
+
+void QBluetoothLocalDevice::pairingConfirmation(bool confirmation)
+{
+ Q_UNUSED(confirmation);
+}
+
+void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode)
+{
+ Q_UNUSED(mode);
+}
+
+QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const
+{
+ return HostConnectable;
+}
+
+QList<QBluetoothAddress> QBluetoothLocalDevice::connectedDevices() const
+{
+ return QList<QBluetoothAddress>();
+}
+
+void QBluetoothLocalDevice::powerOn()
+{
+}
+
+QString QBluetoothLocalDevice::name() const
+{
+ return QString();
+}
+
+QBluetoothAddress QBluetoothLocalDevice::address() const
+{
+ return QBluetoothAddress();
+}
+
+QList<QBluetoothHostInfo> QBluetoothLocalDevice::allDevices()
+{
+ QList<QBluetoothHostInfo> localDevices;
+ return localDevices;
+}
+
+QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothserver.cpp b/src/bluetooth/qbluetoothserver.cpp
index 75ac9979..daed5dc2 100644
--- a/src/bluetooth/qbluetoothserver.cpp
+++ b/src/bluetooth/qbluetoothserver.cpp
@@ -265,7 +265,7 @@ bool QBluetoothServer::isListening() const
{
Q_D(const QBluetoothServer);
-#if defined(QT_ANDROID_BLUETOOTH) || defined(QT_WINRT_BLUETOOTH)
+#if defined(QT_ANDROID_BLUETOOTH) || defined(QT_WINRT_BLUETOOTH) || defined(QT_OSX_BLUETOOTH)
return d->isListening();
#endif
diff --git a/src/bluetooth/qbluetoothserver_osx.mm b/src/bluetooth/qbluetoothserver_osx.mm
index eefaf4da..83d7e060 100644
--- a/src/bluetooth/qbluetoothserver_osx.mm
+++ b/src/bluetooth/qbluetoothserver_osx.mm
@@ -38,7 +38,7 @@
****************************************************************************/
#include "osx/osxbtsocketlistener_p.h"
-#include "qbluetoothserver_osx_p.h"
+#include "qbluetoothserver_p.h"
// The order is important: a workround for
// a private header included by private header
@@ -58,7 +58,6 @@
#include <QtCore/qglobal.h>
#include <QtCore/qmutex.h>
-// Import, since Obj-C headers do not have inclusion guards.
#include <Foundation/Foundation.h>
#include <limits>
@@ -67,7 +66,9 @@ QT_BEGIN_NAMESPACE
namespace {
-typedef QBluetoothServiceInfo QSInfo;
+using DarwinBluetooth::RetainPolicy;
+using ServiceInfo = QBluetoothServiceInfo;
+using ObjCListener = QT_MANGLE_NAMESPACE(OSXBTSocketListener);
QMap<quint16, QBluetoothServerPrivate *> &busyPSMs()
{
@@ -86,79 +87,89 @@ typedef QMap<quint16, QBluetoothServerPrivate *>::iterator ServerMapIterator;
}
-QBluetoothServerPrivate::QBluetoothServerPrivate(QSInfo::Protocol type, QBluetoothServer *q)
- : serverType(type),
- q_ptr(q),
- lastError(QBluetoothServer::NoError),
- port(0),
- maxPendingConnections(1)
+QBluetoothServerPrivate::QBluetoothServerPrivate(ServiceInfo::Protocol type,
+ QBluetoothServer *parent)
+ : socket(nullptr),
+ maxPendingConnections(1),
+ securityFlags(QBluetooth::NoSecurity),
+ serverType(type),
+ q_ptr(parent),
+ m_lastError(QBluetoothServer::NoError),
+ port(0)
{
- Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
- if (serverType == QSInfo::UnknownProtocol)
+ if (serverType == ServiceInfo::UnknownProtocol)
qCWarning(QT_BT_OSX) << "unknown protocol";
}
QBluetoothServerPrivate::~QBluetoothServerPrivate()
{
- // Actually, not good, but lock must be acquired.
- // TODO: test this.
const QMutexLocker lock(&channelMapMutex());
unregisterServer(this);
}
-void QBluetoothServerPrivate::_q_newConnection()
-{
- // Noop, we have openNotify for this.
-}
-
bool QBluetoothServerPrivate::startListener(quint16 realPort)
{
Q_ASSERT_X(realPort, Q_FUNC_INFO, "invalid port");
- if (serverType == QSInfo::UnknownProtocol) {
+ if (serverType == ServiceInfo::UnknownProtocol) {
qCWarning(QT_BT_OSX) << "invalid protocol";
return false;
}
- if (!listener)
- listener.reset([[ObjCListener alloc] initWithListener:this]);
+ if (!listener) {
+ listener.reset([[ObjCListener alloc] initWithListener:this],
+ RetainPolicy::noInitialRetain);
+ }
bool result = false;
- if (serverType == QSInfo::RfcommProtocol)
- result = [listener listenRFCOMMConnectionsWithChannelID:realPort];
+ if (serverType == ServiceInfo::RfcommProtocol)
+ result = [listener.getAs<ObjCListener>() listenRFCOMMConnectionsWithChannelID:realPort];
else
- result = [listener listenL2CAPConnectionsWithPSM:realPort];
+ result = [listener.getAs<ObjCListener>() listenL2CAPConnectionsWithPSM:realPort];
if (!result)
- listener.reset(nil);
+ listener.reset();
return result;
}
+bool QBluetoothServerPrivate::isListening() const
+{
+ if (serverType == ServiceInfo::UnknownProtocol)
+ return false;
+
+ const QMutexLocker lock(&QBluetoothServerPrivate::channelMapMutex());
+ return QBluetoothServerPrivate::registeredServer(q_ptr->serverPort(), serverType);
+}
+
void QBluetoothServerPrivate::stopListener()
{
- listener.reset(nil);
+ listener.reset();
}
-void QBluetoothServerPrivate::openNotify(IOBluetoothRFCOMMChannel *channel)
+void QBluetoothServerPrivate::openNotifyRFCOMM(void *generic)
{
+ auto channel = static_cast<IOBluetoothRFCOMMChannel *>(generic);
+
Q_ASSERT_X(listener, Q_FUNC_INFO, "invalid listener (nil)");
Q_ASSERT_X(channel, Q_FUNC_INFO, "invalid channel (nil)");
Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
- PendingConnection newConnection(channel, true);
+ PendingConnection newConnection(channel, RetainPolicy::doInitialRetain);
pendingConnections.append(newConnection);
emit q_ptr->newConnection();
}
-void QBluetoothServerPrivate::openNotify(IOBluetoothL2CAPChannel *channel)
+void QBluetoothServerPrivate::openNotifyL2CAP(void *generic)
{
+ auto channel = static_cast<IOBluetoothL2CAPChannel *>(generic);
+
Q_ASSERT_X(listener, Q_FUNC_INFO, "invalid listener (nil)");
Q_ASSERT_X(channel, Q_FUNC_INFO, "invalid channel (nil)");
Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
- PendingConnection newConnection(channel, true);
+ PendingConnection newConnection(channel, RetainPolicy::doInitialRetain);
pendingConnections.append(newConnection);
emit q_ptr->newConnection();
@@ -209,11 +220,11 @@ void QBluetoothServerPrivate::registerServer(QBluetoothServerPrivate *server, qu
// External lock is required + port must be free.
Q_ASSERT_X(server, Q_FUNC_INFO, "invalid server (null)");
- const QSInfo::Protocol type = server->serverType;
- if (type == QSInfo::RfcommProtocol) {
+ const ServiceInfo::Protocol type = server->serverType;
+ if (type == ServiceInfo::RfcommProtocol) {
Q_ASSERT_X(!channelIsBusy(port), Q_FUNC_INFO, "port is busy");
busyChannels()[port] = server;
- } else if (type == QSInfo::L2capProtocol) {
+ } else if (type == ServiceInfo::L2capProtocol) {
Q_ASSERT_X(!psmIsBusy(port), Q_FUNC_INFO, "port is busy");
busyPSMs()[port] = server;
} else {
@@ -225,11 +236,11 @@ void QBluetoothServerPrivate::registerServer(QBluetoothServerPrivate *server, qu
QBluetoothServerPrivate *QBluetoothServerPrivate::registeredServer(quint16 port, QBluetoothServiceInfo::Protocol protocol)
{
// Eternal lock is required.
- if (protocol == QSInfo::RfcommProtocol) {
+ if (protocol == ServiceInfo::RfcommProtocol) {
ServerMapIterator it = busyChannels().find(port);
if (it != busyChannels().end())
return it.value();
- } else if (protocol == QSInfo::L2capProtocol) {
+ } else if (protocol == ServiceInfo::L2capProtocol) {
ServerMapIterator it = busyPSMs().find(port);
if (it != busyPSMs().end())
return it.value();
@@ -243,17 +254,17 @@ QBluetoothServerPrivate *QBluetoothServerPrivate::registeredServer(quint16 port,
void QBluetoothServerPrivate::unregisterServer(QBluetoothServerPrivate *server)
{
// External lock is required.
- const QSInfo::Protocol type = server->serverType;
+ const ServiceInfo::Protocol type = server->serverType;
const quint16 port = server->port;
- if (type == QSInfo::RfcommProtocol) {
+ if (type == ServiceInfo::RfcommProtocol) {
ServerMapIterator it = busyChannels().find(port);
if (it != busyChannels().end()) {
busyChannels().erase(it);
} else {
qCWarning(QT_BT_OSX) << "server is not registered";
}
- } else if (type == QSInfo::L2capProtocol) {
+ } else if (type == ServiceInfo::L2capProtocol) {
ServerMapIterator it = busyPSMs().find(port);
if (it != busyPSMs().end()) {
busyPSMs().erase(it);
@@ -265,21 +276,9 @@ void QBluetoothServerPrivate::unregisterServer(QBluetoothServerPrivate *server)
}
}
-
-QBluetoothServer::QBluetoothServer(QSInfo::Protocol serverType, QObject *parent)
- : QObject(parent),
- d_ptr(new QBluetoothServerPrivate(serverType, this))
-{
-}
-
-QBluetoothServer::~QBluetoothServer()
-{
- delete d_ptr;
-}
-
void QBluetoothServer::close()
{
- d_ptr->listener.reset(nil);
+ d_ptr->listener.reset();
// Needs a lock :(
const QMutexLocker lock(&d_ptr->channelMapMutex());
@@ -289,8 +288,6 @@ void QBluetoothServer::close()
bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port)
{
- typedef QBluetoothServerPrivate::ObjCListener ObjCListener;
-
OSXBluetooth::qt_test_iobluetooth_runloop();
if (d_ptr->listener) {
@@ -303,7 +300,7 @@ bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port)
qCWarning(QT_BT_OSX) << "device does not support Bluetooth or"
<< address.toString()
<< "is not a valid local adapter";
- d_ptr->lastError = UnknownError;
+ d_ptr->m_lastError = UnknownError;
emit error(UnknownError);
return false;
}
@@ -311,53 +308,53 @@ bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port)
const QBluetoothLocalDevice::HostMode hostMode = device.hostMode();
if (hostMode == QBluetoothLocalDevice::HostPoweredOff) {
qCWarning(QT_BT_OSX) << "Bluetooth device is powered off";
- d_ptr->lastError = PoweredOffError;
+ d_ptr->m_lastError = PoweredOffError;
emit error(PoweredOffError);
return false;
}
- const QSInfo::Protocol type = d_ptr->serverType;
+ const ServiceInfo::Protocol type = d_ptr->serverType;
- if (type == QSInfo::UnknownProtocol) {
+ if (type == ServiceInfo::UnknownProtocol) {
qCWarning(QT_BT_OSX) << "invalid protocol";
- d_ptr->lastError = UnsupportedProtocolError;
- emit error(d_ptr->lastError);
+ d_ptr->m_lastError = UnsupportedProtocolError;
+ emit error(d_ptr->m_lastError);
return false;
}
- d_ptr->lastError = QBluetoothServer::NoError;
+ d_ptr->m_lastError = QBluetoothServer::NoError;
// Now we have to register a (fake) port, doing a proper (?) lock.
const QMutexLocker lock(&d_ptr->channelMapMutex());
if (port) {
- if (type == QSInfo::RfcommProtocol) {
+ if (type == ServiceInfo::RfcommProtocol) {
if (d_ptr->channelIsBusy(port)) {
qCWarning(QT_BT_OSX) << "server port:" << port
<< "already registered";
- d_ptr->lastError = ServiceAlreadyRegisteredError;
+ d_ptr->m_lastError = ServiceAlreadyRegisteredError;
}
} else {
if (d_ptr->psmIsBusy(port)) {
qCWarning(QT_BT_OSX) << "server port:" << port
<< "already registered";
- d_ptr->lastError = ServiceAlreadyRegisteredError;
+ d_ptr->m_lastError = ServiceAlreadyRegisteredError;
}
}
} else {
- type == QSInfo::RfcommProtocol ? port = d_ptr->findFreeChannel()
+ type == ServiceInfo::RfcommProtocol ? port = d_ptr->findFreeChannel()
: port = d_ptr->findFreePSM();
}
- if (d_ptr->lastError != QBluetoothServer::NoError) {
- emit error(d_ptr->lastError);
+ if (d_ptr->m_lastError != QBluetoothServer::NoError) {
+ emit error(d_ptr->m_lastError);
return false;
}
if (!port) {
qCWarning(QT_BT_OSX) << "all ports are busy";
- d_ptr->lastError = ServiceAlreadyRegisteredError;
- emit error(d_ptr->lastError);
+ d_ptr->m_lastError = ServiceAlreadyRegisteredError;
+ emit error(d_ptr->m_lastError);
return false;
}
@@ -365,82 +362,17 @@ bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port)
// (provided after a service was registered).
d_ptr->port = port;
d_ptr->registerServer(d_ptr, port);
- d_ptr->listener.reset([[ObjCListener alloc] initWithListener:d_ptr]);
+ d_ptr->listener.reset([[ObjCListener alloc] initWithListener:d_ptr],
+ RetainPolicy::noInitialRetain);
return true;
}
-QBluetoothServiceInfo QBluetoothServer::listen(const QBluetoothUuid &uuid, const QString &serviceName)
-{
- if (!listen())
- return QBluetoothServiceInfo();
-
- QBluetoothServiceInfo serviceInfo;
- serviceInfo.setAttribute(QSInfo::ServiceName, serviceName);
- QBluetoothServiceInfo::Sequence publicBrowse;
- publicBrowse << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
- serviceInfo.setAttribute(QSInfo::BrowseGroupList, publicBrowse);
-
- QSInfo::Sequence profileSequence;
- QSInfo::Sequence classId;
- classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
- classId << QVariant::fromValue(quint16(0x100));
- profileSequence.append(QVariant::fromValue(classId));
- serviceInfo.setAttribute(QSInfo::BluetoothProfileDescriptorList, profileSequence);
-
- classId.clear();
- classId << QVariant::fromValue(uuid);
- classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
- serviceInfo.setAttribute(QSInfo::ServiceClassIds, classId);
- serviceInfo.setServiceUuid(uuid);
-
- QSInfo::Sequence protocolDescriptorList;
- QSInfo::Sequence protocol;
- protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap));
- if (d_ptr->serverType == QSInfo::L2capProtocol)
- protocol << QVariant::fromValue(serverPort());
- protocolDescriptorList.append(QVariant::fromValue(protocol));
- protocol.clear();
-
- if (d_ptr->serverType == QBluetoothServiceInfo::RfcommProtocol) {
- protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
- << QVariant::fromValue(quint8(serverPort()));
- protocolDescriptorList.append(QVariant::fromValue(protocol));
- }
-
- serviceInfo.setAttribute(QSInfo::ProtocolDescriptorList,
- protocolDescriptorList);
-
-
- // It's now up to a service info to acquire a real PSM/channel ID
- // (provided by IOBluetooth) and start a listener.
- if (!serviceInfo.registerService())
- return QBluetoothServiceInfo();
-
- return serviceInfo;
-}
-
-bool QBluetoothServer::isListening() const
-{
- if (d_ptr->serverType == QSInfo::UnknownProtocol)
- return false;
-
- const QMutexLocker lock(&QBluetoothServerPrivate::channelMapMutex());
- return QBluetoothServerPrivate::registeredServer(serverPort(), d_ptr->serverType);
-}
-
void QBluetoothServer::setMaxPendingConnections(int numConnections)
{
- // That's a 'fake' limit, it affects nothing.
d_ptr->maxPendingConnections = numConnections;
}
-int QBluetoothServer::maxPendingConnections() const
-{
- // That's a 'fake' limit, it affects nothing.
- return d_ptr->maxPendingConnections;
-}
-
bool QBluetoothServer::hasPendingConnections() const
{
return d_ptr->pendingConnections.size();
@@ -457,11 +389,11 @@ QBluetoothSocket *QBluetoothServer::nextPendingConnection()
// Remove it even if we have some errors below.
d_ptr->pendingConnections.pop_front();
- if (d_ptr->serverType == QSInfo::RfcommProtocol) {
- if (!newSocket->d_ptr->setChannel(static_cast<IOBluetoothRFCOMMChannel *>(channel)))
+ if (d_ptr->serverType == ServiceInfo::RfcommProtocol) {
+ if (!static_cast<QBluetoothSocketPrivate *>(newSocket->d_ptr)->setRFCOMChannel(channel.getAs<IOBluetoothRFCOMMChannel>()))
return nullptr;
} else {
- if (!newSocket->d_ptr->setChannel(static_cast<IOBluetoothL2CAPChannel *>(channel)))
+ if (!static_cast<QBluetoothSocketPrivate *>(newSocket->d_ptr)->setL2CAPChannel(channel.getAs<IOBluetoothL2CAPChannel>()))
return nullptr;
}
@@ -481,25 +413,13 @@ quint16 QBluetoothServer::serverPort() const
void QBluetoothServer::setSecurityFlags(QBluetooth::SecurityFlags security)
{
Q_UNUSED(security)
- // Not implemented (yet?)
+ Q_UNIMPLEMENTED();
}
QBluetooth::SecurityFlags QBluetoothServer::securityFlags() const
{
- // Not implemented (yet?)
+ Q_UNIMPLEMENTED();
return QBluetooth::NoSecurity;
}
-QSInfo::Protocol QBluetoothServer::serverType() const
-{
- return d_ptr->serverType;
-}
-
-QBluetoothServer::Error QBluetoothServer::error() const
-{
- return d_ptr->lastError;
-}
-
-#include "moc_qbluetoothserver.cpp"
-
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothserver_p.h b/src/bluetooth/qbluetoothserver_p.h
index 5ace7f75..d14dc7b4 100644
--- a/src/bluetooth/qbluetoothserver_p.h
+++ b/src/bluetooth/qbluetoothserver_p.h
@@ -77,15 +77,25 @@ class ServerAcceptanceThread;
#include <windows.networking.sockets.h>
#endif
+#ifdef QT_OSX_BLUETOOTH
+
+#include "osx/btdelegates_p.h"
+#include "osx/btraii_p.h"
+
+#include <QtCore/qvector.h>
+
+#endif // QT_OSX_BLUETOOTH
+
QT_BEGIN_NAMESPACE
class QBluetoothAddress;
class QBluetoothSocket;
class QBluetoothServer;
-#ifndef QT_OSX_BLUETOOTH
-
class QBluetoothServerPrivate
+#ifdef QT_OSX_BLUETOOTH
+ : public DarwinBluetooth::SocketListener
+#endif
{
Q_DECLARE_PUBLIC(QBluetoothServer)
@@ -142,9 +152,53 @@ public:
bool initiateActiveListening(const QString &serviceName);
bool deactivateActiveListening();
#endif
-};
-#endif //QT_OSX_BLUETOOTH
+#ifdef QT_OSX_BLUETOOTH
+
+public:
+
+ friend class QBluetoothServer;
+ friend class QBluetoothServiceInfoPrivate;
+
+private:
+ bool startListener(quint16 realPort);
+ void stopListener();
+ bool isListening() const;
+
+ // SocketListener (delegate):
+ void openNotifyRFCOMM(void *channel) override;
+ void openNotifyL2CAP(void *channel) override;
+
+ // Either a "temporary" channelID/PSM assigned by QBluetoothServer::listen,
+ // or a real channelID/PSM returned by IOBluetooth after we've registered
+ // a service.
+ quint16 port;
+
+ DarwinBluetooth::StrongReference listener;
+
+ // These static functions below
+ // deal with differences between bluetooth sockets
+ // (bluez and QtBluetooth's API) and IOBluetooth, where it's not possible
+ // to have a real PSM/channelID _before_ a service is registered,
+ // the solution - "fake" ports.
+ // These functions require external locking - using channelMapMutex.
+ static QMutex &channelMapMutex();
+
+ static bool channelIsBusy(quint16 channelID);
+ static quint16 findFreeChannel();
+
+ static bool psmIsBusy(quint16 psm);
+ static quint16 findFreePSM();
+
+ static void registerServer(QBluetoothServerPrivate *server, quint16 port);
+ static QBluetoothServerPrivate *registeredServer(quint16 port, QBluetoothServiceInfo::Protocol protocol);
+ static void unregisterServer(QBluetoothServerPrivate *server);
+
+ using PendingConnection = DarwinBluetooth::StrongReference;
+ QVector<PendingConnection> pendingConnections;
+
+#endif // QT_OSX_BLUETOOTH
+};
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.cpp b/src/bluetooth/qbluetoothservicediscoveryagent.cpp
index a5fc7654..e76c2311 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent.cpp
@@ -169,6 +169,11 @@ QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(QObject *parent
\note On WinRT the passed adapter address will be ignored.
+ \note On Android passing any \a deviceAdapter address is meaningless as Android 6.0 or later does not publish
+ the local Bluetooth address anymore. Subsequently, the passed adapter address can never be matched
+ against the local adapter address. Therefore the subsequent call to \l start() will always trigger
+ \l InvalidBluetoothAdapterError.
+
\sa error()
*/
QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, QObject *parent)
@@ -303,6 +308,13 @@ QBluetoothAddress QBluetoothServiceDiscoveryAgent::remoteAddress() const
return QBluetoothAddress();
}
+namespace OSXBluetooth {
+
+void qt_test_iobluetooth_runloop();
+
+}
+
+
/*!
Starts service discovery. \a mode specifies the type of service discovery to perform.
@@ -313,6 +325,10 @@ QBluetoothAddress QBluetoothServiceDiscoveryAgent::remoteAddress() const
void QBluetoothServiceDiscoveryAgent::start(DiscoveryMode mode)
{
Q_D(QBluetoothServiceDiscoveryAgent);
+#ifdef QT_OSX_BLUETOOTH
+ // Make sure we are on the right thread/have a run loop:
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+#endif
if (d->discoveryState() == QBluetoothServiceDiscoveryAgentPrivate::Inactive
&& d->error != InvalidBluetoothAdapterError) {
@@ -568,7 +584,8 @@ bool QBluetoothServiceDiscoveryAgentPrivate::isDuplicatedService(
const QBluetoothServiceInfo &info = discoveredServices.at(j);
if (info.device() == serviceInfo.device()
&& info.serviceClassUuids() == serviceInfo.serviceClassUuids()
- && info.serviceUuid() == serviceInfo.serviceUuid()) {
+ && info.serviceUuid() == serviceInfo.serviceUuid()
+ && info.serverChannel() == serviceInfo.serverChannel()) {
return true;
}
}
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
index ce2911d3..3ab0d580 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
@@ -47,6 +47,7 @@
#include <QtBluetooth/QBluetoothServiceDiscoveryAgent>
#include "qbluetoothservicediscoveryagent_p.h"
+#include "qbluetoothsocket_android_p.h"
#include "android/servicediscoverybroadcastreceiver_p.h"
#include "android/localdevicebroadcastreceiver_p.h"
@@ -55,21 +56,33 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(
- QBluetoothServiceDiscoveryAgent *qp, const QBluetoothAddress &/*deviceAdapter*/)
+ QBluetoothServiceDiscoveryAgent *qp, const QBluetoothAddress &deviceAdapter)
: error(QBluetoothServiceDiscoveryAgent::NoError),
+ m_deviceAdapterAddress(deviceAdapter),
state(Inactive),
mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery),
singleDevice(false),
q_ptr(qp)
{
- QList<QBluetoothHostInfo> devices = QBluetoothLocalDevice::allDevices();
- Q_ASSERT(devices.count() <= 1); //Android only supports one device at the moment
-
- if (devices.isEmpty()) {
- error = QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError;
- errorString = QBluetoothServiceDiscoveryAgent::tr("Invalid Bluetooth adapter address");
- return;
+ // If a specific adapter address is requested we need to check it matches
+ // the current local adapter. If it does not match we emit
+ // InvalidBluetoothAdapterError when calling start()
+
+ bool createAdapter = true;
+ if (!deviceAdapter.isNull()) {
+ const QList<QBluetoothHostInfo> devices = QBluetoothLocalDevice::allDevices();
+ if (devices.isEmpty()) {
+ createAdapter = false;
+ } else {
+ auto match = [deviceAdapter](const QBluetoothHostInfo& info) {
+ return info.address() == deviceAdapter;
+ };
+
+ auto result = std::find_if(devices.begin(), devices.end(), match);
+ if (result == devices.end())
+ createAdapter = false;
+ }
}
if (QtAndroidPrivate::androidSdkVersion() < 15)
@@ -84,7 +97,8 @@ QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(
The logic below must change once there is more than one adapter.
*/
- btAdapter = QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothAdapter",
+ if (createAdapter)
+ btAdapter = QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothAdapter",
"getDefaultAdapter",
"()Landroid/bluetooth/BluetoothAdapter;");
if (!btAdapter.isValid())
@@ -110,8 +124,15 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr
Q_Q(QBluetoothServiceDiscoveryAgent);
if (!btAdapter.isValid()) {
- error = QBluetoothServiceDiscoveryAgent::UnknownError;
- errorString = QBluetoothServiceDiscoveryAgent::tr("Platform does not support Bluetooth");
+ if (m_deviceAdapterAddress.isNull()) {
+ error = QBluetoothServiceDiscoveryAgent::UnknownError;
+ errorString = QBluetoothServiceDiscoveryAgent::tr("Platform does not support Bluetooth");
+ } else {
+ // specific adapter was requested which does not match the locally
+ // existing adapter
+ error = QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError;
+ errorString = QBluetoothServiceDiscoveryAgent::tr("Invalid Bluetooth adapter address");
+ }
//abort any outstanding discoveries
discoveredDevices.clear();
@@ -315,42 +336,62 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_processFetchedUuids(
void QBluetoothServiceDiscoveryAgentPrivate::populateDiscoveredServices(const QBluetoothDeviceInfo &remoteDevice, const QList<QBluetoothUuid> &uuids)
{
- /* Android doesn't provide decent SDP data. A list of uuids is close to meaning-less
+ /* Android doesn't provide decent SDP data. A flat list of uuids is all we get.
*
* The following approach is chosen:
* - If we see an SPP service class and we see
- * one or more custom uuids we match them up. Such services will always be SPP services.
+ * one or more custom uuids we match them up. Such services will always
+ * be SPP services. There is the chance that a custom uuid is eronously
+ * mapped as being an SPP service. In addition, the SPP uuid will be mapped as
+ * standalone SPP service.
* - If we see a custom uuid but no SPP uuid then we return
- * BluetoothServiceInfo instance with just a servuceUuid (no service class set)
+ * BluetoothServiceInfo instance with just a serviceUuid (no service class set)
+ * - If we don't find any custom uuid but the SPP uuid, we return a
+ * BluetoothServiceInfo instance where classId and serviceUuid() are set to SPP.
* - Any other service uuid will stand on its own.
* */
Q_Q(QBluetoothServiceDiscoveryAgent);
//find SPP and custom uuid
- QBluetoothUuid uuid;
- int sppIndex = -1;
+ bool haveSppClass = false;
QVector<int> customUuids;
for (int i = 0; i < uuids.count(); i++) {
- uuid = uuids.at(i);
+ const QBluetoothUuid uuid = uuids.at(i);
if (uuid.isNull())
continue;
//check for SPP protocol
bool ok = false;
- quint16 uuid16 = uuid.toUInt16(&ok);
- if (ok && uuid16 == QBluetoothUuid::SerialPort)
- sppIndex = i;
+ auto uuid16 = uuid.toUInt16(&ok);
+ haveSppClass |= ok && uuid16 == QBluetoothUuid::SerialPort;
//check for custom uuid
if (uuid.minimumSize() == 16)
customUuids.append(i);
}
+ auto rfcommProtocolDescriptorList = []() -> QBluetoothServiceInfo::Sequence {
+ QBluetoothServiceInfo::Sequence protocol;
+ protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
+ << QVariant::fromValue(0);
+ return protocol;
+ };
+
+ auto sppProfileDescriptorList = []() -> QBluetoothServiceInfo::Sequence {
+ QBluetoothServiceInfo::Sequence profileSequence;
+ QBluetoothServiceInfo::Sequence classId;
+ classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
+ classId << QVariant::fromValue(quint16(0x100));
+ profileSequence.append(QVariant::fromValue(classId));
+ return profileSequence;
+ };
+
for (int i = 0; i < uuids.count(); i++) {
- if (i == sppIndex && !customUuids.isEmpty())
+ const QBluetoothUuid &uuid = uuids.at(i);
+ if (uuid.isNull())
continue;
QBluetoothServiceInfo serviceInfo;
@@ -363,52 +404,38 @@ void QBluetoothServiceDiscoveryAgentPrivate::populateDiscoveredServices(const QB
protocolDescriptorList.append(QVariant::fromValue(protocol));
}
- if (customUuids.contains(i) && sppIndex > -1) {
+ if (customUuids.contains(i) && haveSppClass) {
//we have a custom uuid of service class type SPP
//set rfcomm protocol
- QBluetoothServiceInfo::Sequence protocol;
- protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
- << QVariant::fromValue(0);
- protocolDescriptorList.append(QVariant::fromValue(protocol));
+ protocolDescriptorList.append(QVariant::fromValue(rfcommProtocolDescriptorList()));
- QBluetoothServiceInfo::Sequence profileSequence;
- QBluetoothServiceInfo::Sequence classId;
- classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
- classId << QVariant::fromValue(quint16(0x100));
- profileSequence.append(QVariant::fromValue(classId));
+ //set SPP profile descriptor list
serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList,
- profileSequence);
+ sppProfileDescriptorList());
- classId.clear();
+ QBluetoothServiceInfo::Sequence classId;
//set SPP service class uuid
- classId << QVariant::fromValue(uuids.at(i));
+ classId << QVariant::fromValue(uuid);
classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
serviceInfo.setServiceName(QBluetoothServiceDiscoveryAgent::tr("Serial Port Profile"));
- serviceInfo.setServiceUuid(uuids.at(i));
- } else if (sppIndex == i && customUuids.isEmpty()) {
+ serviceInfo.setServiceUuid(uuid);
+ } else if (uuid == QBluetoothUuid{QBluetoothUuid::SerialPort}) {
//set rfcomm protocol
- QBluetoothServiceInfo::Sequence protocol;
- protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
- << QVariant::fromValue(0);
- protocolDescriptorList.append(QVariant::fromValue(protocol));
+ protocolDescriptorList.append(QVariant::fromValue(rfcommProtocolDescriptorList()));
- QBluetoothServiceInfo::Sequence profileSequence;
- QBluetoothServiceInfo::Sequence classId;
- classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
- classId << QVariant::fromValue(quint16(0x100));
- profileSequence.append(QVariant::fromValue(classId));
+ //set SPP profile descriptor list
serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList,
- profileSequence);
+ sppProfileDescriptorList());
//also we need to set the custom uuid to the SPP uuid
//otherwise QBluetoothSocket::connectToService() would fail due to a missing service uuid
- serviceInfo.setServiceUuid(uuids.at(i));
+ serviceInfo.setServiceUuid(uuid);
} else if (customUuids.contains(i)) {
//custom uuid but no serial port
- serviceInfo.setServiceUuid(uuids.at(i));
+ serviceInfo.setServiceUuid(uuid);
}
serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList);
@@ -419,18 +446,20 @@ void QBluetoothServiceDiscoveryAgentPrivate::populateDiscoveredServices(const QB
if (!customUuids.contains(i)) {
//if we don't have custom uuid use it as class id as well
QBluetoothServiceInfo::Sequence classId;
- classId << QVariant::fromValue(uuids.at(i));
+ classId << QVariant::fromValue(uuid);
serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
- QBluetoothUuid::ServiceClassUuid clsId
- = static_cast<QBluetoothUuid::ServiceClassUuid>(uuids.at(i).toUInt16());
+ auto clsId = QBluetoothUuid::ServiceClassUuid(uuid.toUInt16());
serviceInfo.setServiceName(QBluetoothUuid::serviceClassToString(clsId));
}
//Check if the service is in the uuidFilter
if (!uuidFilter.isEmpty()) {
bool match = uuidFilter.contains(serviceInfo.serviceUuid());
- for (const auto &uuid : qAsConst(uuidFilter))
+ match |= uuidFilter.contains(QBluetoothSocketPrivateAndroid::reverseUuid(serviceInfo.serviceUuid()));
+ for (const auto &uuid : qAsConst(uuidFilter)) {
match |= serviceInfo.serviceClassUuids().contains(uuid);
+ match |= serviceInfo.serviceClassUuids().contains(QBluetoothSocketPrivateAndroid::reverseUuid(uuid));
+ }
if (!match)
continue;
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm b/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm
index bd9cc7f3..d8decae1 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm
@@ -37,6 +37,7 @@
**
****************************************************************************/
+#include "qbluetoothservicediscoveryagent_p.h"
#include "qbluetoothservicediscoveryagent.h"
#include "qbluetoothdevicediscoveryagent.h"
#include "qbluetoothlocaldevice.h"
@@ -57,132 +58,41 @@
QT_BEGIN_NAMESPACE
-class QBluetoothServiceDiscoveryAgentPrivate : public QObject, public OSXBluetooth::SDPInquiryDelegate
-{
- friend class QBluetoothServiceDiscoveryAgent;
-public:
- enum DiscoveryState {
- Inactive,
- DeviceDiscovery,
- ServiceDiscovery,
- };
-
- QBluetoothServiceDiscoveryAgentPrivate(QBluetoothServiceDiscoveryAgent *qp,
- const QBluetoothAddress &localAddress);
-
- void startDeviceDiscovery();
- void stopDeviceDiscovery();
-
- void startServiceDiscovery();
- void stopServiceDiscovery();
-
- DiscoveryState discoveryState();
- void setDiscoveryMode(QBluetoothServiceDiscoveryAgent::DiscoveryMode m);
- QBluetoothServiceDiscoveryAgent::DiscoveryMode DiscoveryMode();
-
- void _q_deviceDiscovered(const QBluetoothDeviceInfo &info);
- void _q_deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error);
- void _q_deviceDiscoveryFinished();
-
-private:
- // SDPInquiryDelegate:
- void SDPInquiryFinished(IOBluetoothDevice *device) override;
- void SDPInquiryError(IOBluetoothDevice *device, IOReturn errorCode) override;
-
- void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress);
- void setupDeviceDiscoveryAgent();
- bool isDuplicatedService(const QBluetoothServiceInfo &serviceInfo) const;
- void serviceDiscoveryFinished();
-
- bool serviceHasMathingUuid(const QBluetoothServiceInfo &serviceInfo) const;
-
- QBluetoothServiceDiscoveryAgent *q_ptr;
+namespace {
- QBluetoothServiceDiscoveryAgent::Error error;
- QString errorString;
+using DarwinBluetooth::RetainPolicy;
+using ObjCServiceInquiry = QT_MANGLE_NAMESPACE(OSXBTSDPInquiry);
- QList<QBluetoothDeviceInfo> discoveredDevices;
- QList<QBluetoothServiceInfo> discoveredServices;
- QList<QBluetoothUuid> uuidFilter;
-
- bool singleDevice;
- QBluetoothAddress deviceAddress;
- QBluetoothAddress localAdapterAddress;
-
- DiscoveryState state;
- QBluetoothServiceDiscoveryAgent::DiscoveryMode discoveryMode;
-
- QScopedPointer<QBluetoothDeviceDiscoveryAgent> deviceDiscoveryAgent;
- OSXBluetooth::ObjCScopedPointer<ObjCServiceInquiry> serviceInquiry;
-};
+}
QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(
QBluetoothServiceDiscoveryAgent *qp, const QBluetoothAddress &localAddress) :
- q_ptr(qp),
+
error(QBluetoothServiceDiscoveryAgent::NoError),
- singleDevice(false),
- localAdapterAddress(localAddress),
+ m_deviceAdapterAddress(localAddress),
state(Inactive),
- discoveryMode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery)
-{
- serviceInquiry.reset([[ObjCServiceInquiry alloc] initWithDelegate:this]);
-}
+ mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery),
+ singleDevice(false),
+ q_ptr(qp)
-void QBluetoothServiceDiscoveryAgentPrivate::startDeviceDiscovery()
{
- Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
- Q_ASSERT_X(state == Inactive, Q_FUNC_INFO, "invalid state");
- Q_ASSERT_X(error != QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError,
- Q_FUNC_INFO, "invalid bluetooth adapter");
-
- Q_ASSERT_X(deviceDiscoveryAgent.isNull(), "startDeviceDiscovery()",
- "discovery agent already exists");
-
- state = DeviceDiscovery;
-
- setupDeviceDiscoveryAgent();
- deviceDiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::ClassicMethod);
+ Q_ASSERT(q_ptr);
+ serviceInquiry.reset([[ObjCServiceInquiry alloc] initWithDelegate:this], RetainPolicy::noInitialRetain);
}
-void QBluetoothServiceDiscoveryAgentPrivate::stopDeviceDiscovery()
+QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate()
{
- Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
- Q_ASSERT_X(!deviceDiscoveryAgent.isNull(), Q_FUNC_INFO,
- "invalid device discovery agent (null)");
- Q_ASSERT_X(state == DeviceDiscovery, Q_FUNC_INFO, "invalid state");
-
- deviceDiscoveryAgent->stop();
- deviceDiscoveryAgent.reset(nullptr);
- state = Inactive;
-
- emit q_ptr->canceled();
}
-void QBluetoothServiceDiscoveryAgentPrivate::startServiceDiscovery()
+void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &deviceAddress)
{
- // Any of 'Inactive'/'DeviceDiscovery'/'ServiceDiscovery' states
- // are possible.
-
- Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
- Q_ASSERT_X(error != QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError,
- Q_FUNC_INFO, "invalid bluetooth adapter");
-
- if (discoveredDevices.isEmpty()) {
- state = Inactive;
- emit q_ptr->finished();
- return;
- }
-
QT_BT_MAC_AUTORELEASEPOOL;
- state = ServiceDiscovery;
- const QBluetoothAddress &address(discoveredDevices.at(0).address());
-
- if (address.isNull()) {
+ if (deviceAddress.isNull()) {
// This can happen: LE scan works with CoreBluetooth, but CBPeripherals
// do not expose hardware addresses.
// Pop the current QBluetoothDeviceInfo and decide what to do next.
- return serviceDiscoveryFinished();
+ return _q_serviceDiscoveryFinished();
}
// Autoreleased object.
@@ -195,17 +105,18 @@ void QBluetoothServiceDiscoveryAgentPrivate::startServiceDiscovery()
emit q_ptr->error(error);
}
- return serviceDiscoveryFinished();
+ return _q_serviceDiscoveryFinished();
}
if (DiscoveryMode() == QBluetoothServiceDiscoveryAgent::MinimalDiscovery) {
- performMinimalServiceDiscovery(address);
+ performMinimalServiceDiscovery(deviceAddress);
} else {
IOReturn result = kIOReturnSuccess;
+ auto nativeInquiry = serviceInquiry.getAs<ObjCServiceInquiry>();
if (uuidFilter.size())
- result = [serviceInquiry performSDPQueryWithDevice:address filters:uuidFilter];
+ result = [nativeInquiry performSDPQueryWithDevice:deviceAddress filters:uuidFilter];
else
- result = [serviceInquiry performSDPQueryWithDevice:address];
+ result = [nativeInquiry performSDPQueryWithDevice:deviceAddress];
if (result != kIOReturnSuccess) {
// Failed immediately to perform an SDP inquiry on IOBluetoothDevice:
@@ -214,87 +125,21 @@ void QBluetoothServiceDiscoveryAgentPrivate::startServiceDiscovery()
}
}
-void QBluetoothServiceDiscoveryAgentPrivate::stopServiceDiscovery()
+void QBluetoothServiceDiscoveryAgentPrivate::stop()
{
- Q_ASSERT_X(state != Inactive, Q_FUNC_INFO, "invalid state");
Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
discoveredDevices.clear();
- state = Inactive;
// "Stops" immediately.
- [serviceInquiry stopSDPQuery];
+ [serviceInquiry.getAs<ObjCServiceInquiry>() stopSDPQuery];
emit q_ptr->canceled();
}
-QBluetoothServiceDiscoveryAgentPrivate::DiscoveryState
- QBluetoothServiceDiscoveryAgentPrivate::discoveryState()
-{
- return state;
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::setDiscoveryMode(
- QBluetoothServiceDiscoveryAgent::DiscoveryMode m)
-{
- discoveryMode = m;
-
-}
-
-QBluetoothServiceDiscoveryAgent::DiscoveryMode
- QBluetoothServiceDiscoveryAgentPrivate::DiscoveryMode()
-{
- return discoveryMode;
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscovered(const QBluetoothDeviceInfo &info)
-{
- // Look for duplicates, and cached entries
- for (int i = 0; i < discoveredDevices.count(); i++) {
- if (discoveredDevices.at(i).address() == info.address()) {
- discoveredDevices.removeAt(i);
- break;
- }
- }
-
- discoveredDevices.prepend(info);
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error)
-{
- Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
-
- error = QBluetoothServiceDiscoveryAgent::UnknownError;
- errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_UNKNOWN_ERROR);
-
- deviceDiscoveryAgent->stop();
- deviceDiscoveryAgent.reset(nullptr);
-
- state = QBluetoothServiceDiscoveryAgentPrivate::Inactive;
- emit q_ptr->error(error);
- emit q_ptr->finished();
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryFinished()
-{
- Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
-
- if (deviceDiscoveryAgent->error() != QBluetoothDeviceDiscoveryAgent::NoError) {
- //Forward the device discovery error
- error = static_cast<QBluetoothServiceDiscoveryAgent::Error>(deviceDiscoveryAgent->error());
- errorString = deviceDiscoveryAgent->errorString();
- deviceDiscoveryAgent.reset(nullptr);
- state = Inactive;
- emit q_ptr->error(error);
- emit q_ptr->finished();
- } else {
- deviceDiscoveryAgent.reset(nullptr);
- startServiceDiscovery();
- }
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryFinished(IOBluetoothDevice *device)
+void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryFinished(void *generic)
{
+ auto device = static_cast<IOBluetoothDevice *>(generic);
Q_ASSERT_X(device, Q_FUNC_INFO, "invalid IOBluetoothDevice (nil)");
if (state == Inactive)
@@ -323,10 +168,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryFinished(IOBluetoothDevic
}
}
- serviceDiscoveryFinished();
+ _q_serviceDiscoveryFinished();
}
-void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryError(IOBluetoothDevice *device, IOReturn errorCode)
+void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryError(void *device, IOReturn errorCode)
{
Q_UNUSED(device)
@@ -340,7 +185,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryError(IOBluetoothDevice *
emit q_ptr->error(error);
}
- serviceDiscoveryFinished();
+ _q_serviceDiscoveryFinished();
}
void QBluetoothServiceDiscoveryAgentPrivate::performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress)
@@ -371,7 +216,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::performMinimalServiceDiscovery(cons
if (!serviceInfo.isValid())
continue;
- if (!uuidFilter.isEmpty() && !serviceHasMathingUuid(serviceInfo))
+ if (!uuidFilter.isEmpty() && !serviceHasMatchingUuid(serviceInfo))
continue;
if (!isDuplicatedService(serviceInfo)) {
@@ -381,52 +226,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::performMinimalServiceDiscovery(cons
}
}
- serviceDiscoveryFinished();
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::setupDeviceDiscoveryAgent()
-{
- Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
- Q_ASSERT_X(deviceDiscoveryAgent.isNull() || !deviceDiscoveryAgent->isActive(),
- Q_FUNC_INFO, "device discovery agent is active");
-
- deviceDiscoveryAgent.reset(new QBluetoothDeviceDiscoveryAgent(localAdapterAddress, q_ptr));
-
- QObject::connect(deviceDiscoveryAgent.data(), &QBluetoothDeviceDiscoveryAgent::deviceDiscovered,
- this, &QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscovered);
- QObject::connect(deviceDiscoveryAgent.data(), &QBluetoothDeviceDiscoveryAgent::finished,
- this, &QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryFinished);
- QObject::connect(deviceDiscoveryAgent.data(),
- QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error),
- this,
- &QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryError);
-}
-
-bool QBluetoothServiceDiscoveryAgentPrivate::isDuplicatedService(const QBluetoothServiceInfo &serviceInfo) const
-{
- //check the service is not already part of our known list
- for (int j = 0; j < discoveredServices.count(); j++) {
- const QBluetoothServiceInfo &info = discoveredServices.at(j);
- if (info.device() == serviceInfo.device()
- && info.serviceClassUuids() == serviceInfo.serviceClassUuids()
- && info.serviceUuid() == serviceInfo.serviceUuid()) {
- return true;
- }
- }
-
- return false;
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::serviceDiscoveryFinished()
-{
- if (!discoveredDevices.isEmpty())
- discoveredDevices.removeFirst();
-
- if (state == ServiceDiscovery)
- startServiceDiscovery();
+ _q_serviceDiscoveryFinished();
}
-bool QBluetoothServiceDiscoveryAgentPrivate::serviceHasMathingUuid(const QBluetoothServiceInfo &serviceInfo) const
+bool QBluetoothServiceDiscoveryAgentPrivate::serviceHasMatchingUuid(const QBluetoothServiceInfo &serviceInfo) const
{
for (const auto &requestedUuid : uuidFilter) {
if (serviceInfo.serviceUuid() == requestedUuid)
@@ -437,161 +240,4 @@ bool QBluetoothServiceDiscoveryAgentPrivate::serviceHasMathingUuid(const QBlueto
return false;
}
-QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(QObject *parent)
-: QObject(parent),
- d_ptr(new QBluetoothServiceDiscoveryAgentPrivate(this, QBluetoothAddress()))
-{
-}
-
-QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, QObject *parent)
-: QObject(parent),
- d_ptr(new QBluetoothServiceDiscoveryAgentPrivate(this, deviceAdapter))
-{
- if (!deviceAdapter.isNull()) {
- const QList<QBluetoothHostInfo> localDevices = QBluetoothLocalDevice::allDevices();
- for (const QBluetoothHostInfo &hostInfo : localDevices) {
- if (hostInfo.address() == deviceAdapter)
- return;
- }
- d_ptr->error = InvalidBluetoothAdapterError;
- d_ptr->errorString = QCoreApplication::translate(SERVICE_DISCOVERY, SD_INVALID_ADDRESS);
- }
-}
-
-QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent()
-{
- delete d_ptr;
-}
-
-QList<QBluetoothServiceInfo> QBluetoothServiceDiscoveryAgent::discoveredServices() const
-{
- return d_ptr->discoveredServices;
-}
-
-/*
- Sets the UUID filter to \a uuids. Only services matching the UUIDs in \a uuids will be
- returned.
-
- An empty UUID list is equivalent to a list containing only QBluetoothUuid::PublicBrowseGroup.
-
- \sa uuidFilter()
-*/
-void QBluetoothServiceDiscoveryAgent::setUuidFilter(const QList<QBluetoothUuid> &uuids)
-{
- d_ptr->uuidFilter = uuids;
-}
-
-/*
- This is an overloaded member function, provided for convenience.
-
- Sets the UUID filter to a list containing the single element \a uuid.
-
- \sa uuidFilter()
-*/
-void QBluetoothServiceDiscoveryAgent::setUuidFilter(const QBluetoothUuid &uuid)
-{
- d_ptr->uuidFilter.clear();
- d_ptr->uuidFilter.append(uuid);
-}
-
-/*
- Returns the UUID filter.
-
- \sa setUuidFilter()
-*/
-QList<QBluetoothUuid> QBluetoothServiceDiscoveryAgent::uuidFilter() const
-{
- return d_ptr->uuidFilter;
-}
-
-/*
- Sets the remote device address to \a address. If \a address is default constructed,
- services will be discovered on all contactable Bluetooth devices. A new remote
- address can only be set while there is no service discovery in progress; otherwise
- this function returns false.
-
- \sa remoteAddress()
-*/
-bool QBluetoothServiceDiscoveryAgent::setRemoteAddress(const QBluetoothAddress &address)
-{
- if (isActive())
- return false;
-
- if (!address.isNull())
- d_ptr->singleDevice = true;
-
- d_ptr->deviceAddress = address;
- return true;
-}
-
-QBluetoothAddress QBluetoothServiceDiscoveryAgent::remoteAddress() const
-{
- if (d_ptr->singleDevice)
- return d_ptr->deviceAddress;
-
- return QBluetoothAddress();
-}
-
-void QBluetoothServiceDiscoveryAgent::start(DiscoveryMode mode)
-{
- OSXBluetooth::qt_test_iobluetooth_runloop();
-
- if (d_ptr->discoveryState() == QBluetoothServiceDiscoveryAgentPrivate::Inactive
- && d_ptr->error != InvalidBluetoothAdapterError)
- {
- d_ptr->setDiscoveryMode(mode);
- if (d_ptr->deviceAddress.isNull()) {
- d_ptr->startDeviceDiscovery();
- } else {
- d_ptr->discoveredDevices.append(QBluetoothDeviceInfo(d_ptr->deviceAddress, QString(), 0));
- d_ptr->startServiceDiscovery();
- }
- }
-}
-
-void QBluetoothServiceDiscoveryAgent::stop()
-{
- if (d_ptr->error == InvalidBluetoothAdapterError || !isActive())
- return;
-
- switch (d_ptr->discoveryState()) {
- case QBluetoothServiceDiscoveryAgentPrivate::DeviceDiscovery:
- d_ptr->stopDeviceDiscovery();
- break;
- case QBluetoothServiceDiscoveryAgentPrivate::ServiceDiscovery:
- d_ptr->stopServiceDiscovery();
- default:;
- }
-
- d_ptr->discoveredDevices.clear();
-}
-
-void QBluetoothServiceDiscoveryAgent::clear()
-{
- // Don't clear the list while the search is ongoing
- if (isActive())
- return;
-
- d_ptr->discoveredDevices.clear();
- d_ptr->discoveredServices.clear();
- d_ptr->uuidFilter.clear();
-}
-
-bool QBluetoothServiceDiscoveryAgent::isActive() const
-{
- return d_ptr->state != QBluetoothServiceDiscoveryAgentPrivate::Inactive;
-}
-
-QBluetoothServiceDiscoveryAgent::Error QBluetoothServiceDiscoveryAgent::error() const
-{
- return d_ptr->error;
-}
-
-QString QBluetoothServiceDiscoveryAgent::errorString() const
-{
- return d_ptr->errorString;
-}
-
-#include "moc_qbluetoothservicediscoveryagent.cpp"
-
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_p.h b/src/bluetooth/qbluetoothservicediscoveryagent_p.h
index cb588f70..41410b70 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_p.h
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_p.h
@@ -90,6 +90,11 @@ QT_END_NAMESPACE
#include <QtCore/QPointer>
#endif
+#ifdef QT_OSX_BLUETOOTH
+#include "osx/btdelegates_p.h"
+#include "osx/btraii_p.h"
+#endif
+
QT_BEGIN_NAMESPACE
class QBluetoothDeviceDiscoveryAgent;
@@ -109,6 +114,9 @@ class QBluetoothServiceDiscoveryAgentPrivate
: public QObject
{
Q_OBJECT
+#elif defined(QT_OSX_BLUETOOTH)
+ : public QObject, public DarwinBluetooth::SDPInquiryDelegate
+{
#else
{
#endif
@@ -238,6 +246,19 @@ private:
QPointer<QWinRTBluetoothServiceDiscoveryWorker> worker;
#endif
+#ifdef QT_OSX_BLUETOOTH
+ // SDPInquiryDelegate:
+ void SDPInquiryFinished(void *device) override;
+ void SDPInquiryError(void *device, IOReturn errorCode) override;
+
+ void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress);
+ //void serviceDiscoveryFinished();
+
+ bool serviceHasMatchingUuid(const QBluetoothServiceInfo &serviceInfo) const;
+
+ DarwinBluetooth::ScopedPointer serviceInquiry;
+#endif // QT_OSX_BLUETOOTH
+
protected:
QBluetoothServiceDiscoveryAgent *q_ptr;
};
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp
index c6b00346..f1476758 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp
@@ -52,6 +52,7 @@
#include <windows.devices.enumeration.h>
#include <windows.devices.bluetooth.h>
#include <windows.foundation.collections.h>
+#include <windows.networking.h>
#include <windows.storage.streams.h>
#include <wrl.h>
@@ -81,24 +82,6 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT)
#define TYPE_STRING 37
#define TYPE_SEQUENCE 53
-static QByteArray byteArrayFromBuffer(const ComPtr<IBuffer> &buffer, bool isWCharString = false)
-{
- ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteAccess;
- HRESULT hr = buffer.As(&byteAccess);
- Q_ASSERT_SUCCEEDED(hr);
- char *data;
- hr = byteAccess->Buffer(reinterpret_cast<byte **>(&data));
- Q_ASSERT_SUCCEEDED(hr);
- UINT32 size;
- hr = buffer->get_Length(&size);
- Q_ASSERT_SUCCEEDED(hr);
- if (isWCharString) {
- QString valueString = QString::fromUtf16(reinterpret_cast<ushort *>(data)).left(size / 2);
- return valueString.toUtf8();
- }
- return QByteArray(data, size);
-}
-
class QWinRTBluetoothServiceDiscoveryWorker : public QObject
{
Q_OBJECT
@@ -226,6 +209,14 @@ void QWinRTBluetoothServiceDiscoveryWorker::processServiceSearchResult(quint64 a
hr = service->get_ConnectionServiceName(name.GetAddressOf());
Q_ASSERT_SUCCEEDED(hr);
const QString serviceName = QString::fromWCharArray(WindowsGetStringRawBuffer(name.Get(), nullptr));
+ ComPtr<ABI::Windows::Networking::IHostName> host;
+ hr = service->get_ConnectionHostName(host.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ HString hostName;
+ hr = host->get_RawName(hostName.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ const QString qHostName = QString::fromWCharArray(WindowsGetStringRawBuffer(hostName.Get(),
+ nullptr));
ComPtr<IRfcommServiceId> id;
hr = service->get_ServiceId(&id);
Q_ASSERT_SUCCEEDED(hr);
@@ -235,6 +226,8 @@ void QWinRTBluetoothServiceDiscoveryWorker::processServiceSearchResult(quint64 a
Q_ASSERT_SUCCEEDED(hr);
QBluetoothServiceInfo info;
+ info.setAttribute(0xBEEF, QVariant(qHostName));
+ info.setAttribute(0xBEF0, QVariant(serviceName));
info.setServiceName(serviceName);
info.setServiceUuid(uuid);
ComPtr<IAsyncOperation<IMapView<UINT32, IBuffer *> *>> op;
@@ -343,6 +336,17 @@ void QWinRTBluetoothServiceDiscoveryWorker::processServiceSearchResult(quint64 a
}
hr = iterator->MoveNext(&current);
}
+ // Windows is only able to discover Rfcomm services but the according protocolDescriptor is
+ // not always set in the raw attribute map. If we encounter a service like that we should
+ // fill the protocol descriptor ourselves.
+ if (info.protocolDescriptor(QBluetoothUuid::Rfcomm).isEmpty()) {
+ QBluetoothServiceInfo::Sequence protocolDescriptorList;
+ QBluetoothServiceInfo::Sequence protocol;
+ protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
+ << QVariant::fromValue(0);
+ protocolDescriptorList.append(QVariant::fromValue(protocol));
+ info.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList);
+ }
emit serviceFound(address, info);
}
emit scanFinished(address);
diff --git a/src/bluetooth/qbluetoothserviceinfo.cpp b/src/bluetooth/qbluetoothserviceinfo.cpp
index 74b17ac4..23a78c81 100644
--- a/src/bluetooth/qbluetoothserviceinfo.cpp
+++ b/src/bluetooth/qbluetoothserviceinfo.cpp
@@ -180,7 +180,12 @@ bool QBluetoothServiceInfo::isRegistered() const
bool QBluetoothServiceInfo::registerService(const QBluetoothAddress &localAdapter)
{
+#ifdef QT_OSX_BLUETOOTH
+ Q_UNUSED(localAdapter)
+ return d_ptr->registerService(*this);
+#else
return d_ptr->registerService(localAdapter);
+#endif
}
/*!
@@ -413,6 +418,9 @@ void QBluetoothServiceInfo::setDevice(const QBluetoothDeviceInfo &device)
If the service information is already registered with the platform's SDP database,
the database entry will not be updated until \l registerService() was called again.
+ \note If an attribute expectes a byte-encoded value (e.g. Bluetooth HID services),
+ it should be set as QByteArray.
+
\sa isRegistered(), registerService()
*/
void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QVariant &value)
@@ -578,6 +586,10 @@ static void dumpAttributeVariant(QDebug dbg, const QVariant &var, const QString&
dbg << QString::asprintf("%sstring %s\n", indent.toUtf8().constData(),
var.toString().toUtf8().constData());
break;
+ case QMetaType::QByteArray:
+ dbg << QString::asprintf("%sbytearray %s\n", indent.toUtf8().constData(),
+ var.toByteArray().toHex().constData());
+ break;
case QMetaType::Bool:
dbg << QString::asprintf("%sbool %d\n", indent.toUtf8().constData(), var.toBool());
break;
@@ -631,7 +643,7 @@ QDebug operator<<(QDebug dbg, const QBluetoothServiceInfo &info)
{
QDebugStateSaver saver(dbg);
dbg.noquote() << "\n";
- QList<quint16> attributes = info.attributes();
+ const QList<quint16> attributes = info.attributes();
for (quint16 id : attributes) {
dumpAttributeVariant(dbg, info.attribute(id), QStringLiteral("(%1)\t").arg(id));
}
diff --git a/src/bluetooth/qbluetoothserviceinfo_bluez.cpp b/src/bluetooth/qbluetoothserviceinfo_bluez.cpp
index 09829b13..d91367c4 100644
--- a/src/bluetooth/qbluetoothserviceinfo_bluez.cpp
+++ b/src/bluetooth/qbluetoothserviceinfo_bluez.cpp
@@ -69,66 +69,57 @@ static void writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute)
stream->writeAttribute(QStringLiteral("value"),
unsignedFormat.arg(attribute.value<quint8>(), 2, 16,
QLatin1Char('0')));
- //stream->writeAttribute(QStringLiteral("name"), foo);
break;
case QMetaType::UShort:
stream->writeEmptyElement(QStringLiteral("uint16"));
stream->writeAttribute(QStringLiteral("value"),
unsignedFormat.arg(attribute.value<quint16>(), 4, 16,
QLatin1Char('0')));
- //stream->writeAttribute(QStringLiteral("name"), foo);
break;
case QMetaType::UInt:
stream->writeEmptyElement(QStringLiteral("uint32"));
stream->writeAttribute(QStringLiteral("value"),
unsignedFormat.arg(attribute.value<quint32>(), 8, 16,
QLatin1Char('0')));
- //stream->writeAttribute(QStringLiteral("name"), foo);
break;
case QMetaType::Char:
stream->writeEmptyElement(QStringLiteral("int8"));
stream->writeAttribute(QStringLiteral("value"),
- QString::number(attribute.value<uchar>(), 16));
- //stream->writeAttribute(QStringLiteral("name"), foo);
+ QString::number(attribute.value<qint8>()));
break;
case QMetaType::Short:
stream->writeEmptyElement(QStringLiteral("int16"));
stream->writeAttribute(QStringLiteral("value"),
- QString::number(attribute.value<qint16>(), 16));
- //stream->writeAttribute(QStringLiteral("name"), foo);
+ QString::number(attribute.value<qint16>()));
break;
case QMetaType::Int:
stream->writeEmptyElement(QStringLiteral("int32"));
stream->writeAttribute(QStringLiteral("value"),
- QString::number(attribute.value<qint32>(), 16));
- //stream->writeAttribute(QStringLiteral("name"), foo);
+ QString::number(attribute.value<qint32>()));
+ break;
+ case QMetaType::QByteArray:
+ stream->writeEmptyElement(QStringLiteral("text"));
+ stream->writeAttribute(QStringLiteral("value"),
+ QString::fromLatin1(attribute.value<QByteArray>().toHex().constData()));
+ stream->writeAttribute(QStringLiteral("encoding"), QStringLiteral("hex"));
break;
case QMetaType::QString:
stream->writeEmptyElement(QStringLiteral("text"));
- if (/* require hex encoding */ false) {
- stream->writeAttribute(QStringLiteral("value"), QString::fromLatin1(
- attribute.value<QString>().toUtf8().toHex().constData()));
- stream->writeAttribute(QStringLiteral("encoding"), QStringLiteral("hex"));
- } else {
- stream->writeAttribute(QStringLiteral("value"), attribute.value<QString>());
- stream->writeAttribute(QStringLiteral("encoding"), QStringLiteral("normal"));
- }
- //stream->writeAttribute(QStringLiteral("name"), foo);
+ stream->writeAttribute(QStringLiteral("value"), attribute.value<QString>());
+ stream->writeAttribute(QStringLiteral("encoding"), QStringLiteral("normal"));
break;
- case QMetaType::Bool:
+ case QMetaType::Bool:
stream->writeEmptyElement(QStringLiteral("boolean"));
if (attribute.value<bool>())
stream->writeAttribute(QStringLiteral("value"), QStringLiteral("true"));
else
stream->writeAttribute(QStringLiteral("value"), QStringLiteral("false"));
- //stream->writeAttribute(QStringLiteral("name"), foo);
break;
- case QMetaType::QUrl:
+ case QMetaType::QUrl:
stream->writeEmptyElement(QStringLiteral("url"));
stream->writeAttribute(QStringLiteral("value"), attribute.value<QUrl>().toString());
- //stream->writeAttribute(QStringLiteral("name"), foo);
break;
- case QVariant::UserType:
+ case QVariant::UserType:
if (attribute.userType() == qMetaTypeId<QBluetoothUuid>()) {
stream->writeEmptyElement(QStringLiteral("uuid"));
diff --git a/src/bluetooth/qbluetoothserviceinfo_osx.mm b/src/bluetooth/qbluetoothserviceinfo_osx.mm
index 27da70fc..41e4e8b7 100644
--- a/src/bluetooth/qbluetoothserviceinfo_osx.mm
+++ b/src/bluetooth/qbluetoothserviceinfo_osx.mm
@@ -38,9 +38,10 @@
****************************************************************************/
#include "osx/osxbtservicerecord_p.h"
-#include "qbluetoothserver_osx_p.h"
+#include "qbluetoothserviceinfo_p.h"
#include "qbluetoothserviceinfo.h"
#include "qbluetoothdeviceinfo.h"
+#include "qbluetoothserver_p.h"
#include "osx/osxbtutility_p.h"
#include "osx/osxbluetooth_p.h"
@@ -55,85 +56,116 @@
QT_BEGIN_NAMESPACE
-class QBluetoothServiceInfoPrivate
+namespace {
+
+using DarwinBluetooth::RetainPolicy;
+using ServiceInfo = QBluetoothServiceInfo;
+
+// Alas, since there is no d_ptr<->q_ptr link (which is not that bad in itself),
+// I need these getters duplicated here:
+ServiceInfo::Protocol socket_protocol(const QBluetoothServiceInfoPrivate &privateInfo)
{
-public:
+ ServiceInfo::Sequence parameters = privateInfo.protocolDescriptor(QBluetoothUuid::Rfcomm);
+ if (!parameters.isEmpty())
+ return ServiceInfo::RfcommProtocol;
- typedef QBluetoothServiceInfo QSInfo;
+ parameters = privateInfo.protocolDescriptor(QBluetoothUuid::L2cap);
+ if (!parameters.isEmpty())
+ return ServiceInfo::L2capProtocol;
- bool registerService(const OSXBluetooth::ObjCStrongReference<NSMutableDictionary> &serviceDict);
- bool isRegistered() const;
- bool unregisterService();
+ return ServiceInfo::UnknownProtocol;
+}
- QBluetoothDeviceInfo deviceInfo;
- QMap<quint16, QVariant> attributes;
+int channel_or_psm(const QBluetoothServiceInfoPrivate &privateInfo, QBluetoothUuid::ProtocolUuid uuid)
+{
+ const auto parameters = privateInfo.protocolDescriptor(uuid);
+ if (parameters.isEmpty())
+ return -1;
+ else if (parameters.count() == 1)
+ return 0;
- QBluetoothServiceInfo::Sequence protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const;
- QBluetoothServiceInfo::Protocol socketProtocol() const;
- int protocolServiceMultiplexer() const;
- int serverChannel() const;
+ return parameters.at(1).toInt();
+}
-private:
+} // unnamed namespace
- bool registered = false;
+QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate()
+{
+}
- typedef OSXBluetooth::ObjCScopedPointer<IOBluetoothSDPServiceRecord> SDPRecord;
- SDPRecord serviceRecord;
- BluetoothSDPServiceRecordHandle serviceRecordHandle = 0;
-};
+QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate()
+{
+}
-bool QBluetoothServiceInfoPrivate::registerService(const OSXBluetooth::ObjCStrongReference<NSMutableDictionary> &serviceDict)
+bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &localAddress)
+{
+ Q_UNUSED(localAddress);
+ return false;
+}
+
+bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothServiceInfo &info)
{
using namespace OSXBluetooth;
- Q_ASSERT(serviceDict);
+ if (isRegistered())
+ return false;
+
+ using namespace OSXBluetooth;
+
+ ObjCStrongReference<NSMutableDictionary> serviceDict(iobluetooth_service_dictionary(info));
+ if (!serviceDict) {
+ qCWarning(QT_BT_OSX) << "failed to create a service dictionary";
+ return false;
+ }
+
Q_ASSERT(!registered);
Q_ASSERT_X(!serviceRecord, Q_FUNC_INFO, "not registered, but serviceRecord is not nil");
SDPRecord newRecord;
- newRecord.reset([[IOBluetoothSDPServiceRecord
- publishedServiceRecordWithDictionary:serviceDict] retain]);
+ newRecord.reset([IOBluetoothSDPServiceRecord
+ publishedServiceRecordWithDictionary:serviceDict], RetainPolicy::doInitialRetain);
if (!newRecord) {
qCWarning(QT_BT_OSX) << "failed to register a service record";
return false;
}
BluetoothSDPServiceRecordHandle newRecordHandle = 0;
- if ([newRecord getServiceRecordHandle:&newRecordHandle] != kIOReturnSuccess) {
+ auto *ioSDPRecord = newRecord.getAs<IOBluetoothSDPServiceRecord>();
+ if ([ioSDPRecord getServiceRecordHandle:&newRecordHandle] != kIOReturnSuccess) {
qCWarning(QT_BT_OSX) << "failed to register a service record";
- [newRecord removeServiceRecord];
+ [ioSDPRecord removeServiceRecord];
return false;
}
- const QSInfo::Protocol type = socketProtocol();
+ const ServiceInfo::Protocol type = info.socketProtocol();
quint16 realPort = 0;
QBluetoothServerPrivate *server = nullptr;
bool configured = false;
if (type == QBluetoothServiceInfo::L2capProtocol) {
BluetoothL2CAPPSM psm = 0;
- server = QBluetoothServerPrivate::registeredServer(protocolServiceMultiplexer(), type);
- if ([newRecord getL2CAPPSM:&psm] == kIOReturnSuccess) {
+ server = QBluetoothServerPrivate::registeredServer(info.protocolServiceMultiplexer(), type);
+ if ([ioSDPRecord getL2CAPPSM:&psm] == kIOReturnSuccess) {
configured = true;
realPort = psm;
}
} else if (type == QBluetoothServiceInfo::RfcommProtocol) {
BluetoothRFCOMMChannelID channelID = 0;
- server = QBluetoothServerPrivate::registeredServer(serverChannel(), type);
- if ([newRecord getRFCOMMChannelID:&channelID] == kIOReturnSuccess) {
+ server = QBluetoothServerPrivate::registeredServer(info.serverChannel(), type);
+ if ([ioSDPRecord getRFCOMMChannelID:&channelID] == kIOReturnSuccess) {
configured = true;
realPort = channelID;
}
}
if (!configured) {
- [newRecord removeServiceRecord];
+ [ioSDPRecord removeServiceRecord];
qCWarning(QT_BT_OSX) << "failed to register a service record";
return false;
}
registered = true;
- serviceRecord.reset(newRecord.take());
+ serviceRecord.swap(newRecord);
serviceRecordHandle = newRecordHandle;
if (server)
@@ -154,17 +186,18 @@ bool QBluetoothServiceInfoPrivate::unregisterService()
Q_ASSERT_X(serviceRecord, Q_FUNC_INFO, "service registered, but serviceRecord is nil");
- [serviceRecord removeServiceRecord];
- serviceRecord.reset(nil);
+ auto *nativeRecord = serviceRecord.getAs<IOBluetoothSDPServiceRecord>();
+ [nativeRecord removeServiceRecord];
+ serviceRecord.reset();
- const QSInfo::Protocol type = socketProtocol();
+ const ServiceInfo::Protocol type = socket_protocol(*this);
QBluetoothServerPrivate *server = nullptr;
const QMutexLocker lock(&QBluetoothServerPrivate::channelMapMutex());
- if (type == QSInfo::RfcommProtocol)
- server = QBluetoothServerPrivate::registeredServer(serverChannel(), type);
- else if (type == QSInfo::L2capProtocol)
- server = QBluetoothServerPrivate::registeredServer(protocolServiceMultiplexer(), type);
+ if (type == ServiceInfo::RfcommProtocol)
+ server = QBluetoothServerPrivate::registeredServer(channel_or_psm(*this, QBluetoothUuid::Rfcomm), type);
+ else if (type == ServiceInfo::L2capProtocol)
+ server = QBluetoothServerPrivate::registeredServer(channel_or_psm(*this, QBluetoothUuid::L2cap), type);
if (server)
server->stopListener();
@@ -175,268 +208,4 @@ bool QBluetoothServiceInfoPrivate::unregisterService()
return true;
}
-bool QBluetoothServiceInfo::isRegistered() const
-{
- return d_ptr->isRegistered();
-}
-
-bool QBluetoothServiceInfo::registerService(const QBluetoothAddress &localAdapter)
-{
- Q_UNUSED(localAdapter);
- if (isRegistered())
- return false;
-
- using namespace OSXBluetooth;
-
- ObjCStrongReference<NSMutableDictionary> serviceDict(iobluetooth_service_dictionary(*this));
- if (!serviceDict) {
- qCWarning(QT_BT_OSX) << "failed to create a service dictionary";
- return false;
- }
-
- return d_ptr->registerService(serviceDict);
-}
-
-bool QBluetoothServiceInfo::unregisterService()
-{
- return d_ptr->unregisterService();
-}
-
-QBluetoothServiceInfo::QBluetoothServiceInfo()
- : d_ptr(new QBluetoothServiceInfoPrivate)
-{
-}
-
-QBluetoothServiceInfo::QBluetoothServiceInfo(const QBluetoothServiceInfo &other)
- : d_ptr(other.d_ptr)
-{
-}
-
-QBluetoothServiceInfo::~QBluetoothServiceInfo()
-{
-}
-
-bool QBluetoothServiceInfo::isValid() const
-{
- return !d_ptr->attributes.isEmpty();
-}
-
-bool QBluetoothServiceInfo::isComplete() const
-{
- return d_ptr->attributes.contains(ProtocolDescriptorList);
-}
-
-QBluetoothDeviceInfo QBluetoothServiceInfo::device() const
-{
- return d_ptr->deviceInfo;
-}
-
-void QBluetoothServiceInfo::setDevice(const QBluetoothDeviceInfo &device)
-{
- d_ptr->deviceInfo = device;
-}
-
-void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QVariant &value)
-{
- d_ptr->attributes[attributeId] = value;
-}
-
-QVariant QBluetoothServiceInfo::attribute(quint16 attributeId) const
-{
- return d_ptr->attributes.value(attributeId);
-}
-
-QList<quint16> QBluetoothServiceInfo::attributes() const
-{
- return d_ptr->attributes.keys();
-}
-
-bool QBluetoothServiceInfo::contains(quint16 attributeId) const
-{
- return d_ptr->attributes.contains(attributeId);
-}
-
-void QBluetoothServiceInfo::removeAttribute(quint16 attributeId)
-{
- d_ptr->attributes.remove(attributeId);
-}
-
-QBluetoothServiceInfo::Protocol QBluetoothServiceInfo::socketProtocol() const
-{
- return d_ptr->socketProtocol();
-}
-
-int QBluetoothServiceInfo::protocolServiceMultiplexer() const
-{
- return d_ptr->protocolServiceMultiplexer();
-}
-
-int QBluetoothServiceInfo::serverChannel() const
-{
- return d_ptr->serverChannel();
-}
-
-QBluetoothServiceInfo::Sequence QBluetoothServiceInfo::protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const
-{
- return d_ptr->protocolDescriptor(protocol);
-}
-
-QList<QBluetoothUuid> QBluetoothServiceInfo::serviceClassUuids() const
-{
- QList<QBluetoothUuid> results;
-
- const QVariant var = attribute(QBluetoothServiceInfo::ServiceClassIds);
- if (!var.isValid())
- return results;
-
- const QBluetoothServiceInfo::Sequence seq = var.value<QBluetoothServiceInfo::Sequence>();
- for (int i = 0; i < seq.count(); i++)
- results.append(seq.at(i).value<QBluetoothUuid>());
-
- return results;
-}
-
-QBluetoothServiceInfo &QBluetoothServiceInfo::operator=(const QBluetoothServiceInfo &other)
-{
- if (this != &other)
- d_ptr = other.d_ptr;
-
- return *this;
-}
-
-static void dumpAttributeVariant(const QVariant &var, const QString indent)
-{
- switch (int(var.type())) {
- case QMetaType::Void:
- qDebug("%sEmpty", indent.toLocal8Bit().constData());
- break;
- case QMetaType::UChar:
- qDebug("%suchar %u", indent.toLocal8Bit().constData(), var.toUInt());
- break;
- case QMetaType::UShort:
- qDebug("%sushort %u", indent.toLocal8Bit().constData(), var.toUInt());
- case QMetaType::UInt:
- qDebug("%suint %u", indent.toLocal8Bit().constData(), var.toUInt());
- break;
- case QMetaType::Char:
- qDebug("%schar %d", indent.toLocal8Bit().constData(), var.toInt());
- break;
- case QMetaType::Short:
- qDebug("%sshort %d", indent.toLocal8Bit().constData(), var.toInt());
- break;
- case QMetaType::Int:
- qDebug("%sint %d", indent.toLocal8Bit().constData(), var.toInt());
- break;
- case QMetaType::QString:
- qDebug("%sstring %s", indent.toLocal8Bit().constData(), var.toString().toLocal8Bit().constData());
- break;
- case QMetaType::Bool:
- qDebug("%sbool %d", indent.toLocal8Bit().constData(), var.toBool());
- break;
- case QMetaType::QUrl:
- qDebug("%surl %s", indent.toLocal8Bit().constData(), var.toUrl().toString().toLocal8Bit().constData());
- break;
- case QVariant::UserType:
- if (var.userType() == qMetaTypeId<QBluetoothUuid>()) {
- QBluetoothUuid uuid = var.value<QBluetoothUuid>();
- switch (uuid.minimumSize()) {
- case 0:
- qDebug("%suuid NULL", indent.toLocal8Bit().constData());
- break;
- case 2:
- qDebug("%suuid %04x", indent.toLocal8Bit().constData(), uuid.toUInt16());
- break;
- case 4:
- qDebug("%suuid %08x", indent.toLocal8Bit().constData(), uuid.toUInt32());
- break;
- case 16:
- qDebug("%suuid %s", indent.toLocal8Bit().constData(), QByteArray(reinterpret_cast<const char *>(uuid.toUInt128().data), 16).toHex().constData());
- break;
- default:
- qDebug("%suuid ???", indent.toLocal8Bit().constData());
- ;
- }
- } else if (var.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) {
- qDebug("%sSequence", indent.toLocal8Bit().constData());
- const QBluetoothServiceInfo::Sequence *sequence = static_cast<const QBluetoothServiceInfo::Sequence *>(var.data());
- for (const QVariant &v : *sequence)
- dumpAttributeVariant(v, indent + QLatin1Char('\t'));
- } else if (var.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) {
- qDebug("%sAlternative", indent.toLocal8Bit().constData());
- const QBluetoothServiceInfo::Alternative *alternative = static_cast<const QBluetoothServiceInfo::Alternative *>(var.data());
- for (const QVariant &v : *alternative)
- dumpAttributeVariant(v, indent + QLatin1Char('\t'));
- }
- break;
- default:
- qDebug("%sunknown variant type %d", indent.toLocal8Bit().constData(), var.userType());
- }
-}
-
-QDebug operator << (QDebug dbg, const QBluetoothServiceInfo &info)
-{
- const QList<quint16> attributes = info.attributes();
- for (quint16 id : attributes) {
- dumpAttributeVariant(info.attribute(id), QString::fromLatin1("(%1)\t").arg(id));
- }
- return dbg;
-}
-
-QBluetoothServiceInfo::Sequence QBluetoothServiceInfoPrivate::protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const
-{
- if (!attributes.contains(QBluetoothServiceInfo::ProtocolDescriptorList))
- return QBluetoothServiceInfo::Sequence();
-
- const QBluetoothServiceInfo::Sequence sequence
- = attributes.value(QBluetoothServiceInfo::ProtocolDescriptorList).value<QBluetoothServiceInfo::Sequence>();
- for (const QVariant &v : sequence) {
- QBluetoothServiceInfo::Sequence parameters = v.value<QBluetoothServiceInfo::Sequence>();
- if (parameters.empty())
- continue;
- if (parameters.at(0).userType() == qMetaTypeId<QBluetoothUuid>()) {
- if (parameters.at(0).value<QBluetoothUuid>() == protocol)
- return parameters;
- }
- }
-
- return QBluetoothServiceInfo::Sequence();
-}
-
-QBluetoothServiceInfo::Protocol QBluetoothServiceInfoPrivate::socketProtocol() const
-{
- QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(QBluetoothUuid::Rfcomm);
- if (!parameters.isEmpty())
- return QBluetoothServiceInfo::RfcommProtocol;
-
- parameters = protocolDescriptor(QBluetoothUuid::L2cap);
- if (!parameters.isEmpty())
- return QBluetoothServiceInfo::L2capProtocol;
-
- return QBluetoothServiceInfo::UnknownProtocol;
-}
-
-
-int QBluetoothServiceInfoPrivate::protocolServiceMultiplexer() const
-{
- const QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(QBluetoothUuid::L2cap);
- if (parameters.isEmpty())
- return -1;
- else if (parameters.count() == 1)
- return 0;
-
- return parameters.at(1).toUInt();
-}
-
-
-int QBluetoothServiceInfoPrivate::serverChannel() const
-{
- const QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(QBluetoothUuid::Rfcomm);
- if (parameters.isEmpty())
- return -1;
- else if (parameters.count() == 1)
- return 0;
-
- return parameters.at(1).toUInt();
-}
-
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothserviceinfo_p.h b/src/bluetooth/qbluetoothserviceinfo_p.h
index 0638867d..3ed005e1 100644
--- a/src/bluetooth/qbluetoothserviceinfo_p.h
+++ b/src/bluetooth/qbluetoothserviceinfo_p.h
@@ -59,6 +59,10 @@
#include <QMap>
#include <QVariant>
+#ifdef Q_OS_MACOS
+#include "osx/btraii_p.h"
+#endif
+
class OrgBluezServiceInterface;
class OrgBluezProfileManager1Interface;
@@ -87,7 +91,6 @@ QT_BEGIN_NAMESPACE
class QBluetoothServiceInfo;
-#ifndef QT_OSX_BLUETOOTH
class QBluetoothServiceInfoPrivate
: public QObject
@@ -133,11 +136,20 @@ private:
QVector<WCHAR> serviceDescription;
#endif
- mutable bool registered;
-};
+#if QT_OSX_BLUETOOTH
+public:
+ bool registerService(const QBluetoothServiceInfo &info);
-#endif
+private:
+
+ using SDPRecord = DarwinBluetooth::ScopedPointer;
+ SDPRecord serviceRecord;
+ quint32 serviceRecordHandle = 0;
+#endif // QT_OSX_BLUETOOTH
+
+ mutable bool registered = false;
+};
QT_END_NAMESPACE
-#endif
+#endif // QBLUETOOTHSERVICEINFO_P_H
diff --git a/src/bluetooth/qbluetoothserviceinfo_winrt.cpp b/src/bluetooth/qbluetoothserviceinfo_winrt.cpp
index 45262735..e806096f 100644
--- a/src/bluetooth/qbluetoothserviceinfo_winrt.cpp
+++ b/src/bluetooth/qbluetoothserviceinfo_winrt.cpp
@@ -297,6 +297,14 @@ static ComPtr<IBuffer> bufferFromAttribute(const QVariant &attribute)
hr = writer->WriteInt64(attribute.value<qint64>());
Q_ASSERT_SUCCEEDED(hr);
break;
+ case QMetaType::QByteArray: {
+ qCDebug(QT_BT_WINRT) << Q_FUNC_INFO << "Registering attribute of type QMetaType::QByteArray:" << attribute.value<QString>();
+ const QString stringValue = QString::fromLatin1(attribute.value<QByteArray>().toHex());
+ const bool writeSuccess = writeStringHelper(stringValue, writer);
+ if (!writeSuccess)
+ return nullptr;
+ break;
+ }
case QMetaType::QString: {
qCDebug(QT_BT_WINRT) << Q_FUNC_INFO << "Registering attribute of type QMetaType::QString:" << attribute.value<QString>();
const QString stringValue = attribute.value<QString>();
diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp
index 54eb6024..e4d85447 100644
--- a/src/bluetooth/qbluetoothsocket.cpp
+++ b/src/bluetooth/qbluetoothsocket.cpp
@@ -49,6 +49,8 @@
#include "qbluetoothsocket_winrt_p.h"
#elif defined(QT_WIN_BLUETOOTH)
#include "qbluetoothsocket_win_p.h"
+#elif defined(QT_OSX_BLUETOOTH)
+#include "qbluetoothsocket_osx_p.h"
#else
#include "qbluetoothsocket_dummy_p.h"
#endif
@@ -271,6 +273,8 @@ static QBluetoothSocketBasePrivate *createSocketPrivate()
return new QBluetoothSocketPrivateWinRT();
#elif defined(QT_WIN_BLUETOOTH)
return new QBluetoothSocketPrivateWin();
+#elif defined(QT_OSX_BLUETOOTH)
+ return new QBluetoothSocketPrivate();
#else
return new QBluetoothSocketPrivateDummy();
#endif
@@ -364,8 +368,8 @@ qint64 QBluetoothSocket::bytesToWrite() const
/*!
Attempts to connect to the service described by \a service.
- The socket is opened in the given \a openMode. The \l socketType() may change
- depending on the protocol required by \a service.
+ The socket is opened in the given \a openMode. The \l socketType() is ignored
+ if \a service specifies a differing \l QBluetoothServiceInfo::socketProtocol().
The socket first enters ConnectingState and attempts to connect to the device providing
\a service. If a connection is established, QBluetoothSocket enters ConnectedState and
@@ -376,6 +380,9 @@ qint64 QBluetoothSocket::bytesToWrite() const
Note that most platforms require a pairing prior to connecting to the remote device. Otherwise
the connection process may fail.
+ On Android, only RFCOMM connections are possible. This function ignores any socket protocol indicator
+ and assumes RFCOMM.
+
\sa state(), disconnectFromService()
*/
void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, OpenMode openMode)
@@ -514,6 +521,9 @@ QString QBluetoothSocket::errorString() const
*/
void QBluetoothSocket::setPreferredSecurityFlags(QBluetooth::SecurityFlags flags)
{
+#ifdef QT_OSX_BLUETOOTH
+ return; // not supported on macOS.
+#endif
Q_D(QBluetoothSocketBase);
if (d->secFlags != flags)
d->secFlags = flags;
@@ -535,8 +545,13 @@ void QBluetoothSocket::setPreferredSecurityFlags(QBluetooth::SecurityFlags flags
*/
QBluetooth::SecurityFlags QBluetoothSocket::preferredSecurityFlags() const
{
+#if QT_OSX_BLUETOOTH
+ // not supported on macOS - platform always uses encryption
+ return QBluetooth::Secure;
+#else
Q_D(const QBluetoothSocketBase);
return d->secFlags;
+#endif // QT_OSX_BLUETOOTH
}
/*!
@@ -560,6 +575,9 @@ void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state)
emit disconnected();
}
if(state == ListeningState){
+#ifdef QT_OSX_BLUETOOTH
+ qCWarning(QT_BT) << "listening socket is not supported by IOBluetooth";
+#endif
// TODO: look at this, is this really correct?
// if we're a listening socket we can't handle connects?
if (d->readNotifier) {
@@ -641,6 +659,13 @@ void QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &service)
connectToService(service, d->openMode);
d->discoveryAgent->deleteLater();
d->discoveryAgent = nullptr;
+#ifdef QT_WINRT_BLUETOOTH
+ } else if (!service.attribute(0xBEEF).isNull()
+ && !service.attribute(0xBEF0).isNull()) {
+ connectToService(service, d->openMode);
+ d->discoveryAgent->deleteLater();
+ d->discoveryAgent = nullptr;
+#endif
} else {
qCDebug(QT_BT) << "Could not find port/psm for potential remote service";
}
diff --git a/src/bluetooth/qbluetoothsocket.h b/src/bluetooth/qbluetoothsocket.h
index eefcd2ad..8d35f77e 100644
--- a/src/bluetooth/qbluetoothsocket.h
+++ b/src/bluetooth/qbluetoothsocket.h
@@ -52,21 +52,14 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_OSX_BLUETOOTH
+
class QBluetoothSocketBasePrivate;
-#else
-class QBluetoothSocketPrivate;
-#endif
class Q_BLUETOOTH_EXPORT QBluetoothSocket : public QIODevice
{
Q_OBJECT
-#ifndef QT_OSX_BLUETOOTH
- Q_DECLARE_PRIVATE(QBluetoothSocketBase)
-#else
- Q_DECLARE_PRIVATE(QBluetoothSocket)
-#endif
+ Q_DECLARE_PRIVATE(QBluetoothSocketBase)
friend class QBluetoothServer;
friend class QBluetoothServerPrivate;
@@ -188,11 +181,8 @@ protected:
QBluetoothServiceInfo::Protocol socketType,
QObject *parent = nullptr);
#endif
-#ifndef QT_OSX_BLUETOOTH
+
QBluetoothSocketBasePrivate *d_ptr;
-#else
- QBluetoothSocketPrivate *d_ptr;
-#endif
private:
friend class QLowEnergyControllerPrivateBluez;
diff --git a/src/bluetooth/qbluetoothsocket_android.cpp b/src/bluetooth/qbluetoothsocket_android.cpp
index d7f17d17..85da325b 100644
--- a/src/bluetooth/qbluetoothsocket_android.cpp
+++ b/src/bluetooth/qbluetoothsocket_android.cpp
@@ -182,30 +182,6 @@ private:
QPointer<SocketConnectWorker> workerPointer;
};
-/*
- * This function is part of a workaround for QTBUG-61392
- *
- * Returns null uuid if the given \a serviceUuid is not a uuid
- * derived from the Bluetooth base uuid.
- */
-static QBluetoothUuid reverseUuid(const QBluetoothUuid &serviceUuid)
-{
- if (serviceUuid.isNull())
- return QBluetoothUuid();
-
- bool isBaseUuid = false;
- serviceUuid.toUInt32(&isBaseUuid);
- if (isBaseUuid)
- return serviceUuid;
-
- const quint128 original = serviceUuid.toUInt128();
- quint128 reversed;
- for (int i = 0; i < 16; i++)
- reversed.data[15-i] = original.data[i];
-
- return QBluetoothUuid(reversed);
-}
-
QBluetoothSocketPrivateAndroid::QBluetoothSocketPrivateAndroid()
:
inputThread(0)
@@ -518,7 +494,33 @@ void QBluetoothSocketPrivateAndroid::connectToService(
return;
}
- if (!ensureNativeSocket(service.socketProtocol())) {
+ // Workaround for QTBUG-75035
+ /* Not all Android devices publish or discover the SPP uuid for serial services.
+ * Also, Android does not permit the detection of the protocol used by a serial
+ * Bluetooth connection.
+ *
+ * Therefore, QBluetoothServiceDiscoveryAgentPrivate::populateDiscoveredServices()
+ * may have to guess what protocol a potential custom uuid uses. The guessing works
+ * reasonably well as long as the SDP discovery finds the SPP uuid. Otherwise
+ * the SPP and rfcomm protocol info is missing in \a service.
+ *
+ * Android only supports RFCOMM (no L2CP). We assume (in favor of user experience)
+ * that a non-RFCOMM protocol implies a missing SPP uuid during discovery but the user
+ * still wanting to connect with the given \a service instance.
+ */
+
+ auto protocol = service.socketProtocol();
+ switch (protocol) {
+ case QBluetoothServiceInfo::L2capProtocol:
+ case QBluetoothServiceInfo::UnknownProtocol:
+ qCWarning(QT_BT_ANDROID) << "Changing socket protocol to RFCOMM";
+ protocol = QBluetoothServiceInfo::RfcommProtocol;
+ break;
+ case QBluetoothServiceInfo::RfcommProtocol:
+ break;
+ }
+
+ if (!ensureNativeSocket(protocol)) {
errorString = QBluetoothSocket::tr("Socket type not supported");
q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
return;
@@ -942,6 +944,32 @@ qint64 QBluetoothSocketPrivateAndroid::bytesToWrite() const
return 0; // nothing because always unbuffered
}
+/*
+ * This function is part of a workaround for QTBUG-61392
+ *
+ * Returns null uuid if the given \a serviceUuid is not a uuid
+ * derived from the Bluetooth base uuid.
+ */
+QBluetoothUuid QBluetoothSocketPrivateAndroid::reverseUuid(const QBluetoothUuid &serviceUuid)
+{
+ if (QtAndroid::androidSdkVersion() < 23)
+ return serviceUuid;
+
+ if (serviceUuid.isNull())
+ return QBluetoothUuid();
+
+ bool isBaseUuid = false;
+ serviceUuid.toUInt32(&isBaseUuid);
+ if (isBaseUuid)
+ return serviceUuid;
+
+ const quint128 original = serviceUuid.toUInt128();
+ quint128 reversed;
+ for (int i = 0; i < 16; i++)
+ reversed.data[15-i] = original.data[i];
+ return QBluetoothUuid{reversed};
+}
+
bool QBluetoothSocketPrivateAndroid::canReadLine() const
{
// We cannot access buffer directly as it is part of different thread
diff --git a/src/bluetooth/qbluetoothsocket_android_p.h b/src/bluetooth/qbluetoothsocket_android_p.h
index 7bf42e32..042e1bcd 100644
--- a/src/bluetooth/qbluetoothsocket_android_p.h
+++ b/src/bluetooth/qbluetoothsocket_android_p.h
@@ -112,6 +112,8 @@ public:
bool canReadLine() const override;
qint64 bytesToWrite() const override;
+ static QBluetoothUuid reverseUuid(const QBluetoothUuid &serviceUuid);
+
QAndroidJniObject adapter;
QAndroidJniObject socketObject;
QAndroidJniObject remoteDevice;
diff --git a/src/bluetooth/qbluetoothsocket_bluez.cpp b/src/bluetooth/qbluetoothsocket_bluez.cpp
index bbc32a90..25f07bb3 100644
--- a/src/bluetooth/qbluetoothsocket_bluez.cpp
+++ b/src/bluetooth/qbluetoothsocket_bluez.cpp
@@ -674,6 +674,9 @@ bool QBluetoothSocketPrivateBluez::setSocketDescriptor(int socketDescriptor, QBl
connectWriteNotifier = nullptr;
socketType = socketType_;
+ if (socket != -1)
+ QT_CLOSE(socket);
+
socket = socketDescriptor;
// ensure that O_NONBLOCK is set on new connections.
diff --git a/src/bluetooth/qbluetoothsocket_bluezdbus.cpp b/src/bluetooth/qbluetoothsocket_bluezdbus.cpp
index c98d0c26..d3fc13e4 100644
--- a/src/bluetooth/qbluetoothsocket_bluezdbus.cpp
+++ b/src/bluetooth/qbluetoothsocket_bluezdbus.cpp
@@ -538,6 +538,8 @@ void QBluetoothSocketPrivateBluezDBus::remoteConnected(const QDBusUnixFileDescri
q, &QBluetoothSocket::readyRead);
connect(localSocket, &QLocalSocket::stateChanged,
this, &QBluetoothSocketPrivateBluezDBus::socketStateChanged);
+ connect(localSocket, &QLocalSocket::bytesWritten,
+ q, &QBluetoothSocket::bytesWritten);
socket = descriptor;
q->setSocketState(QBluetoothSocket::ConnectedState);
diff --git a/src/bluetooth/qbluetoothsocket_osx.mm b/src/bluetooth/qbluetoothsocket_osx.mm
index 7f630146..f74c14f8 100644
--- a/src/bluetooth/qbluetoothsocket_osx.mm
+++ b/src/bluetooth/qbluetoothsocket_osx.mm
@@ -43,6 +43,9 @@
// dependencies problem.
#include "qbluetoothsocketbase_p.h"
#include "qbluetoothsocket_osx_p.h"
+
+#include "osx/osxbtrfcommchannel_p.h"
+#include "osx/osxbtl2capchannel_p.h"
#include "qbluetoothlocaldevice.h"
#include "qbluetoothdeviceinfo.h"
#include "osx/osxbtutility_p.h"
@@ -57,30 +60,294 @@
QT_BEGIN_NAMESPACE
+namespace {
+
+using DarwinBluetooth::RetainPolicy;
+using ObjCL2CAPChannel = QT_MANGLE_NAMESPACE(OSXBTL2CAPChannel);
+using ObjCRFCOMMChannel = QT_MANGLE_NAMESPACE(OSXBTRFCOMMChannel);
+
+} // unnamed namespace
+
QBluetoothSocketPrivate::QBluetoothSocketPrivate()
- : writeChunk(std::numeric_limits<UInt16>::max()),
- openMode(QIODevice::NotOpen), // That's what is set in public class' ctors.
- state(QBluetoothSocket::UnconnectedState),
- socketType(QBluetoothServiceInfo::UnknownProtocol),
- socketError(QBluetoothSocket::NoSocketError),
- isConnecting(false)
+ : writeChunk(std::numeric_limits<UInt16>::max())
{
q_ptr = nullptr;
}
QBluetoothSocketPrivate::~QBluetoothSocketPrivate()
{
- // "Empty" dtor to make a shared pointer happy (parametrized with
- // incomplete type in the header file).
+}
+
+bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
+{
+ // For now - very simplistic, we don't call it in this file, public class
+ // only calls it in a ctor, setting the protocol RFCOMM (in case of Android)
+ // or, indeed, doing, socket-related initialization in BlueZ backend.
+ Q_ASSERT(socketType == QBluetoothServiceInfo::UnknownProtocol);
+ socketType = type;
+ return type != QBluetoothServiceInfo::UnknownProtocol;
+}
+
+QString QBluetoothSocketPrivate::localName() const
+{
+ const QBluetoothLocalDevice device;
+ return device.name();
+}
+
+QBluetoothAddress QBluetoothSocketPrivate::localAddress() const
+{
+ const QBluetoothLocalDevice device;
+ return device.address();
+}
+
+quint16 QBluetoothSocketPrivate::localPort() const
+{
+ return 0;
+}
+
+QString QBluetoothSocketPrivate::peerName() const
+{
+ QT_BT_MAC_AUTORELEASEPOOL;
+
+ NSString *nsName = nil;
+ if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
+ if (rfcommChannel)
+ nsName = [rfcommChannel.getAs<ObjCRFCOMMChannel>() peerName];
+ } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
+ if (l2capChannel)
+ nsName = [l2capChannel.getAs<ObjCL2CAPChannel>() peerName];
+ }
+
+ if (nsName)
+ return QString::fromNSString(nsName);
+
+ return QString();
+}
+
+QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
+{
+ BluetoothDeviceAddress addr = {};
+ if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
+ if (rfcommChannel)
+ addr = [rfcommChannel.getAs<ObjCRFCOMMChannel>() peerAddress];
+ } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
+ if (l2capChannel)
+ addr = [l2capChannel.getAs<ObjCL2CAPChannel>() peerAddress];
+ }
+
+ return OSXBluetooth::qt_address(&addr);
+}
+
+quint16 QBluetoothSocketPrivate::peerPort() const
+{
+ if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
+ if (rfcommChannel)
+ return [rfcommChannel.getAs<ObjCRFCOMMChannel>() getChannelID];
+ } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
+ if (l2capChannel)
+ return [l2capChannel.getAs<ObjCL2CAPChannel>() getPSM];
+ }
+
+ return 0;
+}
+
+void QBluetoothSocketPrivate::abort()
+{
+ // Can never be called while we're in connectToService:
+ Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - "
+ "still in connectToService()");
+
+ if (socketType == QBluetoothServiceInfo::RfcommProtocol)
+ rfcommChannel.reset();
+ else if (socketType == QBluetoothServiceInfo::L2capProtocol)
+ l2capChannel.reset();
+
+ Q_ASSERT(q_ptr);
+
+ q_ptr->setSocketState(QBluetoothSocket::UnconnectedState);
+ emit q_ptr->readChannelFinished();
+ emit q_ptr->disconnected();
+
+}
+
+void QBluetoothSocketPrivate::close()
+{
+ // Can never be called while we're in connectToService:
+ Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - "
+ "still in connectToService()");
+
+ if (!txBuffer.size())
+ abort();
+}
+
+
+qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
+{
+ Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)");
+ Q_ASSERT_X(maxSize > 0, Q_FUNC_INFO, "invalid data size");
+
+ if (state != QBluetoothSocket::ConnectedState) {
+ errorString = QCoreApplication::translate(SOCKET, SOC_NOWRITE);
+ q_ptr->setSocketError(QBluetoothSocket::OperationError);
+ return -1;
+ }
+
+ // We do not have a real socket API under the hood,
+ // IOBluetoothL2CAPChannel is buffered (writeAsync).
+
+ if (!txBuffer.size())
+ QMetaObject::invokeMethod(this, "_q_writeNotify", Qt::QueuedConnection);
+
+ char *dst = txBuffer.reserve(int(maxSize));
+ std::copy(data, data + maxSize, dst);
+
+ return maxSize;
+}
+
+qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
+{
+ if (!data)
+ return 0;
+
+ if (state != QBluetoothSocket::ConnectedState) {
+ errorString = QCoreApplication::translate(SOCKET, SOC_NOREAD);
+ q_ptr->setSocketError(QBluetoothSocket::OperationError);
+ return -1;
+ }
+
+ if (!buffer.isEmpty())
+ return buffer.read(data, int(maxSize));
+
+ return 0;
+}
+
+qint64 QBluetoothSocketPrivate::bytesAvailable() const
+{
+ return buffer.size();
+}
+
+bool QBluetoothSocketPrivate::canReadLine() const
+{
+ return buffer.canReadLine();
+}
+
+qint64 QBluetoothSocketPrivate::bytesToWrite() const
+{
+ return txBuffer.size();
+}
+
+bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+ QBluetoothSocket::SocketState socketState, QIODevice::OpenMode openMode)
+{
+ Q_UNUSED(socketDescriptor)
+ Q_UNUSED(socketType)
+ Q_UNUSED(socketState)
+ Q_UNUSED(openMode)
+
+ qCWarning(QT_BT_OSX) << "setting a socket descriptor is not supported by IOBluetooth";
+ // Noop on macOS.
+ return true;
+}
+
+void QBluetoothSocketPrivate::connectToServiceHelper(const QBluetoothAddress &address, quint16 port,
+ QIODevice::OpenMode openMode)
+{
+ Q_UNUSED(address)
+ Q_UNUSED(port)
+ Q_UNUSED(openMode)
+}
+
+void QBluetoothSocketPrivate::connectToService(const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
+{
+ Q_ASSERT(q_ptr);
+
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
+ if (state!= QBluetoothSocket::UnconnectedState && state != QBluetoothSocket::ServiceLookupState) {
+ qCWarning(QT_BT_OSX) << "called on a busy socket";
+ errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS);
+ q_ptr->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ // Report this problem early, potentially avoid device discovery:
+ if (service.socketProtocol() == QBluetoothServiceInfo::UnknownProtocol) {
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
+ errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
+ q_ptr->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ socketType = service.socketProtocol();
+
+ if (service.protocolServiceMultiplexer() > 0) {
+ connectToService(service.device().address(),
+ quint16(service.protocolServiceMultiplexer()),
+ openMode);
+ } else if (service.serverChannel() > 0) {
+ connectToService(service.device().address(),
+ quint16(service.serverChannel()),
+ openMode);
+ } else {
+ // Try service discovery.
+ if (service.serviceUuid().isNull()) {
+ qCWarning(QT_BT_OSX) << "No port, no PSM, and no "
+ "UUID provided, unable to connect";
+ return;
+ }
+
+ q_ptr->doDeviceDiscovery(service, openMode);
+ }
+}
+
+void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode)
+{
+ Q_ASSERT(q_ptr);
+
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
+ // Report this problem early, avoid device discovery:
+ if (socketType == QBluetoothServiceInfo::UnknownProtocol) {
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
+ errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
+ q_ptr->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ if (state != QBluetoothSocket::UnconnectedState) {
+ qCWarning(QT_BT_OSX) << "called on a busy socket";
+ errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS);
+ q_ptr->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice);
+ QBluetoothServiceInfo service;
+ service.setDevice(device);
+ service.setServiceUuid(uuid);
+ q_ptr->doDeviceDiscovery(service, openMode);
}
void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, quint16 port,
QIODevice::OpenMode mode)
{
- Q_ASSERT_X(state == QBluetoothSocket::ServiceLookupState
- || state == QBluetoothSocket::UnconnectedState,
+ Q_ASSERT(q_ptr);
+
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
+ if (socketType == QBluetoothServiceInfo::UnknownProtocol) {
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
+ errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
+ q_ptr->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ Q_ASSERT_X(state == QBluetoothSocket::ServiceLookupState || state == QBluetoothSocket::UnconnectedState,
Q_FUNC_INFO, "invalid state");
+ q_ptr->setOpenMode(mode);
+
socketError = QBluetoothSocket::NoSocketError;
errorString.clear();
buffer.clear();
@@ -100,15 +367,15 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
openMode = mode;
if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
- rfcommChannel.reset([[ObjCRFCOMMChannel alloc] initWithDelegate:this]);
+ rfcommChannel.reset([[ObjCRFCOMMChannel alloc] initWithDelegate:this], RetainPolicy::noInitialRetain);
if (rfcommChannel)
- status = [rfcommChannel connectAsyncToDevice:address withChannelID:port];
+ status = [rfcommChannel.getAs<ObjCRFCOMMChannel>() connectAsyncToDevice:address withChannelID:port];
else
status = kIOReturnNoMemory;
} else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
- l2capChannel.reset([[ObjCL2CAPChannel alloc] initWithDelegate:this]);
+ l2capChannel.reset([[ObjCL2CAPChannel alloc] initWithDelegate:this], RetainPolicy::noInitialRetain);
if (l2capChannel)
- status = [l2capChannel connectAsyncToDevice:address withPSM:port];
+ status = [l2capChannel.getAs<ObjCL2CAPChannel>() connectAsyncToDevice:address withPSM:port];
else
status = kIOReturnNoMemory;
}
@@ -148,84 +415,6 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
}
}
-void QBluetoothSocketPrivate::close()
-{
- // Can never be called while we're in connectToService:
- Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - "
- "still in connectToService()");
-
- if (!txBuffer.size())
- abort();
-}
-
-void QBluetoothSocketPrivate::abort()
-{
- // Can never be called while we're in connectToService:
- Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - "
- "still in connectToService()");
-
- if (socketType == QBluetoothServiceInfo::RfcommProtocol)
- rfcommChannel.reset(nil);
- else if (socketType == QBluetoothServiceInfo::L2capProtocol)
- l2capChannel.reset(nil);
-}
-
-quint64 QBluetoothSocketPrivate::bytesAvailable() const
-{
- return buffer.size();
-}
-
-QString QBluetoothSocketPrivate::peerName() const
-{
- QT_BT_MAC_AUTORELEASEPOOL;
-
- NSString *nsName = nil;
- if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
- if (rfcommChannel)
- nsName = [rfcommChannel peerName];
- } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
- if (l2capChannel)
- nsName = [l2capChannel peerName];
- }
-
- if (nsName)
- return QString::fromNSString(nsName);
-
- return QString();
-}
-
-QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
-{
- BluetoothDeviceAddress addr = {};
- if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
- if (rfcommChannel)
- addr = [rfcommChannel peerAddress];
- } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
- if (l2capChannel)
- addr = [l2capChannel peerAddress];
- }
-
- return OSXBluetooth::qt_address(&addr);
-}
-
-quint16 QBluetoothSocketPrivate::peerPort() const
-{
- if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
- if (rfcommChannel)
- return [rfcommChannel getChannelID];
- } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
- if (l2capChannel)
- return [l2capChannel getPSM];
- }
-
- return 0;
-}
-
-void QBluetoothSocketPrivate::_q_readNotify()
-{
- // Noop.
-}
-
void QBluetoothSocketPrivate::_q_writeNotify()
{
Q_ASSERT_X(socketType == QBluetoothServiceInfo::L2capProtocol
@@ -238,14 +427,14 @@ void QBluetoothSocketPrivate::_q_writeNotify()
if (txBuffer.size()) {
const bool isL2CAP = socketType == QBluetoothServiceInfo::L2capProtocol;
writeChunk.resize(isL2CAP ? std::numeric_limits<UInt16>::max() :
- [rfcommChannel getMTU]);
+ [rfcommChannel.getAs<ObjCRFCOMMChannel>() getMTU]);
const int size = txBuffer.read(writeChunk.data(), writeChunk.size());
IOReturn status = kIOReturnError;
if (!isL2CAP)
- status = [rfcommChannel writeAsync:writeChunk.data() length:UInt16(size)];
+ status = [rfcommChannel.getAs<ObjCRFCOMMChannel>() writeAsync:writeChunk.data() length:UInt16(size)];
else
- status = [l2capChannel writeAsync:writeChunk.data() length:UInt16(size)];
+ status = [l2capChannel.getAs<ObjCL2CAPChannel>() writeAsync:writeChunk.data() length:UInt16(size)];
if (status != kIOReturnSuccess) {
errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
@@ -260,21 +449,22 @@ void QBluetoothSocketPrivate::_q_writeNotify()
close();
}
-bool QBluetoothSocketPrivate::setChannel(IOBluetoothRFCOMMChannel *channel)
+bool QBluetoothSocketPrivate::setRFCOMChannel(void *generic)
{
// A special case "constructor": on OS X we do not have a real listening socket,
// instead a bluetooth server "listens" for channel open notifications and
// creates (if asked by a user later) a "socket" object
// for this connection. This function initializes
// a "socket" from such an external channel (reported by a notification).
-
+ auto channel = static_cast<IOBluetoothRFCOMMChannel *>(generic);
// It must be a newborn socket!
Q_ASSERT_X(socketError == QBluetoothSocket::NoSocketError
&& state == QBluetoothSocket::UnconnectedState && !rfcommChannel && !l2capChannel,
Q_FUNC_INFO, "unexpected socket state");
openMode = QIODevice::ReadWrite;
- rfcommChannel.reset([[ObjCRFCOMMChannel alloc] initWithDelegate:this channel:channel]);
+ rfcommChannel.reset([[ObjCRFCOMMChannel alloc] initWithDelegate:this channel:channel],
+ RetainPolicy::noInitialRetain);
if (rfcommChannel) {// We do not handle errors, up to an external user.
q_ptr->setOpenMode(QIODevice::ReadWrite);
state = QBluetoothSocket::ConnectedState;
@@ -284,13 +474,14 @@ bool QBluetoothSocketPrivate::setChannel(IOBluetoothRFCOMMChannel *channel)
return rfcommChannel;
}
-bool QBluetoothSocketPrivate::setChannel(IOBluetoothL2CAPChannel *channel)
+bool QBluetoothSocketPrivate::setL2CAPChannel(void *generic)
{
// A special case "constructor": on OS X we do not have a real listening socket,
// instead a bluetooth server "listens" for channel open notifications and
// creates (if asked by a user later) a "socket" object
// for this connection. This function initializes
// a "socket" from such an external channel (reported by a notification).
+ auto channel = static_cast<IOBluetoothL2CAPChannel *>(generic);
// It must be a newborn socket!
Q_ASSERT_X(socketError == QBluetoothSocket::NoSocketError
@@ -298,7 +489,7 @@ bool QBluetoothSocketPrivate::setChannel(IOBluetoothL2CAPChannel *channel)
Q_FUNC_INFO, "unexpected socket state");
openMode = QIODevice::ReadWrite;
- l2capChannel.reset([[ObjCL2CAPChannel alloc] initWithDelegate:this channel:channel]);
+ l2capChannel.reset([[ObjCL2CAPChannel alloc] initWithDelegate:this channel:channel], RetainPolicy::noInitialRetain);
if (l2capChannel) {// We do not handle errors, up to an external user.
q_ptr->setOpenMode(QIODevice::ReadWrite);
state = QBluetoothSocket::ConnectedState;
@@ -308,7 +499,6 @@ bool QBluetoothSocketPrivate::setChannel(IOBluetoothL2CAPChannel *channel)
return l2capChannel;
}
-
void QBluetoothSocketPrivate::setChannelError(IOReturn errorCode)
{
Q_UNUSED(errorCode)
@@ -365,7 +555,7 @@ void QBluetoothSocketPrivate::readChannelData(void *data, std::size_t size)
Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
const char *src = static_cast<char *>(data);
- char *dst = buffer.reserve(size);
+ char *dst = buffer.reserve(int(size));
std::copy(src, src + size, dst);
if (!isConnecting) {
@@ -379,449 +569,4 @@ void QBluetoothSocketPrivate::writeComplete()
_q_writeNotify();
}
-qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
-{
- Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)");
- Q_ASSERT_X(maxSize > 0, Q_FUNC_INFO, "invalid data size");
-
- if (state != QBluetoothSocket::ConnectedState) {
- errorString = QCoreApplication::translate(SOCKET, SOC_NOWRITE);
- q_ptr->setSocketError(QBluetoothSocket::OperationError);
- return -1;
- }
-
- // We do not have a real socket API under the hood,
- // IOBluetoothL2CAPChannel buffered (writeAsync).
-
- if (!txBuffer.size())
- QMetaObject::invokeMethod(this, "_q_writeNotify", Qt::QueuedConnection);
-
- char *dst = txBuffer.reserve(maxSize);
- std::copy(data, data + maxSize, dst);
-
- return maxSize;
-}
-
-QBluetoothSocket::QBluetoothSocket(QBluetoothServiceInfo::Protocol socketType, QObject *parent)
- : QIODevice(parent),
- d_ptr(new QBluetoothSocketPrivate)
-{
- d_ptr->q_ptr = this;
- d_ptr->socketType = socketType;
-
- setOpenMode(NotOpen);
-}
-
-QBluetoothSocket::QBluetoothSocket(QObject *parent)
- : QIODevice(parent),
- d_ptr(new QBluetoothSocketPrivate)
-{
- d_ptr->q_ptr = this;
- setOpenMode(NotOpen);
-}
-
-QBluetoothSocket::~QBluetoothSocket()
-{
- delete d_ptr;
-}
-
-bool QBluetoothSocket::isSequential() const
-{
- return true;
-}
-
-qint64 QBluetoothSocket::bytesAvailable() const
-{
- return QIODevice::bytesAvailable() + d_ptr->bytesAvailable();
-}
-
-qint64 QBluetoothSocket::bytesToWrite() const
-{
- return d_ptr->txBuffer.size();
-}
-
-void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, OpenMode openMode)
-{
- OSXBluetooth::qt_test_iobluetooth_runloop();
-
- if (state() != UnconnectedState && state() != ServiceLookupState) {
- qCWarning(QT_BT_OSX) << "called on a busy socket";
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS);
- setSocketError(OperationError);
- return;
- }
-
- // Report this problem early, potentially avoid device discovery:
- if (service.socketProtocol() == QBluetoothServiceInfo::UnknownProtocol) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
-
- d_ptr->socketType = service.socketProtocol();
-
- if (service.protocolServiceMultiplexer() > 0) {
- d_ptr->connectToService(service.device().address(),
- service.protocolServiceMultiplexer(),
- openMode);
- } else if (service.serverChannel() > 0) {
- d_ptr->connectToService(service.device().address(),
- service.serverChannel(), openMode);
- } else {
- // Try service discovery.
- if (service.serviceUuid().isNull()) {
- qCWarning(QT_BT_OSX) << "No port, no PSM, and no "
- "UUID provided, unable to connect";
- return;
- }
-
- doDeviceDiscovery(service, openMode);
- }
-}
-
-void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
- OpenMode openMode)
-{
- OSXBluetooth::qt_test_iobluetooth_runloop();
-
- // Report this problem early, avoid device discovery:
- if (socketType() == QBluetoothServiceInfo::UnknownProtocol) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
-
- if (state() != QBluetoothSocket::UnconnectedState) {
- qCWarning(QT_BT_OSX) << "called on a busy socket";
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS);
- setSocketError(QBluetoothSocket::OperationError);
- return;
- }
-
- QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice);
- QBluetoothServiceInfo service;
- service.setDevice(device);
- service.setServiceUuid(uuid);
- doDeviceDiscovery(service, openMode);
-}
-
-void QBluetoothSocket::connectToService(const QBluetoothAddress &address, quint16 port,
- OpenMode openMode)
-{
- OSXBluetooth::qt_test_iobluetooth_runloop();
-
- if (socketType() == QBluetoothServiceInfo::UnknownProtocol) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
-
- if (state() != QBluetoothSocket::UnconnectedState) {
- qCWarning(QT_BT_OSX) << "called on a busy socket";
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS);
- setSocketError(OperationError);
- return;
- }
-
- setOpenMode(openMode);
- d_ptr->connectToService(address, port, openMode);
-}
-
-QBluetoothServiceInfo::Protocol QBluetoothSocket::socketType() const
-{
- return d_ptr->socketType;
-}
-
-QBluetoothSocket::SocketState QBluetoothSocket::state() const
-{
- return d_ptr->state;
-}
-
-QBluetoothSocket::SocketError QBluetoothSocket::error() const
-{
- return d_ptr->socketError;
-}
-
-QString QBluetoothSocket::errorString() const
-{
- return d_ptr->errorString;
-}
-
-void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state)
-{
- const SocketState oldState = d_ptr->state;
- d_ptr->state = state;
- if (oldState != d_ptr->state)
- emit stateChanged(state);
-
- if (state == ListeningState) {
- // We can register for L2CAP/RFCOMM open notifications,
- // that's different from 'listen' and is implemented
- // in QBluetoothServer.
- qCWarning(QT_BT_OSX) << "listening sockets are not supported";
- }
-}
-
-bool QBluetoothSocket::canReadLine() const
-{
- return d_ptr->buffer.canReadLine() || QIODevice::canReadLine();
-}
-
-void QBluetoothSocket::setSocketError(QBluetoothSocket::SocketError socketError)
-{
- d_ptr->socketError = socketError;
- emit error(socketError);
-}
-
-void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, OpenMode openMode)
-{
- OSXBluetooth::qt_test_iobluetooth_runloop();
-
- setSocketState(ServiceLookupState);
-
- if (d_ptr->discoveryAgent)
- d_ptr->discoveryAgent->stop();
-
- d_ptr->discoveryAgent.reset(new QBluetoothServiceDiscoveryAgent(this));
- d_ptr->discoveryAgent->setRemoteAddress(service.device().address());
-
- connect(d_ptr->discoveryAgent.data(), SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
- this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
- connect(d_ptr->discoveryAgent.data(), SIGNAL(finished()),
- this, SLOT(discoveryFinished()));
-
- d_ptr->openMode = openMode;
-
- if (!service.serviceUuid().isNull())
- d_ptr->discoveryAgent->setUuidFilter(service.serviceUuid());
-
- if (!service.serviceClassUuids().isEmpty())
- d_ptr->discoveryAgent->setUuidFilter(service.serviceClassUuids());
-
- Q_ASSERT_X(!d_ptr->discoveryAgent->uuidFilter().isEmpty(), Q_FUNC_INFO,
- "invalid service info");
-
- d_ptr->discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery);
-}
-
-void QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &service)
-{
- if (service.protocolServiceMultiplexer() != 0 || service.serverChannel() != 0) {
- d_ptr->discoveryAgent->stop();
- connectToService(service, d_ptr->openMode);
- }
-}
-
-void QBluetoothSocket::discoveryFinished()
-{
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_SERVICE_NOT_FOUND);
- setSocketState(UnconnectedState);
- setSocketError(ServiceNotFoundError);
-}
-
-void QBluetoothSocket::abort()
-{
- if (state() == UnconnectedState)
- return;
-
- setOpenMode(NotOpen);
-
- if (state() == ServiceLookupState && d_ptr->discoveryAgent) {
- d_ptr->discoveryAgent->disconnect();
- d_ptr->discoveryAgent->stop();
- d_ptr->discoveryAgent.reset();
- }
-
- setSocketState(QBluetoothSocket::ClosingState);
- d_ptr->abort();
-
- setSocketState(QBluetoothSocket::UnconnectedState);
- emit readChannelFinished();
- emit disconnected();
-}
-
-void QBluetoothSocket::disconnectFromService()
-{
- close();
-}
-
-QString QBluetoothSocket::localName() const
-{
- const QBluetoothLocalDevice device;
- return device.name();
-}
-
-QBluetoothAddress QBluetoothSocket::localAddress() const
-{
- const QBluetoothLocalDevice device;
- return device.address();
-}
-
-quint16 QBluetoothSocket::localPort() const
-{
- return 0;
-}
-
-QString QBluetoothSocket::peerName() const
-{
- return d_ptr->peerName();
-}
-
-QBluetoothAddress QBluetoothSocket::peerAddress() const
-{
- return d_ptr->peerAddress();
-}
-
-quint16 QBluetoothSocket::peerPort() const
-{
- return d_ptr->peerPort();
-}
-
-qint64 QBluetoothSocket::writeData(const char *data, qint64 maxSize)
-{
- if (!data || maxSize <= 0) {
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_INVAL_DATASIZE);
- setSocketError(QBluetoothSocket::OperationError);
- return -1;
- }
-
- return d_ptr->writeData(data, maxSize);
-}
-
-qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
-{
- if (state != QBluetoothSocket::ConnectedState) {
- errorString = QCoreApplication::translate(SOCKET, SOC_NOREAD);
- q_ptr->setSocketError(QBluetoothSocket::OperationError);
- return -1;
- }
-
- if (!buffer.isEmpty())
- return buffer.read(data, maxSize);
-
- return 0;
-}
-
-qint64 QBluetoothSocket::readData(char *data, qint64 maxSize)
-{
- return d_ptr->readData(data, maxSize);
-}
-
-void QBluetoothSocket::close()
-{
- if (state() == UnconnectedState)
- return;
-
- setOpenMode(NotOpen);
-
- if (state() == ServiceLookupState && d_ptr->discoveryAgent) {
- d_ptr->discoveryAgent->disconnect();
- d_ptr->discoveryAgent->stop();
- d_ptr->discoveryAgent.reset();
- }
-
- setSocketState(ClosingState);
-
- d_ptr->close();
-
- setSocketState(UnconnectedState);
- emit readChannelFinished();
- emit disconnected();
-}
-
-bool QBluetoothSocket::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
- SocketState socketState, OpenMode openMode)
-{
- Q_UNUSED(socketDescriptor)
- Q_UNUSED(socketType)
- Q_UNUSED(socketState)
- Q_UNUSED(openMode)
-
- // Noop on OS X.
- return true;
-}
-
-int QBluetoothSocket::socketDescriptor() const
-{
- return -1;
-}
-
-/* not supported on OS X */
-void QBluetoothSocket::setPreferredSecurityFlags(QBluetooth::SecurityFlags flags)
-{
- Q_UNUSED(flags)
-}
-
-/* not supported on OS X - platform always uses encryption */
-QBluetooth::SecurityFlags QBluetoothSocket::preferredSecurityFlags() const
-{
- return QBluetooth::Secure;
-}
-
-#ifndef QT_NO_DEBUG_STREAM
-
-QDebug operator<<(QDebug debug, QBluetoothSocket::SocketError error)
-{
- switch (error) {
- case QBluetoothSocket::UnknownSocketError:
- debug << "QBluetoothSocket::UnknownSocketError";
- break;
- case QBluetoothSocket::HostNotFoundError:
- debug << "QBluetoothSocket::HostNotFoundError";
- break;
- case QBluetoothSocket::RemoteHostClosedError:
- debug << "QBluetoothSocket::RemoteHostClosedError";
- break;
- case QBluetoothSocket::ServiceNotFoundError:
- debug << "QBluetoothSocket::ServiceNotFoundError";
- break;
- case QBluetoothSocket::NetworkError:
- debug << "QBluetoothSocket::NetworkError";
- break;
- case QBluetoothSocket::UnsupportedProtocolError:
- debug << "QBluetoothSocket::UnsupportedProtocolError";
- break;
- default:
- debug << "QBluetoothSocket::SocketError(" << (int)error << ")";
- }
- return debug;
-}
-
-QDebug operator<<(QDebug debug, QBluetoothSocket::SocketState state)
-{
- switch (state) {
- case QBluetoothSocket::UnconnectedState:
- debug << "QBluetoothSocket::UnconnectedState";
- break;
- case QBluetoothSocket::ConnectingState:
- debug << "QBluetoothSocket::ConnectingState";
- break;
- case QBluetoothSocket::ConnectedState:
- debug << "QBluetoothSocket::ConnectedState";
- break;
- case QBluetoothSocket::BoundState:
- debug << "QBluetoothSocket::BoundState";
- break;
- case QBluetoothSocket::ClosingState:
- debug << "QBluetoothSocket::ClosingState";
- break;
- case QBluetoothSocket::ListeningState:
- debug << "QBluetoothSocket::ListeningState";
- break;
- case QBluetoothSocket::ServiceLookupState:
- debug << "QBluetoothSocket::ServiceLookupState";
- break;
- default:
- debug << "QBluetoothSocket::SocketState(" << (int)state << ")";
- }
- return debug;
-}
-
-#endif // QT_NO_DEBUG_STREAM
-
-#include "moc_qbluetoothsocket.cpp"
-
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothsocket_osx_p.h b/src/bluetooth/qbluetoothsocket_osx_p.h
index dcc684b8..1291878c 100644
--- a/src/bluetooth/qbluetoothsocket_osx_p.h
+++ b/src/bluetooth/qbluetoothsocket_osx_p.h
@@ -53,12 +53,11 @@
#ifdef QT_OSX_BLUETOOTH
-#include "osx/osxbtchanneldelegate_p.h"
-#include "osx/osxbtrfcommchannel_p.h"
-#include "osx/osxbtl2capchannel_p.h"
+#include "qbluetoothsocketbase_p.h"
#include "qbluetoothserviceinfo.h"
-#include "osx/osxbtutility_p.h"
+#include "osx/btdelegates_p.h"
#include "qbluetoothsocket.h"
+#include "osx/btraii_p.h"
#ifndef QPRIVATELINEARBUFFER_BUFFERSIZE
#define QPRIVATELINEARBUFFER_BUFFERSIZE Q_INT64_C(16384)
@@ -74,14 +73,11 @@
#include <QtCore/qstring.h>
#include <QtCore/qvector.h>
-@class IOBluetoothRFCOMMChannel;
-@class IOBluetoothL2CAPChannel;
-
QT_BEGIN_NAMESPACE
class QBluetoothAddress;
-class QBluetoothSocketPrivate : public QBluetoothSocketBasePrivate, public OSXBluetooth::ChannelDelegate
+class QBluetoothSocketPrivate : public QBluetoothSocketBasePrivate, public DarwinBluetooth::ChannelDelegate
{
friend class QBluetoothSocket;
friend class QBluetoothServer;
@@ -90,25 +86,47 @@ public:
QBluetoothSocketPrivate();
~QBluetoothSocketPrivate();
- void connectToService(const QBluetoothAddress &address, quint16 port,
- QIODevice::OpenMode openMode);
+ //
+ bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override;
+
+ QString localName() const override;
+ QBluetoothAddress localAddress() const override;
+ quint16 localPort() const override;
+
+ QString peerName() const override;
+ QBluetoothAddress peerAddress() const override;
+ quint16 peerPort() const override;
- void close();
- void abort();
+ void abort() override;
+ void close() override;
- quint64 bytesAvailable() const;
+ qint64 writeData(const char *data, qint64 maxSize) override;
+ qint64 readData(char *data, qint64 maxSize) override;
- QString peerName() const;
- QBluetoothAddress peerAddress() const;
- quint16 peerPort() const;
+ qint64 bytesAvailable() const override;
+ bool canReadLine() const override;
+ qint64 bytesToWrite() const override;
- void _q_readNotify();
- void _q_writeNotify() override;
+ bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+ QBluetoothSocket::SocketState socketState,
+ QBluetoothSocket::OpenMode openMode) override;
+
+ void connectToServiceHelper(const QBluetoothAddress &address, quint16 port,
+ QIODevice::OpenMode openMode) override;
+ void connectToService(const QBluetoothServiceInfo &service,
+ QIODevice::OpenMode openMode) override;
+ void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode) override;
+
+ void connectToService(const QBluetoothAddress &address, quint16 port,
+ QIODevice::OpenMode openMode) override;
+
+ void _q_writeNotify();
private:
// Create a socket from an external source (without connectToService).
- bool setChannel(IOBluetoothRFCOMMChannel *channel);
- bool setChannel(IOBluetoothL2CAPChannel *channel);
+ bool setRFCOMChannel(void *channel);
+ bool setL2CAPChannel(void *channel);
// L2CAP and RFCOMM delegate
void setChannelError(IOReturn errorCode) override;
@@ -117,33 +135,15 @@ private:
void readChannelData(void *data, std::size_t size) override;
void writeComplete() override;
- qint64 writeData(const char *data, qint64 maxSize);
- qint64 readData(char *data, qint64 maxSize);
-
- QScopedPointer<QBluetoothServiceDiscoveryAgent> discoveryAgent;
-
- QPrivateLinearBuffer buffer;
- QPrivateLinearBuffer txBuffer;
QVector<char> writeChunk;
- // Probably, not needed.
- QIODevice::OpenMode openMode;
-
- QBluetoothSocket::SocketState state;
- QBluetoothServiceInfo::Protocol socketType;
-
- QBluetoothSocket::SocketError socketError;
- QString errorString;
-
- typedef QT_MANGLE_NAMESPACE(OSXBTL2CAPChannel) ObjCL2CAPChannel;
- typedef OSXBluetooth::ObjCScopedPointer<ObjCL2CAPChannel> L2CAPChannel;
+ using L2CAPChannel = DarwinBluetooth::ScopedPointer;
L2CAPChannel l2capChannel;
- typedef QT_MANGLE_NAMESPACE(OSXBTRFCOMMChannel) ObjCRFCOMMChannel;
- typedef OSXBluetooth::ObjCScopedPointer<ObjCRFCOMMChannel> RFCOMMChannel;
+ using RFCOMMChannel = L2CAPChannel;
RFCOMMChannel rfcommChannel;
// A trick to deal with channel open too fast (synchronously).
- bool isConnecting;
+ bool isConnecting = false;
};
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothsocket_winrt.cpp b/src/bluetooth/qbluetoothsocket_winrt.cpp
index 79dccdd6..48b14757 100644
--- a/src/bluetooth/qbluetoothsocket_winrt.cpp
+++ b/src/bluetooth/qbluetoothsocket_winrt.cpp
@@ -94,15 +94,22 @@ static inline QString qt_QStringFromHString(const HString &string)
{
UINT32 length;
PCWSTR rawString = string.GetRawBuffer(&length);
- return QString::fromWCharArray(rawString, length);
+ if (length > INT_MAX)
+ length = INT_MAX;
+ return QString::fromWCharArray(rawString, int(length));
}
static qint64 writeIOStream(ComPtr<IOutputStream> stream, const char *data, qint64 len)
{
ComPtr<IBuffer> buffer;
- HRESULT hr = g->bufferFactory->Create(len, &buffer);
+ if (len > UINT32_MAX) {
+ qCWarning(QT_BT_WINRT) << "writeIOStream can only write up to" << UINT32_MAX << "bytes.";
+ len = UINT32_MAX;
+ }
+ quint32 ulen = static_cast<quint32>(len);
+ HRESULT hr = g->bufferFactory->Create(ulen, &buffer);
Q_ASSERT_SUCCEEDED(hr);
- hr = buffer->put_Length(len);
+ hr = buffer->put_Length(ulen);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
hr = buffer.As(&byteArrayAccess);
@@ -110,7 +117,7 @@ static qint64 writeIOStream(ComPtr<IOutputStream> stream, const char *data, qint
byte *bytes;
hr = byteArrayAccess->Buffer(&bytes);
Q_ASSERT_SUCCEEDED(hr);
- memcpy(bytes, data, len);
+ memcpy(bytes, data, ulen);
ComPtr<IAsyncOperationWithProgress<UINT32, UINT32>> op;
hr = stream->WriteAsync(buffer.Get(), &op);
RETURN_IF_FAILED("Failed to write to stream", return -1);
@@ -257,7 +264,7 @@ public:
return S_OK;
}
- QByteArray newData(reinterpret_cast<const char*>(data), qint64(bufferLength));
+ QByteArray newData(reinterpret_cast<const char*>(data), int(bufferLength));
QMutexLocker readLocker(&m_mutex);
if (m_pendingData.isEmpty())
QMetaObject::invokeMethod(this, "notifyAboutNewData", Qt::QueuedConnection);
@@ -359,10 +366,11 @@ bool QBluetoothSocketPrivateWinRT::ensureNativeSocket(QBluetoothServiceInfo::Pro
return true;
}
-void QBluetoothSocketPrivateWinRT::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+void QBluetoothSocketPrivateWinRT::connectToService(Microsoft::WRL::ComPtr<IHostName> hostName,
+ const QString &serviceName,
+ QIODevice::OpenMode openMode)
{
Q_Q(QBluetoothSocket);
- Q_UNUSED(openMode);
if (socket == -1 && !ensureNativeSocket(socketType)) {
errorString = QBluetoothSocket::tr("Unknown socket error");
@@ -370,20 +378,9 @@ void QBluetoothSocketPrivateWinRT::connectToServiceHelper(const QBluetoothAddres
return;
}
- const QString addressString = address.toString();
- HStringReference hostNameRef(reinterpret_cast<LPCWSTR>(addressString.utf16()));
- ComPtr<IHostNameFactory> hostNameFactory;
- HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
- &hostNameFactory);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IHostName> remoteHost;
- hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost);
- RETURN_VOID_IF_FAILED("QBluetoothSocketPrivateWinRT::connectToService: Could not create hostname.");
-
- const QString portString = QString::number(port);
- HStringReference portReference(reinterpret_cast<LPCWSTR>(portString.utf16()));
+ HStringReference serviceNameReference(reinterpret_cast<LPCWSTR>(serviceName.utf16()));
- hr = m_socketObject->ConnectAsync(remoteHost.Get(), portReference.Get(), &m_connectOp);
+ HRESULT hr = m_socketObject->ConnectAsync(hostName.Get(), serviceNameReference.Get(), &m_connectOp);
if (hr == E_ACCESSDENIED) {
qErrnoWarning(hr, "QBluetoothSocketPrivateWinRT::connectToService: Unable to connect to bluetooth socket."
"Please check your manifest capabilities.");
@@ -404,6 +401,29 @@ void QBluetoothSocketPrivateWinRT::connectToServiceHelper(const QBluetoothAddres
Q_ASSERT_SUCCEEDED(hr);
}
+void QBluetoothSocketPrivateWinRT::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+{
+ Q_Q(QBluetoothSocket);
+
+ if (socket == -1 && !ensureNativeSocket(socketType)) {
+ errorString = QBluetoothSocket::tr("Unknown socket error");
+ q->setSocketError(QBluetoothSocket::UnknownSocketError);
+ return;
+ }
+
+ const QString addressString = address.toString();
+ HStringReference hostNameRef(reinterpret_cast<LPCWSTR>(addressString.utf16()));
+ ComPtr<IHostNameFactory> hostNameFactory;
+ HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
+ &hostNameFactory);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IHostName> remoteHost;
+ hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost);
+ RETURN_VOID_IF_FAILED("QBluetoothSocketPrivateWinRT::connectToService: Could not create hostname.");
+ const QString portString = QString::number(port);
+ connectToService(remoteHost, portString, openMode);
+}
+
void QBluetoothSocketPrivateWinRT::connectToService(
const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
{
@@ -425,6 +445,8 @@ void QBluetoothSocketPrivateWinRT::connectToService(
return;
}
+ const QString connectionHostName = service.attribute(0xBEEF).toString();
+ const QString connectionServiceName = service.attribute(0xBEF0).toString();
if (service.protocolServiceMultiplexer() > 0) {
Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::L2capProtocol);
@@ -433,8 +455,24 @@ void QBluetoothSocketPrivateWinRT::connectToService(
q->setSocketError(QBluetoothSocket::UnknownSocketError);
return;
}
- connectToServiceHelper(service.device().address(), service.protocolServiceMultiplexer(), openMode);
- } else if (service.serverChannel() > 0) {
+ connectToServiceHelper(service.device().address(),
+ quint16(service.protocolServiceMultiplexer()), openMode);
+ } else if (!connectionHostName.isEmpty() && !connectionServiceName.isEmpty()) {
+ Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol);
+ if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
+ errorString = QBluetoothSocket::tr("Unknown socket error");
+ q->setSocketError(QBluetoothSocket::UnknownSocketError);
+ return;
+ }
+ HStringReference hostNameRef(reinterpret_cast<LPCWSTR>(connectionHostName.utf16()));
+ ComPtr<IHostNameFactory> hostNameFactory;
+ HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
+ &hostNameFactory);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IHostName> remoteHost;
+ hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost);
+ connectToService(remoteHost, connectionServiceName, openMode);
+ } else if (service.serverChannel() > 0) {
Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol);
if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
@@ -442,8 +480,9 @@ void QBluetoothSocketPrivateWinRT::connectToService(
q->setSocketError(QBluetoothSocket::UnknownSocketError);
return;
}
- connectToServiceHelper(service.device().address(), service.serverChannel(), openMode);
- } else {
+ connectToServiceHelper(service.device().address(), quint16(service.serverChannel()),
+ openMode);
+ } else {
// try doing service discovery to see if we can find the socket
if (service.serviceUuid().isNull()
&& !service.serviceClassUuids().contains(QBluetoothUuid::SerialPort)) {
@@ -567,7 +606,13 @@ quint16 QBluetoothSocketPrivateWinRT::localPort() const
HString localPortString;
hr = info->get_LocalPort(localPortString.GetAddressOf());
Q_ASSERT_SUCCEEDED(hr);
- return qt_QStringFromHString(localPortString).toInt();
+ bool ok = true;
+ const uint port = qt_QStringFromHString(localPortString).toUInt(&ok);
+ if (!ok || port > UINT16_MAX) {
+ qCWarning(QT_BT_WINRT) << "Unexpected local port";
+ return 0;
+ }
+ return quint16(port);
}
QString QBluetoothSocketPrivateWinRT::peerName() const
@@ -618,7 +663,13 @@ quint16 QBluetoothSocketPrivateWinRT::peerPort() const
HString remotePortString;
hr = info->get_LocalPort(remotePortString.GetAddressOf());
Q_ASSERT_SUCCEEDED(hr);
- return qt_QStringFromHString(remotePortString).toInt();
+ bool ok = true;
+ const uint port = qt_QStringFromHString(remotePortString).toUInt(&ok);
+ if (!ok || port > UINT16_MAX) {
+ qCWarning(QT_BT_WINRT) << "Unexpected remote port";
+ return 0;
+ }
+ return quint16(port);
}
qint64 QBluetoothSocketPrivateWinRT::writeData(const char *data, qint64 maxSize)
@@ -657,8 +708,11 @@ qint64 QBluetoothSocketPrivateWinRT::readData(char *data, qint64 maxSize)
return -1;
}
- if (!buffer.isEmpty())
- return buffer.read(data, maxSize);
+ if (!buffer.isEmpty()) {
+ if (maxSize > INT_MAX)
+ maxSize = INT_MAX;
+ return buffer.read(data, int(maxSize));
+ }
return 0;
}
@@ -749,7 +803,7 @@ void QBluetoothSocketPrivateWinRT::addToPendingData(const QVector<QByteArray> &d
m_pendingData.append(data);
for (const QByteArray &newData : data) {
char *writePointer = buffer.reserve(newData.length());
- memcpy(writePointer, newData.data(), newData.length());
+ memcpy(writePointer, newData.data(), size_t(newData.length()));
}
locker.unlock();
emit q->readyRead();
@@ -767,17 +821,22 @@ HRESULT QBluetoothSocketPrivateWinRT::handleConnectOpFinished(ABI::Windows::Foun
HRESULT hr = action->GetResults();
switch (hr) {
- case 0x8007274c: // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
+
+ // A connection attempt failed because the connected party did not properly respond after a
+ // period of time, or established connection failed because connected host has failed to respond.
+ case HRESULT_FROM_WIN32(WSAETIMEDOUT):
errorString = QBluetoothSocket::tr("Connection timed out");
q->setSocketError(QBluetoothSocket::NetworkError);
q->setSocketState(QBluetoothSocket::UnconnectedState);
return S_OK;
- case 0x80072751: // A socket operation was attempted to an unreachable host.
+ // A socket operation was attempted to an unreachable host.
+ case HRESULT_FROM_WIN32(WSAEHOSTUNREACH):
errorString = QBluetoothSocket::tr("Host not reachable");
q->setSocketError(QBluetoothSocket::HostNotFoundError);
q->setSocketState(QBluetoothSocket::UnconnectedState);
return S_OK;
- case 0x8007274d: // No connection could be made because the target machine actively refused it.
+ // No connection could be made because the target machine actively refused it.
+ case HRESULT_FROM_WIN32(WSAECONNREFUSED):
errorString = QBluetoothSocket::tr("Host refused connection");
q->setSocketError(QBluetoothSocket::HostNotFoundError);
q->setSocketState(QBluetoothSocket::UnconnectedState);
@@ -802,8 +861,7 @@ HRESULT QBluetoothSocketPrivateWinRT::handleConnectOpFinished(ABI::Windows::Foun
hr = info->Close();
Q_ASSERT_SUCCEEDED(hr);
}
- hr = m_connectOp.Reset();
- Q_ASSERT_SUCCEEDED(hr);
+ m_connectOp.Reset();
}
q->setOpenMode(requestedOpenMode);
diff --git a/src/bluetooth/qbluetoothsocket_winrt_p.h b/src/bluetooth/qbluetoothsocket_winrt_p.h
index 40e87f01..de8b7d67 100644
--- a/src/bluetooth/qbluetoothsocket_winrt_p.h
+++ b/src/bluetooth/qbluetoothsocket_winrt_p.h
@@ -57,6 +57,19 @@
QT_FORWARD_DECLARE_CLASS(SocketWorker)
+namespace ABI {
+ namespace Windows {
+ namespace Networking {
+ struct IHostName;
+ }
+ }
+}
+
+namespace Microsoft {
+ namespace WRL {
+ template <typename T> class ComPtr;
+ }
+}
QT_BEGIN_NAMESPACE
class QBluetoothSocketPrivateWinRT final: public QBluetoothSocketBasePrivate
@@ -125,6 +138,8 @@ private slots:
void handleError(QBluetoothSocket::SocketError error);
private:
+ void connectToService(Microsoft::WRL::ComPtr<ABI::Windows::Networking::IHostName> hostName,
+ const QString &serviceName, QIODevice::OpenMode openMode);
HRESULT handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *action,
ABI::Windows::Foundation::AsyncStatus status);
diff --git a/src/bluetooth/qbluetoothsocketbase_p.h b/src/bluetooth/qbluetoothsocketbase_p.h
index 410dcbbd..d1894e96 100644
--- a/src/bluetooth/qbluetoothsocketbase_p.h
+++ b/src/bluetooth/qbluetoothsocketbase_p.h
@@ -89,7 +89,6 @@ QT_FORWARD_DECLARE_CLASS(QBluetoothServiceDiscoveryAgent)
QT_BEGIN_NAMESPACE
-#ifndef QT_OSX_BLUETOOTH
class QBluetoothSocketBasePrivate : public QObject
{
Q_OBJECT
@@ -198,26 +197,6 @@ static inline quint64 convertAddress(const quint8 (&from)[6], quint64 *to = null
return result;
}
-#else // QT_OSX_BLUETOOTH
-
-// QBluetoothSocketPrivate on macOS can not contain
-// Q_OBJECT (moc does not parse Objective-C syntax).
-// But QBluetoothSocket still requires QMetaObject::invokeMethod
-// to work. Here's the trick:
-class QBluetoothSocketBasePrivate : public QObject
-{
-// The most important part of it:
- Q_OBJECT
-public slots:
- virtual void _q_writeNotify() = 0;
-
-protected:
- Q_DECLARE_PUBLIC(QBluetoothSocket)
- QBluetoothSocket *q_ptr;
-};
-
-#endif // QT_OSX_BLUETOOTH
-
QT_END_NAMESPACE
#endif // QBLUETOOTHSOCKETBASE_P_H
diff --git a/src/bluetooth/qbluetoothutils_winrt.cpp b/src/bluetooth/qbluetoothutils_winrt.cpp
index 1d44221b..de4355c6 100644
--- a/src/bluetooth/qbluetoothutils_winrt.cpp
+++ b/src/bluetooth/qbluetoothutils_winrt.cpp
@@ -42,12 +42,15 @@
#include <QtCore/qfunctions_winrt.h>
+#include <robuffer.h>
#include <wrl.h>
#include <windows.foundation.metadata.h>
+#include <windows.storage.streams.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation::Metadata;
+using namespace ABI::Windows::Storage::Streams;
QT_BEGIN_NAMESPACE
@@ -76,4 +79,26 @@ bool supportsNewLEApi()
return apiPresent;
}
+QByteArray byteArrayFromBuffer(const ComPtr<NativeBuffer> &buffer, bool isWCharString)
+{
+ if (!buffer) {
+ qErrnoWarning("nullptr passed to byteArrayFromBuffer");
+ return QByteArray();
+ }
+ ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteAccess;
+ HRESULT hr = buffer.As(&byteAccess);
+ RETURN_IF_FAILED("Could not cast buffer", return QByteArray())
+ char *data;
+ hr = byteAccess->Buffer(reinterpret_cast<byte **>(&data));
+ RETURN_IF_FAILED("Could not obtain buffer data", return QByteArray())
+ UINT32 size;
+ hr = buffer->get_Length(&size);
+ RETURN_IF_FAILED("Could not obtain buffer size", return QByteArray())
+ if (isWCharString) {
+ QString valueString = QString::fromUtf16(reinterpret_cast<ushort *>(data)).left(size / 2);
+ return valueString.toUtf8();
+ }
+ return QByteArray(data, qint32(size));
+}
+
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothutils_winrt_p.h b/src/bluetooth/qbluetoothutils_winrt_p.h
index c272bae1..93950fc9 100644
--- a/src/bluetooth/qbluetoothutils_winrt_p.h
+++ b/src/bluetooth/qbluetoothutils_winrt_p.h
@@ -53,10 +53,26 @@
#include <QtCore/QtGlobal>
+#include <wrl/client.h>
+
+namespace ABI {
+ namespace Windows {
+ namespace Storage {
+ namespace Streams {
+ struct IBuffer;
+ }
+ }
+ }
+}
+
QT_BEGIN_NAMESPACE
bool supportsNewLEApi();
+using NativeBuffer = ABI::Windows::Storage::Streams::IBuffer;
+QByteArray byteArrayFromBuffer(const Microsoft::WRL::ComPtr<NativeBuffer> &buffer,
+ bool isWCharString = false);
+
QT_END_NAMESPACE
#endif // QBLUETOOTHSOCKET_WINRT_P_H
diff --git a/src/bluetooth/qlowenergycharacteristic.h b/src/bluetooth/qlowenergycharacteristic.h
index bb6487c4..fe9b73fa 100644
--- a/src/bluetooth/qlowenergycharacteristic.h
+++ b/src/bluetooth/qlowenergycharacteristic.h
@@ -101,8 +101,8 @@ protected:
friend class QLowEnergyControllerPrivateBluez;
friend class QLowEnergyControllerPrivateBluezDBus;
friend class QLowEnergyControllerPrivateCommon;
- friend class QLowEnergyControllerPrivateOSX;
friend class QLowEnergyControllerPrivateWin32;
+ friend class QLowEnergyControllerPrivateDarwin;
friend class QLowEnergyControllerPrivateWinRT;
friend class QLowEnergyControllerPrivateWinRTNew;
QLowEnergyCharacteristicPrivate *data = nullptr;
diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp
index 444bfb38..bd263812 100644
--- a/src/bluetooth/qlowenergycontroller.cpp
+++ b/src/bluetooth/qlowenergycontroller.cpp
@@ -62,6 +62,8 @@
#endif
#elif defined(QT_WIN_BLUETOOTH)
#include "qlowenergycontroller_win_p.h"
+#elif defined(Q_OS_DARWIN)
+#include "qlowenergycontroller_darwin_p.h"
#else
#include "qlowenergycontroller_p.h"
#endif
@@ -159,6 +161,9 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT)
This value was introduced by Qt 5.7.
\value RemoteHostClosedError The remote device closed the connection.
This value was introduced by Qt 5.10.
+ \value AuthorizationError The local Bluetooth device closed the connection due to
+ insufficient authorization.
+ This value was introduced by Qt 5.14.
*/
/*!
@@ -326,6 +331,9 @@ static QLowEnergyControllerPrivate *privateController(QLowEnergyController::Role
#elif defined(QT_WIN_BLUETOOTH)
Q_UNUSED(role);
return new QLowEnergyControllerPrivateWin32();
+#elif defined(Q_OS_DARWIN)
+ Q_UNUSED(role)
+ return new QLowEnergyControllerPrivateDarwin();
#else
Q_UNUSED(role);
return new QLowEnergyControllerPrivateCommon();
@@ -349,6 +357,9 @@ QLowEnergyController::QLowEnergyController(
QObject *parent)
: QObject(parent)
{
+ // Note: a central created using this ctor is useless
+ // on Darwin - no way to use addresses when connecting.
+
d_ptr = privateController(CentralRole);
Q_D(QLowEnergyController);
@@ -378,11 +389,12 @@ QLowEnergyController::QLowEnergyController(
QObject *parent)
: QObject(parent)
{
- d_ptr = privateController(CentralRole);
+ d_ptr = privateController(CentralRole);
Q_D(QLowEnergyController);
d->q_ptr = this;
d->role = CentralRole;
+ d->deviceUuid = remoteDeviceInfo.deviceUuid();
d->remoteDevice = remoteDeviceInfo.address();
d->localAdapter = QBluetoothLocalDevice().address();
d->addressType = QLowEnergyController::PublicAddress;
@@ -411,6 +423,8 @@ QLowEnergyController::QLowEnergyController(
QObject *parent)
: QObject(parent)
{
+ // Note: a central create using this ctor is useless on
+ // Darwin (CoreBluetooth does not work with addresses).
d_ptr = privateController(CentralRole);
Q_D(QLowEnergyController);
@@ -437,6 +451,29 @@ QLowEnergyController *QLowEnergyController::createCentral(const QBluetoothDevice
return new QLowEnergyController(remoteDevice, parent);
}
+/*!
+ Returns a new instance of this class with \a parent.
+
+ The \a remoteDevice must contain the address of the remote Bluetooth Low
+ Energy device to which this object should attempt to connect later on.
+
+ The connection is established via \a localDevice. If \a localDevice is invalid,
+ the local default device is automatically selected. If \a localDevice specifies
+ a local device that is not a local Bluetooth adapter, \l error() is set to
+ \l InvalidBluetoothAdapterError once \l connectToDevice() is called.
+
+ Note that specifying the local device to be used for the connection is only
+ possible when using BlueZ. All other platforms do not support this feature.
+
+ \since 5.13
+ */
+QLowEnergyController *QLowEnergyController::createCentral(const QBluetoothAddress &remoteDevice,
+ const QBluetoothAddress &localDevice,
+ QObject *parent)
+{
+ return new QLowEnergyController(remoteDevice, localDevice, parent);
+}
+
/*!
Returns a new object of this class that is in the \l PeripheralRole and has the
@@ -516,7 +553,7 @@ QBluetoothAddress QLowEnergyController::remoteAddress() const
*/
QBluetoothUuid QLowEnergyController::remoteDeviceUuid() const
{
- return QBluetoothUuid();
+ return d_ptr->deviceUuid;
}
/*!
diff --git a/src/bluetooth/qlowenergycontroller.h b/src/bluetooth/qlowenergycontroller.h
index 9fe46fe5..37e7b82d 100644
--- a/src/bluetooth/qlowenergycontroller.h
+++ b/src/bluetooth/qlowenergycontroller.h
@@ -66,7 +66,8 @@ public:
InvalidBluetoothAdapterError,
ConnectionError,
AdvertisingError,
- RemoteHostClosedError
+ RemoteHostClosedError,
+ AuthorizationError
};
Q_ENUM(Error)
@@ -93,13 +94,16 @@ public:
explicit QLowEnergyController(const QBluetoothAddress &remoteDevice,
QObject *parent = nullptr); // TODO Qt 6 remove ctor
explicit QLowEnergyController(const QBluetoothDeviceInfo &remoteDevice,
- QObject *parent = nullptr);
+ QObject *parent = nullptr); // TODO Qt 6 make private
explicit QLowEnergyController(const QBluetoothAddress &remoteDevice,
const QBluetoothAddress &localDevice,
QObject *parent = nullptr); // TODO Qt 6 remove ctor
static QLowEnergyController *createCentral(const QBluetoothDeviceInfo &remoteDevice,
QObject *parent = nullptr);
+ static QLowEnergyController *createCentral(const QBluetoothAddress &remoteDevice,
+ const QBluetoothAddress &localDevice,
+ QObject *parent = nullptr);
static QLowEnergyController *createPeripheral(QObject *parent = nullptr);
// TODO: Allow to set connection timeout (disconnect when no data has been exchanged for n seconds).
diff --git a/src/bluetooth/qlowenergycontroller_android_p.h b/src/bluetooth/qlowenergycontroller_android_p.h
index 3f97e363..f05c63ca 100644
--- a/src/bluetooth/qlowenergycontroller_android_p.h
+++ b/src/bluetooth/qlowenergycontroller_android_p.h
@@ -60,15 +60,8 @@
#include "qlowenergycontroller.h"
#include "qlowenergycontrollerbase_p.h"
-#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
-#include <QtBluetooth/QBluetoothSocket>
-#elif defined(QT_ANDROID_BLUETOOTH)
#include <QtAndroidExtras/QAndroidJniObject>
#include "android/lowenergynotificationhub_p.h"
-#elif defined(QT_WINRT_BLUETOOTH)
-#include <wrl.h>
-#include <windows.devices.bluetooth.h>
-#endif
#include <functional>
@@ -77,16 +70,7 @@ QT_BEGIN_NAMESPACE
class QLowEnergyServiceData;
class QTimer;
-#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
-class HciManager;
-class LeCmacCalculator;
-class QSocketNotifier;
-class RemoteDeviceManager;
-#elif defined(QT_ANDROID_BLUETOOTH)
class LowEnergyNotificationHub;
-#elif defined(QT_WINRT_BLUETOOTH)
-class QWinRTLowEnergyServiceHandler;
-#endif
extern void registerQLowEnergyControllerMetaType();
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp
index 65f4e0c2..dfa21004 100644
--- a/src/bluetooth/qlowenergycontroller_bluez.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluez.cpp
@@ -3115,6 +3115,14 @@ void QLowEnergyControllerPrivateBluez::handleConnectionRequest()
if (connectionHandle == 0)
qCWarning(QT_BT_BLUEZ) << "Received client connection, but no connection complete event";
+ if (l2cpSocket) {
+ disconnect(l2cpSocket);
+ if (l2cpSocket->isOpen())
+ l2cpSocket->close();
+
+ l2cpSocket->deleteLater();
+ l2cpSocket = nullptr;
+ }
closeServerSocket();
QBluetoothSocketPrivateBluez *rawSocketPrivate = new QBluetoothSocketPrivateBluez();
diff --git a/src/bluetooth/qlowenergycontroller_bluezdbus.cpp b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
index 441eca6b..4e5f3430 100644
--- a/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
@@ -268,9 +268,13 @@ void QLowEnergyControllerPrivateBluezDBus::connectToDeviceHelper()
const QVariantMap &ifaceValues = jt.value();
if (iface == QStringLiteral("org.bluez.Device1")) {
- if (remoteDevice.toString() == ifaceValues.value(QStringLiteral("Address")).toString()) {
- devicePath = it.key().path();
- break;
+ if (remoteDevice.toString() == ifaceValues.value(QStringLiteral("Address")).toString())
+ {
+ const QVariant adapterForCurrentDevice = ifaceValues.value(QStringLiteral("Adapter"));
+ if (qvariant_cast<QDBusObjectPath>(adapterForCurrentDevice).path() == hostAdapterPath) {
+ devicePath = it.key().path();
+ break;
+ }
}
}
}
@@ -350,6 +354,9 @@ void QLowEnergyControllerPrivateBluezDBus::connectToDevice()
void QLowEnergyControllerPrivateBluezDBus::disconnectFromDevice()
{
+ if (!device)
+ return;
+
setState(QLowEnergyController::ClosingState);
QDBusPendingReply<> reply = device->Disconnect();
diff --git a/src/bluetooth/qlowenergycontroller_osx.mm b/src/bluetooth/qlowenergycontroller_darwin.mm
index 8cef621c..253956e2 100644
--- a/src/bluetooth/qlowenergycontroller_osx.mm
+++ b/src/bluetooth/qlowenergycontroller_darwin.mm
@@ -38,13 +38,17 @@
**
****************************************************************************/
-#include "osx/osxbtnotifier_p.h"
#include "osx/osxbtutility_p.h"
#include "osx/uistrings_p.h"
+#ifndef Q_OS_TVOS
+#include "osx/osxbtperipheralmanager_p.h"
+#endif // Q_OS_TVOS
+#include "qlowenergycontroller_darwin_p.h"
#include "qlowenergyserviceprivate_p.h"
-#include "qlowenergycontroller_osx_p.h"
+#include "osx/osxbtcentralmanager_p.h"
+
#include "qlowenergyservicedata.h"
#include "qbluetoothlocaldevice.h"
#include "qbluetoothdeviceinfo.h"
@@ -58,30 +62,14 @@
#include <QtCore/qstring.h>
#include <QtCore/qlist.h>
-#define OSX_D_PTR QLowEnergyControllerPrivateOSX *osx_d_ptr = static_cast<QLowEnergyControllerPrivateOSX *>(d_ptr)
-
QT_BEGIN_NAMESPACE
namespace {
-static void registerQLowEnergyControllerMetaType()
-{
- static bool initDone = false;
- if (!initDone) {
- qRegisterMetaType<QLowEnergyController::ControllerState>();
- qRegisterMetaType<QLowEnergyController::Error>();
- qRegisterMetaType<QLowEnergyHandle>("QLowEnergyHandle");
- qRegisterMetaType<QSharedPointer<QLowEnergyServicePrivate> >();
- qRegisterMetaType<QLowEnergyCharacteristic>();
- qRegisterMetaType<QLowEnergyDescriptor>();
- initDone = true;
- }
-}
-
typedef QSharedPointer<QLowEnergyServicePrivate> ServicePrivate;
// Convenience function, can return a smart pointer that 'isNull'.
-ServicePrivate qt_createLEService(QLowEnergyControllerPrivateOSX *controller, CBService *cbService, bool included)
+ServicePrivate qt_createLEService(QLowEnergyControllerPrivateDarwin *controller, CBService *cbService, bool included)
{
Q_ASSERT_X(controller, Q_FUNC_INFO, "invalid controller (null)");
Q_ASSERT_X(cbService, Q_FUNC_INFO, "invalid service (nil)");
@@ -131,110 +119,276 @@ UUIDList qt_servicesUuids(NSArray *services)
return uuids;
}
-}
+} // unnamed namespace
-QLowEnergyControllerPrivateOSX::QLowEnergyControllerPrivateOSX(QLowEnergyController::Role r,
- QLowEnergyController *q,
- const QBluetoothDeviceInfo &deviceInfo)
- : q_ptr(q),
- deviceUuid(deviceInfo.deviceUuid()),
- deviceName(deviceInfo.name()),
- lastError(QLowEnergyController::NoError),
- controllerState(QLowEnergyController::UnconnectedState),
- addressType(QLowEnergyController::PublicAddress)
+#ifndef Q_OS_TVOS
+using ObjCPeripheralManager = QT_MANGLE_NAMESPACE(OSXBTPeripheralManager);
+#endif // Q_OS_TVOS
+
+using ObjCCentralManager = QT_MANGLE_NAMESPACE(OSXBTCentralManager);
+
+QLowEnergyControllerPrivateDarwin::QLowEnergyControllerPrivateDarwin()
{
+ void registerQLowEnergyControllerMetaType();
registerQLowEnergyControllerMetaType();
+ qRegisterMetaType<QLowEnergyHandle>("QLowEnergyHandle");
+ qRegisterMetaType<QSharedPointer<QLowEnergyServicePrivate>>();
+}
- Q_ASSERT_X(q, Q_FUNC_INFO, "invalid q_ptr (null)");
+QLowEnergyControllerPrivateDarwin::~QLowEnergyControllerPrivateDarwin()
+{
+ if (const auto leQueue = OSXBluetooth::qt_LE_queue()) {
+ if (role == QLowEnergyController::CentralRole) {
+ const auto manager = centralManager.getAs<ObjCCentralManager>();
+ dispatch_sync(leQueue, ^{
+ [manager detach];
+ });
+ } else {
+#ifndef Q_OS_TVOS
+ const auto manager = peripheralManager.getAs<ObjCPeripheralManager>();
+ dispatch_sync(leQueue, ^{
+ [manager detach];
+ });
+#endif
+ }
+ }
+}
- using OSXBluetooth::LECBManagerNotifier;
+bool QLowEnergyControllerPrivateDarwin::isValid() const
+{
+#ifdef Q_OS_TVOS
+ return centralManager;
+#else
+ return centralManager || peripheralManager;
+#endif
+}
- role = r;
+void QLowEnergyControllerPrivateDarwin::init()
+{
+ using OSXBluetooth::LECBManagerNotifier;
QScopedPointer<LECBManagerNotifier> notifier(new LECBManagerNotifier);
if (role == QLowEnergyController::PeripheralRole) {
#ifndef Q_OS_TVOS
- peripheralManager.reset([[ObjCPeripheralManager alloc] initWith:notifier.data()]);
+ peripheralManager.reset([[ObjCPeripheralManager alloc] initWith:notifier.data()],
+ DarwinBluetooth::RetainPolicy::noInitialRetain);
if (!peripheralManager) {
- qCWarning(QT_BT_OSX) << "failed to initialize peripheral manager";
+ qCWarning(QT_BT_OSX) << "failed to create a peripheral manager";
return;
}
#else
- qCWarning(QT_BT_OSX) << "peripheral role is not supported on your platform";
+ qCWarning(QT_BT_OSX) << "the peripheral role is not supported on your platform";
return;
-#endif
+#endif // Q_OS_TVOS
} else {
- centralManager.reset([[ObjCCentralManager alloc] initWith:notifier.data()]);
+ centralManager.reset([[ObjCCentralManager alloc] initWith:notifier.data()],
+ DarwinBluetooth::RetainPolicy::noInitialRetain);
if (!centralManager) {
- qCWarning(QT_BT_OSX) << "failed to initialize central manager";
+ qCWarning(QT_BT_OSX) << "failed to initialize a central manager";
return;
}
}
- if (!connectSlots(notifier.data())) {
+ if (!connectSlots(notifier.data()))
qCWarning(QT_BT_OSX) << "failed to connect to notifier's signal(s)";
- }
+
// Ownership was taken by central manager.
notifier.take();
}
-QLowEnergyControllerPrivateOSX::~QLowEnergyControllerPrivateOSX()
+void QLowEnergyControllerPrivateDarwin::connectToDevice()
{
- if (const auto leQueue = OSXBluetooth::qt_LE_queue()) {
- if (role == QLowEnergyController::CentralRole) {
- const auto manager = centralManager.data();
- dispatch_sync(leQueue, ^{
- [manager detach];
+ Q_ASSERT_X(state == QLowEnergyController::UnconnectedState,
+ Q_FUNC_INFO, "invalid state");
+
+ if (!isValid()) {
+ // init() had failed for was never called.
+ return _q_CBManagerError(QLowEnergyController::UnknownError);
+ }
+
+ if (deviceUuid.isNull()) {
+ // Wrong constructor was used or invalid UUID was provided.
+ return _q_CBManagerError(QLowEnergyController::UnknownRemoteDeviceError);
+ }
+
+ // The logic enforcing the role is in the public class.
+ Q_ASSERT_X(role != QLowEnergyController::PeripheralRole,
+ Q_FUNC_INFO, "invalid role (peripheral)");
+
+ dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
+ if (!leQueue) {
+ qCWarning(QT_BT_OSX) << "no LE queue found";
+ setErrorDescription(QLowEnergyController::UnknownError);
+ return;
+ }
+
+ setErrorDescription(QLowEnergyController::NoError);
+ setState(QLowEnergyController::ConnectingState);
+
+ const QBluetoothUuid deviceUuidCopy(deviceUuid);
+ ObjCCentralManager *manager = centralManager.getAs<ObjCCentralManager>();
+ dispatch_async(leQueue, ^{
+ [manager connectToDevice:deviceUuidCopy];
+ });
+}
+
+void QLowEnergyControllerPrivateDarwin::disconnectFromDevice()
+{
+ if (role == QLowEnergyController::PeripheralRole) {
+ // CoreBluetooth API intentionally does not provide any way of closing
+ // a connection. All we can do here is to stop the advertisement.
+ stopAdvertising();
+ return;
+ }
+
+ if (isValid()) {
+ const auto oldState = state;
+
+ if (dispatch_queue_t leQueue = OSXBluetooth::qt_LE_queue()) {
+ setState(QLowEnergyController::ClosingState);
+ invalidateServices();
+
+ auto manager = centralManager.getAs<ObjCCentralManager>();
+ dispatch_async(leQueue, ^{
+ [manager disconnectFromDevice];
});
+
+ if (oldState == QLowEnergyController::ConnectingState) {
+ // With a pending connect attempt there is no
+ // guarantee we'll ever have didDisconnect callback,
+ // set the state here and now to make sure we still
+ // can connect.
+ setState(QLowEnergyController::UnconnectedState);
+ }
} else {
-#ifndef Q_OS_TVOS
- const auto manager = peripheralManager.data();
- dispatch_sync(leQueue, ^{
- [manager detach];
- });
-#endif
+ qCCritical(QT_BT_OSX) << "qt LE queue is nil, "
+ "can not dispatch 'disconnect'";
}
}
}
-bool QLowEnergyControllerPrivateOSX::isValid() const
+void QLowEnergyControllerPrivateDarwin::discoverServices()
+{
+ Q_ASSERT_X(state != QLowEnergyController::UnconnectedState,
+ Q_FUNC_INFO, "not connected to peripheral");
+ Q_ASSERT_X(role != QLowEnergyController::PeripheralRole,
+ Q_FUNC_INFO, "invalid role (peripheral)");
+
+ dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
+ Q_ASSERT_X(leQueue, Q_FUNC_INFO, "LE queue not found");
+
+ setState(QLowEnergyController::DiscoveringState);
+
+ ObjCCentralManager *manager = centralManager.getAs<ObjCCentralManager>();
+ dispatch_async(leQueue, ^{
+ [manager discoverServices];
+ });
+}
+
+void QLowEnergyControllerPrivateDarwin::discoverServiceDetails(const QBluetoothUuid &serviceUuid)
{
+ if (state != QLowEnergyController::DiscoveredState) {
+ qCWarning(QT_BT_OSX) << "can not discover service details in the current state, "
+ "QLowEnergyController::DiscoveredState is expected";
+ return;
+ }
+
+ if (!serviceList.contains(serviceUuid)) {
+ qCWarning(QT_BT_OSX) << "unknown service: " << serviceUuid;
+ return;
+ }
+
+ dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
+ Q_ASSERT(leQueue);
+
+ ServicePrivate qtService(serviceList.value(serviceUuid));
+ qtService->setState(QLowEnergyService::DiscoveringServices);
+ // Copy objects ...
+ ObjCCentralManager *manager = centralManager.getAs<ObjCCentralManager>();
+ const QBluetoothUuid serviceUuidCopy(serviceUuid);
+ dispatch_async(leQueue, ^{
+ [manager discoverServiceDetails:serviceUuidCopy];
+ });
+}
+
+void QLowEnergyControllerPrivateDarwin::requestConnectionUpdate(const QLowEnergyConnectionParameters &params)
+{
+ Q_UNUSED(params);
+ // TODO: implement this, if possible.
+ qCWarning(QT_BT_OSX) << "Connection update not implemented on your platform";
+}
+
+void QLowEnergyControllerPrivateDarwin::addToGenericAttributeList(const QLowEnergyServiceData &service,
+ QLowEnergyHandle startHandle)
+{
+ Q_UNUSED(service);
+ Q_UNUSED(startHandle);
+ // TODO: check why I don't need this (apparently it is used in addServiceHelper
+ // of the base class).
+}
+
+QLowEnergyService * QLowEnergyControllerPrivateDarwin::addServiceHelper(const QLowEnergyServiceData &service)
+{
+ // Three checks below should be removed, they are done in the q_ptr's class.
#ifdef Q_OS_TVOS
- return centralManager;
+ Q_UNUSED(service);
+ qCDebug(QT_BT_OSX, "peripheral role is not supported on tvOS");
#else
- return centralManager || peripheralManager;
-#endif
+ if (role != QLowEnergyController::PeripheralRole) {
+ qCWarning(QT_BT_OSX) << "not in peripheral role";
+ return nullptr;
+ }
+
+ if (state != QLowEnergyController::UnconnectedState) {
+ qCWarning(QT_BT_OSX) << "invalid state";
+ return nullptr;
+ }
+
+ if (!service.isValid()) {
+ qCWarning(QT_BT_OSX) << "invalid service";
+ return nullptr;
+ }
+
+ for (auto includedService : service.includedServices())
+ includedService->d_ptr->type |= QLowEnergyService::IncludedService;
+
+ const auto manager = peripheralManager.getAs<ObjCPeripheralManager>();
+ Q_ASSERT(manager);
+ if (const auto servicePrivate = [manager addService:service]) {
+ servicePrivate->setController(this);
+ servicePrivate->state = QLowEnergyService::LocalService;
+ localServices.insert(servicePrivate->uuid, servicePrivate);
+ return new QLowEnergyService(servicePrivate);
+ }
+#endif // Q_OS_TVOS
+ return nullptr;
}
-void QLowEnergyControllerPrivateOSX::_q_connected()
+void QLowEnergyControllerPrivateDarwin::_q_connected()
{
- controllerState = QLowEnergyController::ConnectedState;
-
- emit q_ptr->stateChanged(QLowEnergyController::ConnectedState);
+ setState(QLowEnergyController::ConnectedState);
emit q_ptr->connected();
}
-void QLowEnergyControllerPrivateOSX::_q_disconnected()
+void QLowEnergyControllerPrivateDarwin::_q_disconnected()
{
- controllerState = QLowEnergyController::UnconnectedState;
-
if (role == QLowEnergyController::CentralRole)
invalidateServices();
- emit q_ptr->stateChanged(QLowEnergyController::UnconnectedState);
+ setState(QLowEnergyController::UnconnectedState);
emit q_ptr->disconnected();
}
-void QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished()
+void QLowEnergyControllerPrivateDarwin::_q_serviceDiscoveryFinished()
{
- Q_ASSERT_X(controllerState == QLowEnergyController::DiscoveringState,
+ Q_ASSERT_X(state == QLowEnergyController::DiscoveringState,
Q_FUNC_INFO, "invalid state");
using namespace OSXBluetooth;
QT_BT_MAC_AUTORELEASEPOOL;
- NSArray *const services = [centralManager.data() peripheral].services;
+ NSArray *const services = [centralManager.getAs<ObjCCentralManager>() peripheral].services;
// Now we have to traverse the discovered services tree.
// Essentially it's an iterative version of more complicated code from the
// OSXBTCentralManager's code.
@@ -249,13 +403,13 @@ void QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished()
const ServicePrivate newService(qt_createLEService(this, cbService, false));
if (!newService.data())
continue;
- if (discoveredServices.contains(newService->uuid)) {
+ if (serviceList.contains(newService->uuid)) {
// It's a bit stupid we first created it ...
qCDebug(QT_BT_OSX) << "discovered service with a duplicated UUID"
<< newService->uuid;
continue;
}
- discoveredServices.insert(newService->uuid, newService);
+ serviceList.insert(newService->uuid, newService);
discoveredCBServices.insert(newService->uuid, cbService);
}
@@ -273,8 +427,8 @@ void QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished()
}
const QBluetoothUuid uuid(qt_uuid(s.UUID));
- if (discoveredServices.contains(uuid) && discoveredCBServices.value(uuid) == s) {
- ServicePrivate qtService(discoveredServices.value(uuid));
+ if (serviceList.contains(uuid) && discoveredCBServices.value(uuid) == s) {
+ ServicePrivate qtService(serviceList.value(uuid));
// Add included UUIDs:
qtService->includedServices.append(qt_servicesUuids(s.includedServices));
}// Else - we ignored this CBService object.
@@ -286,15 +440,15 @@ void QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished()
for (NSUInteger i = 0, e = [toVisitNext count]; i < e; ++i) {
CBService *const s = [toVisitNext objectAtIndex:i];
const QBluetoothUuid uuid(qt_uuid(s.UUID));
- if (discoveredServices.contains(uuid)) {
+ if (serviceList.contains(uuid)) {
if (discoveredCBServices.value(uuid) == s) {
- ServicePrivate qtService(discoveredServices.value(uuid));
+ ServicePrivate qtService(serviceList.value(uuid));
qtService->type |= QLowEnergyService::IncludedService;
} // Else this is the duplicate we ignored already.
} else {
// Oh, we do not even have it yet???
ServicePrivate newService(qt_createLEService(this, s, true));
- discoveredServices.insert(newService->uuid, newService);
+ serviceList.insert(newService->uuid, newService);
discoveredCBServices.insert(newService->uuid, s);
}
}
@@ -306,31 +460,26 @@ void QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished()
qCDebug(QT_BT_OSX) << "no services found";
}
- for (ServiceMap::const_iterator it = discoveredServices.constBegin(); it != discoveredServices.constEnd(); ++it) {
- const QBluetoothUuid &uuid = it.key();
- QMetaObject::invokeMethod(q_ptr, "serviceDiscovered", Qt::QueuedConnection,
- Q_ARG(QBluetoothUuid, uuid));
- }
+ for (ServiceMap::const_iterator it = serviceList.constBegin(); it != serviceList.constEnd(); ++it)
+ emit q_ptr->serviceDiscovered(it.key());
- controllerState = QLowEnergyController::DiscoveredState;
- QMetaObject::invokeMethod(q_ptr, "stateChanged", Qt::QueuedConnection,
- Q_ARG(QLowEnergyController::ControllerState, controllerState));
- QMetaObject::invokeMethod(q_ptr, "discoveryFinished", Qt::QueuedConnection);
+ setState(QLowEnergyController::DiscoveredState);
+ emit q_ptr->discoveryFinished();
}
-void QLowEnergyControllerPrivateOSX::_q_serviceDetailsDiscoveryFinished(QSharedPointer<QLowEnergyServicePrivate> service)
+void QLowEnergyControllerPrivateDarwin::_q_serviceDetailsDiscoveryFinished(QSharedPointer<QLowEnergyServicePrivate> service)
{
QT_BT_MAC_AUTORELEASEPOOL;
Q_ASSERT(service);
- if (!discoveredServices.contains(service->uuid)) {
+ if (!serviceList.contains(service->uuid)) {
qCDebug(QT_BT_OSX) << "unknown service uuid:"
<< service->uuid;
return;
}
- ServicePrivate qtService(discoveredServices.value(service->uuid));
+ ServicePrivate qtService(serviceList.value(service->uuid));
// Assert on handles?
qtService->startHandle = service->startHandle;
qtService->endHandle = service->endHandle;
@@ -339,8 +488,23 @@ void QLowEnergyControllerPrivateOSX::_q_serviceDetailsDiscoveryFinished(QSharedP
qtService->setState(QLowEnergyService::ServiceDiscovered);
}
-void QLowEnergyControllerPrivateOSX::_q_characteristicRead(QLowEnergyHandle charHandle,
- const QByteArray &value)
+void QLowEnergyControllerPrivateDarwin::_q_servicesWereModified()
+{
+ if (!(state == QLowEnergyController::DiscoveringState
+ || state == QLowEnergyController::DiscoveredState)) {
+ qCWarning(QT_BT_OSX) << "services were modified while controller is not in Discovered/Discovering state";
+ return;
+ }
+
+ if (state == QLowEnergyController::DiscoveredState)
+ invalidateServices();
+
+ setState(QLowEnergyController::ConnectedState);
+ q_ptr->discoverServices();
+}
+
+void QLowEnergyControllerPrivateDarwin::_q_characteristicRead(QLowEnergyHandle charHandle,
+ const QByteArray &value)
{
Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle(0)");
@@ -360,8 +524,8 @@ void QLowEnergyControllerPrivateOSX::_q_characteristicRead(QLowEnergyHandle char
emit service->characteristicRead(characteristic, value);
}
-void QLowEnergyControllerPrivateOSX::_q_characteristicWritten(QLowEnergyHandle charHandle,
- const QByteArray &value)
+void QLowEnergyControllerPrivateDarwin::_q_characteristicWritten(QLowEnergyHandle charHandle,
+ const QByteArray &value)
{
Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle(0)");
@@ -384,8 +548,8 @@ void QLowEnergyControllerPrivateOSX::_q_characteristicWritten(QLowEnergyHandle c
emit service->characteristicWritten(characteristic, value);
}
-void QLowEnergyControllerPrivateOSX::_q_characteristicUpdated(QLowEnergyHandle charHandle,
- const QByteArray &value)
+void QLowEnergyControllerPrivateDarwin::_q_characteristicUpdated(QLowEnergyHandle charHandle,
+ const QByteArray &value)
{
// TODO: write/update notifications are quite similar (except asserts/warnings messages
// and different signals emitted). Merge them into one function?
@@ -413,8 +577,8 @@ void QLowEnergyControllerPrivateOSX::_q_characteristicUpdated(QLowEnergyHandle c
emit service->characteristicChanged(characteristic, value);
}
-void QLowEnergyControllerPrivateOSX::_q_descriptorRead(QLowEnergyHandle dHandle,
- const QByteArray &value)
+void QLowEnergyControllerPrivateDarwin::_q_descriptorRead(QLowEnergyHandle dHandle,
+ const QByteArray &value)
{
Q_ASSERT_X(dHandle, Q_FUNC_INFO, "invalid descriptor handle (0)");
@@ -429,8 +593,8 @@ void QLowEnergyControllerPrivateOSX::_q_descriptorRead(QLowEnergyHandle dHandle,
emit service->descriptorRead(qtDescriptor, value);
}
-void QLowEnergyControllerPrivateOSX::_q_descriptorWritten(QLowEnergyHandle dHandle,
- const QByteArray &value)
+void QLowEnergyControllerPrivateDarwin::_q_descriptorWritten(QLowEnergyHandle dHandle,
+ const QByteArray &value)
{
Q_ASSERT_X(dHandle, Q_FUNC_INFO, "invalid descriptor handle (0)");
@@ -446,8 +610,8 @@ void QLowEnergyControllerPrivateOSX::_q_descriptorWritten(QLowEnergyHandle dHand
emit service->descriptorWritten(qtDescriptor, value);
}
-void QLowEnergyControllerPrivateOSX::_q_notificationEnabled(QLowEnergyHandle charHandle,
- bool enabled)
+void QLowEnergyControllerPrivateDarwin::_q_notificationEnabled(QLowEnergyHandle charHandle,
+ bool enabled)
{
// CoreBluetooth in peripheral role does not allow mutable descriptors,
// in central we can only call setNotification:enabled/disabled.
@@ -489,7 +653,7 @@ void QLowEnergyControllerPrivateOSX::_q_notificationEnabled(QLowEnergyHandle cha
}
}
-void QLowEnergyControllerPrivateOSX::_q_LEnotSupported()
+void QLowEnergyControllerPrivateDarwin::_q_LEnotSupported()
{
// Report as an error. But this should not be possible
// actually: before connecting to any device, we have
@@ -497,32 +661,30 @@ void QLowEnergyControllerPrivateOSX::_q_LEnotSupported()
// be supported.
}
-void QLowEnergyControllerPrivateOSX::_q_CBManagerError(QLowEnergyController::Error errorCode)
+void QLowEnergyControllerPrivateDarwin::_q_CBManagerError(QLowEnergyController::Error errorCode)
{
- // Errors reported during connect and general errors.
-
- setErrorDescription(errorCode);
- emit q_ptr->error(lastError);
-
- if (controllerState == QLowEnergyController::ConnectingState) {
- controllerState = QLowEnergyController::UnconnectedState;
- emit q_ptr->stateChanged(controllerState);
- } else if (controllerState == QLowEnergyController::DiscoveringState) {
- controllerState = QLowEnergyController::ConnectedState;
- emit q_ptr->stateChanged(controllerState);
- } // In any other case we stay in Discovered, it's
- // a service/characteristic - related error.
+ // This function handles errors reported while connecting to a remote device
+ // and also other errors in general.
+ setError(errorCode);
+
+ if (state == QLowEnergyController::ConnectingState)
+ setState(QLowEnergyController::UnconnectedState);
+ else if (state == QLowEnergyController::DiscoveringState)
+ setState(QLowEnergyController::ConnectedState);
+
+ // In any other case we stay in Discovered, it's
+ // a service/characteristic - related error.
}
-void QLowEnergyControllerPrivateOSX::_q_CBManagerError(const QBluetoothUuid &serviceUuid,
- QLowEnergyController::Error errorCode)
+void QLowEnergyControllerPrivateDarwin::_q_CBManagerError(const QBluetoothUuid &serviceUuid,
+ QLowEnergyController::Error errorCode)
{
// Errors reported while discovering service details etc.
Q_UNUSED(errorCode) // TODO: setError?
// We failed to discover any characteristics/descriptors.
- if (discoveredServices.contains(serviceUuid)) {
- ServicePrivate qtService(discoveredServices.value(serviceUuid));
+ if (serviceList.contains(serviceUuid)) {
+ ServicePrivate qtService(serviceList.value(serviceUuid));
qtService->setState(QLowEnergyService::InvalidService);
} else {
qCDebug(QT_BT_OSX) << "error reported for unknown service"
@@ -530,109 +692,24 @@ void QLowEnergyControllerPrivateOSX::_q_CBManagerError(const QBluetoothUuid &ser
}
}
-void QLowEnergyControllerPrivateOSX::_q_CBManagerError(const QBluetoothUuid &serviceUuid,
- QLowEnergyService::ServiceError errorCode)
+void QLowEnergyControllerPrivateDarwin::_q_CBManagerError(const QBluetoothUuid &serviceUuid,
+ QLowEnergyService::ServiceError errorCode)
{
- if (!discoveredServices.contains(serviceUuid)) {
+ if (!serviceList.contains(serviceUuid)) {
qCDebug(QT_BT_OSX) << "unknown service uuid:"
<< serviceUuid;
return;
}
- ServicePrivate service(discoveredServices.value(serviceUuid));
+ ServicePrivate service(serviceList.value(serviceUuid));
service->setError(errorCode);
}
-void QLowEnergyControllerPrivateOSX::connectToDevice()
-{
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid private controller");
- Q_ASSERT_X(controllerState == QLowEnergyController::UnconnectedState,
- Q_FUNC_INFO, "invalid state");
- Q_ASSERT_X(!deviceUuid.isNull(), Q_FUNC_INFO,
- "invalid private controller (no device uuid)");
- Q_ASSERT_X(role != QLowEnergyController::PeripheralRole,
- Q_FUNC_INFO, "invalid role (peripheral)");
-
- dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- setErrorDescription(QLowEnergyController::UnknownError);
- return;
- }
-
- setErrorDescription(QLowEnergyController::NoError);
- controllerState = QLowEnergyController::ConnectingState;
-
- const QBluetoothUuid deviceUuidCopy(deviceUuid);
- ObjCCentralManager *manager = centralManager.data();
- dispatch_async(leQueue, ^{
- [manager connectToDevice:deviceUuidCopy];
- });
-}
-
-void QLowEnergyControllerPrivateOSX::discoverServices()
-{
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid private controller");
- Q_ASSERT_X(controllerState != QLowEnergyController::UnconnectedState,
- Q_FUNC_INFO, "not connected to peripheral");
- Q_ASSERT_X(role != QLowEnergyController::PeripheralRole,
- Q_FUNC_INFO, "invalid role (peripheral)");
-
- dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- setErrorDescription(QLowEnergyController::UnknownError);
- return;
- }
-
- controllerState = QLowEnergyController::DiscoveringState;
- emit q_ptr->stateChanged(QLowEnergyController::DiscoveringState);
-
- ObjCCentralManager *manager = centralManager.data();
- dispatch_async(leQueue, ^{
- [manager discoverServices];
- });
-}
-
-void QLowEnergyControllerPrivateOSX::discoverServiceDetails(const QBluetoothUuid &serviceUuid)
-{
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid private controller");
-
- if (controllerState != QLowEnergyController::DiscoveredState) {
- // This will also exclude peripheral role, since controller
- // can never be in discovered state ...
- qCWarning(QT_BT_OSX) << "can not discover service details in the current state, "
- "QLowEnergyController::DiscoveredState is expected";
- return;
- }
-
- if (!discoveredServices.contains(serviceUuid)) {
- qCWarning(QT_BT_OSX) << "unknown service: " << serviceUuid;
- return;
- }
-
- dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- return;
- }
-
- ServicePrivate qtService(discoveredServices.value(serviceUuid));
- qtService->setState(QLowEnergyService::DiscoveringServices);
- // Copy objects ...
- ObjCCentralManager *manager = centralManager.data();
- const QBluetoothUuid serviceUuidCopy(serviceUuid);
- dispatch_async(leQueue, ^{
- [manager discoverServiceDetails:serviceUuidCopy];
- });
-}
-
-void QLowEnergyControllerPrivateOSX::setNotifyValue(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle charHandle,
- const QByteArray &newValue)
+void QLowEnergyControllerPrivateDarwin::setNotifyValue(QSharedPointer<QLowEnergyServicePrivate> service,
+ QLowEnergyHandle charHandle,
+ const QByteArray &newValue)
{
Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)");
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid controller");
if (role == QLowEnergyController::PeripheralRole) {
qCWarning(QT_BT_OSX) << "invalid role (peripheral)";
@@ -651,7 +728,7 @@ void QLowEnergyControllerPrivateOSX::setNotifyValue(QSharedPointer<QLowEnergySer
return;
}
- if (!discoveredServices.contains(service->uuid)) {
+ if (!serviceList.contains(service->uuid)) {
qCWarning(QT_BT_OSX) << "no service with uuid:" << service->uuid << "found";
return;
}
@@ -663,11 +740,9 @@ void QLowEnergyControllerPrivateOSX::setNotifyValue(QSharedPointer<QLowEnergySer
}
dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- return;
- }
- ObjCCentralManager *manager = centralManager.data();
+ Q_ASSERT_X(leQueue, Q_FUNC_INFO, "no LE queue found");
+
+ ObjCCentralManager *manager = centralManager.getAs<ObjCCentralManager>();
const QBluetoothUuid serviceUuid(service->uuid);
const QByteArray newValueCopy(newValue);
dispatch_async(leQueue, ^{
@@ -677,18 +752,17 @@ void QLowEnergyControllerPrivateOSX::setNotifyValue(QSharedPointer<QLowEnergySer
});
}
-void QLowEnergyControllerPrivateOSX::readCharacteristic(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle charHandle)
+void QLowEnergyControllerPrivateDarwin::readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle)
{
Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)");
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid controller");
if (role == QLowEnergyController::PeripheralRole) {
qCWarning(QT_BT_OSX) << "invalid role (peripheral)";
return;
}
- if (!discoveredServices.contains(service->uuid)) {
+ if (!serviceList.contains(service->uuid)) {
qCWarning(QT_BT_OSX) << "no service with uuid:"
<< service->uuid << "found";
return;
@@ -701,29 +775,26 @@ void QLowEnergyControllerPrivateOSX::readCharacteristic(QSharedPointer<QLowEnerg
}
dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- return;
- }
+ Q_ASSERT_X(leQueue, Q_FUNC_INFO, "no LE queue found");
+
// Attention! We have to copy UUID.
- ObjCCentralManager *manager = centralManager.data();
+ ObjCCentralManager *manager = centralManager.getAs<ObjCCentralManager>();
const QBluetoothUuid serviceUuid(service->uuid);
dispatch_async(leQueue, ^{
[manager readCharacteristic:charHandle onService:serviceUuid];
});
}
-void QLowEnergyControllerPrivateOSX::writeCharacteristic(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle charHandle, const QByteArray &newValue,
- QLowEnergyService::WriteMode mode)
+void QLowEnergyControllerPrivateDarwin::writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle, const QByteArray &newValue,
+ QLowEnergyService::WriteMode mode)
{
Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)");
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid controller");
// We can work only with services found on a given peripheral
// (== created by the given LE controller).
- if (!discoveredServices.contains(service->uuid)) {
+ if (!serviceList.contains(service->uuid) && !localServices.contains(service->uuid)) {
qCWarning(QT_BT_OSX) << "no service with uuid:"
<< service->uuid << " found";
return;
@@ -736,15 +807,12 @@ void QLowEnergyControllerPrivateOSX::writeCharacteristic(QSharedPointer<QLowEner
}
dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- return;
- }
+ Q_ASSERT_X(leQueue, Q_FUNC_INFO, "no LE queue found");
// Attention! We have to copy objects!
const QByteArray newValueCopy(newValue);
if (role == QLowEnergyController::CentralRole) {
const QBluetoothUuid serviceUuid(service->uuid);
- const auto manager = centralManager.data();
+ const auto manager = centralManager.getAs<ObjCCentralManager>();
dispatch_async(leQueue, ^{
[manager write:newValueCopy
charHandle:charHandle
@@ -753,7 +821,7 @@ void QLowEnergyControllerPrivateOSX::writeCharacteristic(QSharedPointer<QLowEner
});
} else {
#ifndef Q_OS_TVOS
- const auto manager = peripheralManager.data();
+ const auto manager = peripheralManager.getAs<ObjCPeripheralManager>();
dispatch_async(leQueue, ^{
[manager write:newValueCopy charHandle:charHandle];
});
@@ -763,9 +831,9 @@ void QLowEnergyControllerPrivateOSX::writeCharacteristic(QSharedPointer<QLowEner
}
}
-quint16 QLowEnergyControllerPrivateOSX::updateValueOfCharacteristic(QLowEnergyHandle charHandle,
- const QByteArray &value,
- bool appendValue)
+quint16 QLowEnergyControllerPrivateDarwin::updateValueOfCharacteristic(QLowEnergyHandle charHandle,
+ const QByteArray &value,
+ bool appendValue)
{
QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);
if (!service.isNull()) {
@@ -784,18 +852,20 @@ quint16 QLowEnergyControllerPrivateOSX::updateValueOfCharacteristic(QLowEnergyHa
return 0;
}
-void QLowEnergyControllerPrivateOSX::readDescriptor(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle descriptorHandle)
+void QLowEnergyControllerPrivateDarwin::readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle)
{
+ Q_UNUSED(charHandle) // Hehe, yes!
+
Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)");
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid controller");
if (role == QLowEnergyController::PeripheralRole) {
qCWarning(QT_BT_OSX) << "invalid role (peripheral)";
return;
}
- if (!discoveredServices.contains(service->uuid)) {
+ if (!serviceList.contains(service->uuid)) {
qCWarning(QT_BT_OSX) << "no service with uuid:"
<< service->uuid << "found";
return;
@@ -808,19 +878,21 @@ void QLowEnergyControllerPrivateOSX::readDescriptor(QSharedPointer<QLowEnergySer
}
// Attention! Copy objects!
const QBluetoothUuid serviceUuid(service->uuid);
- ObjCCentralManager * const manager = centralManager.data();
+ ObjCCentralManager * const manager = centralManager.getAs<ObjCCentralManager>();
dispatch_async(leQueue, ^{
[manager readDescriptor:descriptorHandle
onService:serviceUuid];
});
}
-void QLowEnergyControllerPrivateOSX::writeDescriptor(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle descriptorHandle,
- const QByteArray &newValue)
+void QLowEnergyControllerPrivateDarwin::writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle,
+ const QByteArray &newValue)
{
+ Q_UNUSED(charHandle)
+
Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)");
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid controller");
if (role == QLowEnergyController::PeripheralRole) {
qCWarning(QT_BT_OSX) << "invalid role (peripheral)";
@@ -830,20 +902,17 @@ void QLowEnergyControllerPrivateOSX::writeDescriptor(QSharedPointer<QLowEnergySe
// We can work only with services found on a given peripheral
// (== created by the given LE controller),
// otherwise we can not write anything at all.
- if (!discoveredServices.contains(service->uuid)) {
+ if (!serviceList.contains(service->uuid)) {
qCWarning(QT_BT_OSX) << "no service with uuid:"
<< service->uuid << " found";
return;
}
dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- return;
- }
+ Q_ASSERT_X(leQueue, Q_FUNC_INFO, "no LE queue found");
// Attention! Copy objects!
const QBluetoothUuid serviceUuid(service->uuid);
- ObjCCentralManager * const manager = centralManager.data();
+ ObjCCentralManager * const manager = centralManager.getAs<ObjCCentralManager>();
const QByteArray newValueCopy(newValue);
dispatch_async(leQueue, ^{
[manager write:newValueCopy
@@ -852,8 +921,8 @@ void QLowEnergyControllerPrivateOSX::writeDescriptor(QSharedPointer<QLowEnergySe
});
}
-quint16 QLowEnergyControllerPrivateOSX::updateValueOfDescriptor(QLowEnergyHandle charHandle, QLowEnergyHandle descHandle,
- const QByteArray &value, bool appendValue)
+quint16 QLowEnergyControllerPrivateDarwin::updateValueOfDescriptor(QLowEnergyHandle charHandle, QLowEnergyHandle descHandle,
+ const QByteArray &value, bool appendValue)
{
QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);
if (!service.isNull()) {
@@ -878,66 +947,15 @@ quint16 QLowEnergyControllerPrivateOSX::updateValueOfDescriptor(QLowEnergyHandle
return 0;
}
-QSharedPointer<QLowEnergyServicePrivate> QLowEnergyControllerPrivateOSX::serviceForHandle(QLowEnergyHandle handle)
-{
- const QList<QSharedPointer<QLowEnergyServicePrivate>> services
- = discoveredServices.values();
- for (QSharedPointer<QLowEnergyServicePrivate> service : services) {
- if (service->startHandle <= handle && handle <= service->endHandle)
- return service;
- }
-
- return QSharedPointer<QLowEnergyServicePrivate>();
-}
-
-QLowEnergyCharacteristic QLowEnergyControllerPrivateOSX::characteristicForHandle(QLowEnergyHandle charHandle)
-{
- QSharedPointer<QLowEnergyServicePrivate> service(serviceForHandle(charHandle));
- if (service.isNull())
- return QLowEnergyCharacteristic();
-
- if (service->characteristicList.isEmpty())
- return QLowEnergyCharacteristic();
-
- // Check whether it is the handle of a characteristic header
- if (service->characteristicList.contains(charHandle))
- return QLowEnergyCharacteristic(service, charHandle);
-
- // Check whether it is the handle of the characteristic value or its descriptors
- QList<QLowEnergyHandle> charHandles(service->characteristicList.keys());
- std::sort(charHandles.begin(), charHandles.end());
-
- for (int i = charHandles.size() - 1; i >= 0; --i) {
- if (charHandles.at(i) > charHandle)
- continue;
-
- return QLowEnergyCharacteristic(service, charHandles.at(i));
- }
-
- return QLowEnergyCharacteristic();
-}
-
-QLowEnergyDescriptor QLowEnergyControllerPrivateOSX::descriptorForHandle(QLowEnergyHandle descriptorHandle)
-{
- const QLowEnergyCharacteristic ch(characteristicForHandle(descriptorHandle));
- if (!ch.isValid())
- return QLowEnergyDescriptor();
-
- const QLowEnergyServicePrivate::CharData charData = ch.d_ptr->characteristicList[ch.attributeHandle()];
-
- if (charData.descriptorList.contains(descriptorHandle))
- return QLowEnergyDescriptor(ch.d_ptr, ch.attributeHandle(), descriptorHandle);
-
- return QLowEnergyDescriptor();
-}
-
-void QLowEnergyControllerPrivateOSX::setErrorDescription(QLowEnergyController::Error errorCode)
+void QLowEnergyControllerPrivateDarwin::setErrorDescription(QLowEnergyController::Error errorCode)
{
// This function does not emit!
+ // TODO: well, it is not a reason to duplicate a significant part of
+ // setError though!
- lastError = errorCode;
+ error = errorCode;
- switch (lastError) {
+ switch (error) {
case QLowEnergyController::NoError:
errorString.clear();
break;
@@ -963,46 +981,36 @@ void QLowEnergyControllerPrivateOSX::setErrorDescription(QLowEnergyController::E
}
}
-void QLowEnergyControllerPrivateOSX::invalidateServices()
-{
- const QList<QSharedPointer<QLowEnergyServicePrivate>> services
- = discoveredServices.values();
- for (const QSharedPointer<QLowEnergyServicePrivate> service : services) {
- service->setController(nullptr);
- service->setState(QLowEnergyService::InvalidService);
- }
-
- discoveredServices.clear();
-}
-
-bool QLowEnergyControllerPrivateOSX::connectSlots(OSXBluetooth::LECBManagerNotifier *notifier)
+bool QLowEnergyControllerPrivateDarwin::connectSlots(OSXBluetooth::LECBManagerNotifier *notifier)
{
using OSXBluetooth::LECBManagerNotifier;
Q_ASSERT_X(notifier, Q_FUNC_INFO, "invalid notifier object (null)");
bool ok = connect(notifier, &LECBManagerNotifier::connected,
- this, &QLowEnergyControllerPrivateOSX::_q_connected);
+ this, &QLowEnergyControllerPrivateDarwin::_q_connected);
ok = ok && connect(notifier, &LECBManagerNotifier::disconnected,
- this, &QLowEnergyControllerPrivateOSX::_q_disconnected);
+ this, &QLowEnergyControllerPrivateDarwin::_q_disconnected);
ok = ok && connect(notifier, &LECBManagerNotifier::serviceDiscoveryFinished,
- this, &QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished);
+ this, &QLowEnergyControllerPrivateDarwin::_q_serviceDiscoveryFinished);
+ ok = ok && connect(notifier, &LECBManagerNotifier::servicesWereModified,
+ this, &QLowEnergyControllerPrivateDarwin::_q_servicesWereModified);
ok = ok && connect(notifier, &LECBManagerNotifier::serviceDetailsDiscoveryFinished,
- this, &QLowEnergyControllerPrivateOSX::_q_serviceDetailsDiscoveryFinished);
+ this, &QLowEnergyControllerPrivateDarwin::_q_serviceDetailsDiscoveryFinished);
ok = ok && connect(notifier, &LECBManagerNotifier::characteristicRead,
- this, &QLowEnergyControllerPrivateOSX::_q_characteristicRead);
+ this, &QLowEnergyControllerPrivateDarwin::_q_characteristicRead);
ok = ok && connect(notifier, &LECBManagerNotifier::characteristicWritten,
- this, &QLowEnergyControllerPrivateOSX::_q_characteristicWritten);
+ this, &QLowEnergyControllerPrivateDarwin::_q_characteristicWritten);
ok = ok && connect(notifier, &LECBManagerNotifier::characteristicUpdated,
- this, &QLowEnergyControllerPrivateOSX::_q_characteristicUpdated);
+ this, &QLowEnergyControllerPrivateDarwin::_q_characteristicUpdated);
ok = ok && connect(notifier, &LECBManagerNotifier::descriptorRead,
- this, &QLowEnergyControllerPrivateOSX::_q_descriptorRead);
+ this, &QLowEnergyControllerPrivateDarwin::_q_descriptorRead);
ok = ok && connect(notifier, &LECBManagerNotifier::descriptorWritten,
- this, &QLowEnergyControllerPrivateOSX::_q_descriptorWritten);
+ this, &QLowEnergyControllerPrivateDarwin::_q_descriptorWritten);
ok = ok && connect(notifier, &LECBManagerNotifier::notificationEnabled,
- this, &QLowEnergyControllerPrivateOSX::_q_notificationEnabled);
+ this, &QLowEnergyControllerPrivateDarwin::_q_notificationEnabled);
ok = ok && connect(notifier, &LECBManagerNotifier::LEnotSupported,
- this, &QLowEnergyControllerPrivateOSX::_q_LEnotSupported);
+ this, &QLowEnergyControllerPrivateDarwin::_q_LEnotSupported);
ok = ok && connect(notifier, SIGNAL(CBManagerError(QLowEnergyController::Error)),
this, SLOT(_q_CBManagerError(QLowEnergyController::Error)));
ok = ok && connect(notifier, SIGNAL(CBManagerError(const QBluetoothUuid &, QLowEnergyController::Error)),
@@ -1016,253 +1024,9 @@ bool QLowEnergyControllerPrivateOSX::connectSlots(OSXBluetooth::LECBManagerNotif
return ok;
}
-QLowEnergyController::QLowEnergyController(const QBluetoothAddress &remoteAddress,
- QObject *parent)
- : QObject(parent),
- d_ptr(new QLowEnergyControllerPrivateOSX(CentralRole, this))
-{
- OSX_D_PTR;
-
- osx_d_ptr->remoteAddress = remoteAddress;
- osx_d_ptr->localAddress = QBluetoothLocalDevice().address();
-
- qCWarning(QT_BT_OSX) << "construction with remote address "
- "is not supported!";
-}
-
-QLowEnergyController::QLowEnergyController(const QBluetoothDeviceInfo &remoteDevice,
- QObject *parent)
- : QObject(parent),
- d_ptr(new QLowEnergyControllerPrivateOSX(CentralRole, this, remoteDevice))
-{
- OSX_D_PTR;
-
- osx_d_ptr->localAddress = QBluetoothLocalDevice().address();
- // That's the only "real" ctor - with Core Bluetooth we need a _valid_ deviceUuid
- // from 'remoteDevice'.
-}
-
-QLowEnergyController::QLowEnergyController(const QBluetoothAddress &remoteAddress,
- const QBluetoothAddress &localAddress,
- QObject *parent)
- : QObject(parent),
- d_ptr(new QLowEnergyControllerPrivateOSX(CentralRole, this))
-{
- OSX_D_PTR;
-
- osx_d_ptr->remoteAddress = remoteAddress;
- osx_d_ptr->localAddress = localAddress;
-
- qCWarning(QT_BT_OSX) << "construction with remote/local "
- "addresses is not supported!";
-}
-
-QLowEnergyController::QLowEnergyController(QObject *parent)
- : QObject(parent),
- d_ptr(new QLowEnergyControllerPrivateOSX(PeripheralRole, this))
-{
- OSX_D_PTR;
-
- osx_d_ptr->localAddress = QBluetoothLocalDevice().address();
-}
-
-QLowEnergyController *QLowEnergyController::createCentral(const QBluetoothDeviceInfo &remoteDevice,
- QObject *parent)
-{
- return new QLowEnergyController(remoteDevice, parent);
-}
-
-QLowEnergyController *QLowEnergyController::createPeripheral(QObject *parent)
-{
- return new QLowEnergyController(parent);
-}
-
-QLowEnergyController::~QLowEnergyController()
-{
- // Deleting a peripheral will also disconnect.
- delete d_ptr;
-}
-
-QLowEnergyController::Role QLowEnergyController::role() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->role;
-}
-
-QBluetoothAddress QLowEnergyController::localAddress() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->localAddress;
-}
-
-QBluetoothAddress QLowEnergyController::remoteAddress() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->remoteAddress;
-}
-
-QBluetoothUuid QLowEnergyController::remoteDeviceUuid() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->deviceUuid;
-}
-
-QString QLowEnergyController::remoteName() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->deviceName;
-}
-
-QLowEnergyController::ControllerState QLowEnergyController::state() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->controllerState;
-}
-
-QLowEnergyController::RemoteAddressType QLowEnergyController::remoteAddressType() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->addressType;
-}
-
-void QLowEnergyController::setRemoteAddressType(RemoteAddressType type)
-{
- Q_UNUSED(type)
-
- OSX_D_PTR;
-
- osx_d_ptr->addressType = type;
-}
-
-void QLowEnergyController::connectToDevice()
-{
- OSX_D_PTR;
-
- // A memory allocation problem.
- if (!osx_d_ptr->isValid())
- return osx_d_ptr->_q_CBManagerError(UnknownError);
-
- if (role() == PeripheralRole) {
- qCWarning(QT_BT_OSX) << "can not connect in peripheral role";
- return osx_d_ptr->_q_CBManagerError(ConnectionError);
- }
-
- // No QBluetoothDeviceInfo provided during construction.
- if (osx_d_ptr->deviceUuid.isNull())
- return osx_d_ptr->_q_CBManagerError(UnknownRemoteDeviceError);
-
- if (osx_d_ptr->controllerState != UnconnectedState)
- return;
-
- osx_d_ptr->connectToDevice();
-}
-
-void QLowEnergyController::disconnectFromDevice()
-{
- if (state() == UnconnectedState || state() == ClosingState)
- return;
-
- OSX_D_PTR;
-
- if (role() == PeripheralRole) {
- // CoreBluetooth API intentionally does not provide any way of closing
- // a connection. All we can do here is to stop the advertisement.
- stopAdvertising();
- return;
- }
-
- if (osx_d_ptr->isValid()) {
- const ControllerState oldState = osx_d_ptr->controllerState;
-
- if (dispatch_queue_t leQueue = OSXBluetooth::qt_LE_queue()) {
- osx_d_ptr->controllerState = ClosingState;
- emit stateChanged(ClosingState);
- osx_d_ptr->invalidateServices();
-
- QT_MANGLE_NAMESPACE(OSXBTCentralManager) *manager
- = osx_d_ptr->centralManager.data();
- dispatch_async(leQueue, ^{
- [manager disconnectFromDevice];
- });
-
- if (oldState == ConnectingState) {
- // With a pending connect attempt there is no
- // guarantee we'll ever have didDisconnect callback,
- // set the state here and now to make sure we still
- // can connect.
- osx_d_ptr->controllerState = UnconnectedState;
- emit stateChanged(UnconnectedState);
- }
- } else {
- qCCritical(QT_BT_OSX) << "qt LE queue is nil, "
- "can not dispatch 'disconnect'";
- }
- }
-}
-
-void QLowEnergyController::discoverServices()
-{
- if (role() == PeripheralRole) {
- qCWarning(QT_BT_OSX) << "invalid role (peripheral)";
- return;
- }
-
- if (state() != ConnectedState)
- return;
-
- OSX_D_PTR;
-
- osx_d_ptr->discoverServices();
-}
-
-QList<QBluetoothUuid> QLowEnergyController::services() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->discoveredServices.keys();
-}
-
-QLowEnergyService *QLowEnergyController::createServiceObject(const QBluetoothUuid &serviceUuid,
- QObject *parent)
-{
- OSX_D_PTR;
-
- QLowEnergyService *service = nullptr;
-
- QLowEnergyControllerPrivateOSX::ServiceMap::const_iterator it = osx_d_ptr->discoveredServices.constFind(serviceUuid);
- if (it != osx_d_ptr->discoveredServices.constEnd()) {
- const QSharedPointer<QLowEnergyServicePrivate> &serviceData = it.value();
-
- service = new QLowEnergyService(serviceData, parent);
- }
-
- return service;
-}
-
-QLowEnergyController::Error QLowEnergyController::error() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->lastError;
-}
-
-QString QLowEnergyController::errorString() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->errorString;
-}
-
-void QLowEnergyController::startAdvertising(const QLowEnergyAdvertisingParameters &params,
- const QLowEnergyAdvertisingData &advertisingData,
- const QLowEnergyAdvertisingData &scanResponseData)
+void QLowEnergyControllerPrivateDarwin::startAdvertising(const QLowEnergyAdvertisingParameters &params,
+ const QLowEnergyAdvertisingData &advertisingData,
+ const QLowEnergyAdvertisingData &scanResponseData)
{
#ifdef Q_OS_TVOS
Q_UNUSED(params)
@@ -1270,123 +1034,65 @@ void QLowEnergyController::startAdvertising(const QLowEnergyAdvertisingParameter
Q_UNUSED(scanResponseData)
qCWarning(QT_BT_OSX) << "advertising is not supported on your platform";
#else
- OSX_D_PTR;
- if (!osx_d_ptr->isValid())
- return osx_d_ptr->_q_CBManagerError(UnknownError);
+ if (!isValid())
+ return _q_CBManagerError(QLowEnergyController::UnknownError);
- if (role() != PeripheralRole) {
- qCWarning(QT_BT_OSX) << "invalid role";
+ if (role != QLowEnergyController::PeripheralRole) {
+ qCWarning(QT_BT_OSX) << "controller is not a peripheral, cannot start advertising";
return;
}
- if (state() != UnconnectedState) {
- qCWarning(QT_BT_OSX) << "invalid state" << state();
+ if (state != QLowEnergyController::UnconnectedState) {
+ qCWarning(QT_BT_OSX) << "invalid state" << state;
return;
}
auto leQueue(OSXBluetooth::qt_LE_queue());
if (!leQueue) {
qCWarning(QT_BT_OSX) << "no LE queue found";
- osx_d_ptr->setErrorDescription(QLowEnergyController::UnknownError);
+ setErrorDescription(QLowEnergyController::UnknownError);
return;
}
- [osx_d_ptr->peripheralManager setParameters:params
- data:advertisingData
- scanResponse:scanResponseData];
+ const auto manager = peripheralManager.getAs<ObjCPeripheralManager>();
+ [manager setParameters:params data:advertisingData scanResponse:scanResponseData];
- osx_d_ptr->controllerState = AdvertisingState;
- emit stateChanged(AdvertisingState);
+ setState(QLowEnergyController::AdvertisingState);
- const auto manager = osx_d_ptr->peripheralManager.data();
dispatch_async(leQueue, ^{
[manager startAdvertising];
});
#endif
}
-void QLowEnergyController::stopAdvertising()
+void QLowEnergyControllerPrivateDarwin::stopAdvertising()
{
#ifdef Q_OS_TVOS
qCWarning(QT_BT_OSX) << "advertising is not supported on your platform";
#else
- OSX_D_PTR;
+ if (!isValid())
+ return _q_CBManagerError(QLowEnergyController::UnknownError);
- if (!osx_d_ptr->isValid())
- return osx_d_ptr->_q_CBManagerError(UnknownError);
-
- if (state() != AdvertisingState) {
- qCDebug(QT_BT_OSX) << "cannot stop advertising, called in state" << state();
+ if (state != QLowEnergyController::AdvertisingState) {
+ qCDebug(QT_BT_OSX) << "cannot stop advertising, called in state" << state;
return;
}
if (const auto leQueue = OSXBluetooth::qt_LE_queue()) {
- const auto manager = osx_d_ptr->peripheralManager.data();
+ const auto manager = peripheralManager.getAs<ObjCPeripheralManager>();
dispatch_sync(leQueue, ^{
[manager stopAdvertising];
});
- osx_d_ptr->controllerState = UnconnectedState;
- emit stateChanged(UnconnectedState);
+ setState(QLowEnergyController::UnconnectedState);
} else {
qCWarning(QT_BT_OSX) << "no LE queue found";
- osx_d_ptr->setErrorDescription(QLowEnergyController::UnknownError);
+ setErrorDescription(QLowEnergyController::UnknownError);
return;
}
#endif
}
-QLowEnergyService *QLowEnergyController::addService(const QLowEnergyServiceData &data,
- QObject *parent)
-{
-#ifdef Q_OS_TVOS
- Q_UNUSED(data)
- Q_UNUSED(parent)
- qCWarning(QT_BT_OSX) << "peripheral role is not supported on your platform";
-#else
- OSX_D_PTR;
-
- if (!osx_d_ptr->isValid()) {
- osx_d_ptr->_q_CBManagerError(UnknownError);
- return nullptr;
- }
-
- if (role() != PeripheralRole) {
- qCWarning(QT_BT_OSX) << "not in peripheral role";
- return nullptr;
- }
-
- if (state() != UnconnectedState) {
- qCWarning(QT_BT_OSX) << "invalid state";
- return nullptr;
- }
-
- if (!data.isValid()) {
- qCWarning(QT_BT_OSX) << "invalid service";
- return nullptr;
- }
-
- for (auto includedService : data.includedServices())
- includedService->d_ptr->type |= QLowEnergyService::IncludedService;
-
- if (const auto servicePrivate = [osx_d_ptr->peripheralManager addService:data]) {
- servicePrivate->setController(osx_d_ptr);
- servicePrivate->state = QLowEnergyService::LocalService;
- osx_d_ptr->discoveredServices.insert(servicePrivate->uuid, servicePrivate);
- return new QLowEnergyService(servicePrivate, parent);
- }
-#endif
-
- return nullptr;
-}
-
-void QLowEnergyController::requestConnectionUpdate(const QLowEnergyConnectionParameters &params)
-{
- Q_UNUSED(params);
- qCWarning(QT_BT_OSX) << "Connection update not implemented on your platform";
-}
-
QT_END_NAMESPACE
-#include "moc_qlowenergycontroller_osx_p.cpp"
diff --git a/src/bluetooth/qlowenergycontroller_osx_p.h b/src/bluetooth/qlowenergycontroller_darwin_p.h
index 24b7c6e9..960d7fbc 100644
--- a/src/bluetooth/qlowenergycontroller_osx_p.h
+++ b/src/bluetooth/qlowenergycontroller_darwin_p.h
@@ -37,8 +37,8 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QLOWENERGYCONTROLLER_OSX_P_H
-#define QLOWENERGYCONTROLLER_OSX_P_H
+#ifndef QLOWENERGYCONTROLLER_DARWIN_P_H
+#define QLOWENERGYCONTROLLER_DARWIN_P_H
//
// W A R N I N G
@@ -51,46 +51,64 @@
// We mean it.
//
-#include "osx/osxbtperipheralmanager_p.h"
#include "qlowenergyserviceprivate_p.h"
-#include "osx/osxbtcentralmanager_p.h"
#include "qlowenergycontrollerbase_p.h"
#include "qlowenergycontroller.h"
#include "osx/osxbtnotifier_p.h"
-#include "osx/osxbtutility_p.h"
#include "qbluetoothaddress.h"
#include "qbluetoothuuid.h"
+#include "osx/btraii_p.h"
#include <QtCore/qsharedpointer.h>
-#include <QtCore/qsysinfo.h>
#include <QtCore/qglobal.h>
#include <QtCore/qstring.h>
#include <QtCore/qmap.h>
QT_BEGIN_NAMESPACE
-namespace OSXBluetooth
-{
-
-class LECBManagerNotifier;
-
-}
-
class QByteArray;
-// Suffix 'OSX' is a legacy, it's also iOS.
-class QLowEnergyControllerPrivateOSX : public QLowEnergyControllerPrivate
+class QLowEnergyControllerPrivateDarwin : public QLowEnergyControllerPrivate
{
friend class QLowEnergyController;
friend class QLowEnergyService;
Q_OBJECT
public:
- QLowEnergyControllerPrivateOSX(QLowEnergyController::Role role, QLowEnergyController *q,
- const QBluetoothDeviceInfo &info = QBluetoothDeviceInfo());
- ~QLowEnergyControllerPrivateOSX();
-
- bool isValid() const;
+ QLowEnergyControllerPrivateDarwin();
+ ~QLowEnergyControllerPrivateDarwin();
+
+ void init() override;
+ void connectToDevice() override;
+ void disconnectFromDevice() override;
+ void discoverServices() override;
+ void discoverServiceDetails(const QBluetoothUuid &serviceUuid) override;
+
+ void readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle) override;
+ void readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle) override;
+
+ void writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle, const QByteArray &newValue,
+ QLowEnergyService::WriteMode mode) override;
+ void writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle,
+ const QByteArray &newValue) override;
+
+
+ void requestConnectionUpdate(const QLowEnergyConnectionParameters &params) override;
+ void addToGenericAttributeList(const QLowEnergyServiceData &service,
+ QLowEnergyHandle startHandle) override;
+
+ void startAdvertising(const QLowEnergyAdvertisingParameters &params,
+ const QLowEnergyAdvertisingData &advertisingData,
+ const QLowEnergyAdvertisingData &scanResponseData) override;
+ void stopAdvertising()override;
+ QLowEnergyService *addServiceHelper(const QLowEnergyServiceData &service) override;
+ bool isValid() const; // QT6 - delete this logic.
private Q_SLOTS:
void _q_connected();
@@ -98,6 +116,7 @@ private Q_SLOTS:
void _q_serviceDiscoveryFinished();
void _q_serviceDetailsDiscoveryFinished(QSharedPointer<QLowEnergyServicePrivate> service);
+ void _q_servicesWereModified();
void _q_characteristicRead(QLowEnergyHandle charHandle, const QByteArray &value);
void _q_characteristicWritten(QLowEnergyHandle charHandle, const QByteArray &value);
@@ -112,75 +131,30 @@ private Q_SLOTS:
void _q_CBManagerError(const QBluetoothUuid &serviceUuid, QLowEnergyService::ServiceError error);
private:
- void connectToDevice();
- void discoverServices();
- void discoverServiceDetails(const QBluetoothUuid &serviceUuid);
-
void setNotifyValue(QSharedPointer<QLowEnergyServicePrivate> service,
QLowEnergyHandle charHandle, const QByteArray &newValue);
- void readCharacteristic(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle charHandle);
- void writeCharacteristic(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle charHandle, const QByteArray &newValue,
- QLowEnergyService::WriteMode mode);
-
quint16 updateValueOfCharacteristic(QLowEnergyHandle charHandle,
const QByteArray &value,
bool appendValue);
- void readDescriptor(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle charHandle);
- void writeDescriptor(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle descriptorHandle,
- const QByteArray &newValue);
-
-
quint16 updateValueOfDescriptor(QLowEnergyHandle charHandle,
QLowEnergyHandle descHandle,
const QByteArray &value,
bool appendValue);
- // 'Lookup' functions:
- QSharedPointer<QLowEnergyServicePrivate> serviceForHandle(QLowEnergyHandle serviceHandle);
- QLowEnergyCharacteristic characteristicForHandle(QLowEnergyHandle charHandle);
- QLowEnergyDescriptor descriptorForHandle(QLowEnergyHandle descriptorHandle);
-
void setErrorDescription(QLowEnergyController::Error errorCode);
- void invalidateServices();
bool connectSlots(OSXBluetooth::LECBManagerNotifier *notifier);
- QLowEnergyController *q_ptr;
- QBluetoothUuid deviceUuid;
- QString deviceName;
-
- QString errorString;
- QLowEnergyController::Error lastError;
-
- QBluetoothAddress localAddress;
- QBluetoothAddress remoteAddress;
-
- QLowEnergyController::Role role;
-
- QLowEnergyController::ControllerState controllerState;
- QLowEnergyController::RemoteAddressType addressType;
-
- typedef QT_MANGLE_NAMESPACE(OSXBTCentralManager) ObjCCentralManager;
- typedef OSXBluetooth::ObjCScopedPointer<ObjCCentralManager> CentralManager;
- CentralManager centralManager;
+ DarwinBluetooth::ScopedPointer centralManager;
#ifndef Q_OS_TVOS
- typedef QT_MANGLE_NAMESPACE(OSXBTPeripheralManager) ObjCPeripheralManager;
- typedef OSXBluetooth::ObjCScopedPointer<ObjCPeripheralManager> PeripheralManager;
- PeripheralManager peripheralManager;
+ DarwinBluetooth::ScopedPointer peripheralManager;
#endif
- typedef QMap<QBluetoothUuid, QSharedPointer<QLowEnergyServicePrivate> > ServiceMap;
- typedef ServiceMap::const_iterator ConstServiceIterator;
- typedef ServiceMap::iterator ServiceIterator;
- ServiceMap discoveredServices;
+ using ServiceMap = QMap<QBluetoothUuid, QSharedPointer<QLowEnergyServicePrivate>>;
};
QT_END_NAMESPACE
-#endif
+#endif // QLOWENERGYCONTROLLER_DARWIN_P_H
diff --git a/src/bluetooth/qlowenergycontroller_winrt.cpp b/src/bluetooth/qlowenergycontroller_winrt.cpp
index ed279ffa..ab566bd9 100644
--- a/src/bluetooth/qlowenergycontroller_winrt.cpp
+++ b/src/bluetooth/qlowenergycontroller_winrt.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qlowenergycontroller_winrt_p.h"
+#include "qbluetoothutils_winrt_p.h"
#include <QtBluetooth/QLowEnergyCharacteristicData>
#include <QtBluetooth/QLowEnergyDescriptorData>
@@ -75,52 +76,7 @@ typedef GattReadClientCharacteristicConfigurationDescriptorResult ClientCharConf
typedef IGattReadClientCharacteristicConfigurationDescriptorResult IClientCharConfigDescriptorResult;
Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT)
-
-static QVector<QBluetoothUuid> getIncludedServiceIds(const ComPtr<IGattDeviceService> &service)
-{
- QVector<QBluetoothUuid> result;
- ComPtr<IGattDeviceService2> service2;
- HRESULT hr = service.As(&service2);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IVectorView<GattDeviceService *>> includedServices;
- hr = service2->GetAllIncludedServices(&includedServices);
- Q_ASSERT_SUCCEEDED(hr);
-
- uint count;
- hr = includedServices->get_Size(&count);
- Q_ASSERT_SUCCEEDED(hr);
- for (uint i = 0; i < count; ++i) {
- ComPtr<IGattDeviceService> includedService;
- hr = includedServices->GetAt(i, &includedService);
- Q_ASSERT_SUCCEEDED(hr);
- GUID guuid;
- hr = includedService->get_Uuid(&guuid);
- Q_ASSERT_SUCCEEDED(hr);
- const QBluetoothUuid service(guuid);
- result << service;
-
- result << getIncludedServiceIds(includedService);
- }
- return result;
-}
-
-static QByteArray byteArrayFromBuffer(const ComPtr<IBuffer> &buffer, bool isWCharString = false)
-{
- ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteAccess;
- HRESULT hr = buffer.As(&byteAccess);
- Q_ASSERT_SUCCEEDED(hr);
- char *data;
- hr = byteAccess->Buffer(reinterpret_cast<byte **>(&data));
- Q_ASSERT_SUCCEEDED(hr);
- UINT32 size;
- hr = buffer->get_Length(&size);
- Q_ASSERT_SUCCEEDED(hr);
- if (isWCharString) {
- QString valueString = QString::fromUtf16(reinterpret_cast<ushort *>(data)).left(size / 2);
- return valueString.toUtf8();
- }
- return QByteArray(data, size);
-}
+Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT_SERVICE_THREAD)
static QByteArray byteArrayFromGattResult(const ComPtr<IGattReadResult> &gattResult, bool isWCharString = false)
{
@@ -284,6 +240,9 @@ QLowEnergyControllerPrivateWinRT::QLowEnergyControllerPrivateWinRT()
qCDebug(QT_BT_WINRT) << __FUNCTION__;
registerQLowEnergyControllerMetaType();
+ connect(this, &QLowEnergyControllerPrivateWinRT::characteristicChanged,
+ this, &QLowEnergyControllerPrivateWinRT::handleCharacteristicChanged,
+ Qt::QueuedConnection);
}
QLowEnergyControllerPrivateWinRT::~QLowEnergyControllerPrivateWinRT()
@@ -291,9 +250,7 @@ QLowEnergyControllerPrivateWinRT::~QLowEnergyControllerPrivateWinRT()
if (mDevice && mStatusChangedToken.value)
mDevice->remove_ConnectionStatusChanged(mStatusChangedToken);
- qCDebug(QT_BT_WINRT) << "Unregistering " << mValueChangedTokens.count() << " value change tokens";
- for (const ValueChangedEntry &entry : qAsConst(mValueChangedTokens))
- entry.characteristic->remove_ValueChanged(entry.token);
+ unregisterFromValueChanges();
}
void QLowEnergyControllerPrivateWinRT::init()
@@ -340,8 +297,10 @@ void QLowEnergyControllerPrivateWinRT::connectToDevice()
&& status == BluetoothConnectionStatus::BluetoothConnectionStatus_Connected) {
setState(QLowEnergyController::ConnectedState);
emit q->connected();
- } else if (state == QLowEnergyController::ConnectedState
+ } else if (state != QLowEnergyController::UnconnectedState
&& status == BluetoothConnectionStatus::BluetoothConnectionStatus_Disconnected) {
+ invalidateServices();
+ unregisterFromValueChanges();
setError(QLowEnergyController::RemoteHostClosedError);
setState(QLowEnergyController::UnconnectedState);
emit q->disconnected();
@@ -436,12 +395,17 @@ void QLowEnergyControllerPrivateWinRT::disconnectFromDevice()
{
qCDebug(QT_BT_WINRT) << __FUNCTION__;
Q_Q(QLowEnergyController);
+ setState(QLowEnergyController::ClosingState);
+ unregisterFromValueChanges();
+ if (mDevice) {
+ if (mStatusChangedToken.value) {
+ mDevice->remove_ConnectionStatusChanged(mStatusChangedToken);
+ mStatusChangedToken.value = 0;
+ }
+ mDevice = nullptr;
+ }
setState(QLowEnergyController::UnconnectedState);
emit q->disconnected();
- if (mDevice && mStatusChangedToken.value) {
- mDevice->remove_ConnectionStatusChanged(mStatusChangedToken);
- mStatusChangedToken.value = 0;
- }
}
ComPtr<IGattDeviceService> QLowEnergyControllerPrivateWinRT::getNativeService(const QBluetoothUuid &serviceUuid)
@@ -493,7 +457,7 @@ void QLowEnergyControllerPrivateWinRT::registerForValueChanges(const QBluetoothU
ComPtr<IBuffer> buffer;
hr = args->get_CharacteristicValue(&buffer);
Q_ASSERT_SUCCEEDED(hr);
- characteristicChanged(handle, byteArrayFromBuffer(buffer));
+ emit characteristicChanged(handle, byteArrayFromBuffer(buffer));
return S_OK;
}).Get(), &token);
Q_ASSERT_SUCCEEDED(hr);
@@ -502,6 +466,17 @@ void QLowEnergyControllerPrivateWinRT::registerForValueChanges(const QBluetoothU
<< serviceUuid << "registered for value changes";
}
+void QLowEnergyControllerPrivateWinRT::unregisterFromValueChanges()
+{
+ qCDebug(QT_BT_WINRT) << "Unregistering " << mValueChangedTokens.count() << " value change tokens";
+ HRESULT hr;
+ for (const ValueChangedEntry &entry : qAsConst(mValueChangedTokens)) {
+ hr = entry.characteristic->remove_ValueChanged(entry.token);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ mValueChangedTokens.clear();
+}
+
void QLowEnergyControllerPrivateWinRT::obtainIncludedServices(QSharedPointer<QLowEnergyServicePrivate> servicePointer,
ComPtr<IGattDeviceService> service)
{
@@ -527,6 +502,9 @@ void QLowEnergyControllerPrivateWinRT::obtainIncludedServices(QSharedPointer<QLo
Q_ASSERT_SUCCEEDED(hr);
const QBluetoothUuid includedUuid(guuid);
QSharedPointer<QLowEnergyServicePrivate> includedPointer;
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__
+ << "Changing service pointer from thread"
+ << QThread::currentThread();
if (serviceList.contains(includedUuid)) {
includedPointer = serviceList.value(includedUuid);
} else {
@@ -537,6 +515,9 @@ void QLowEnergyControllerPrivateWinRT::obtainIncludedServices(QSharedPointer<QLo
includedPointer = QSharedPointer<QLowEnergyServicePrivate>(priv);
serviceList.insert(includedUuid, includedPointer);
}
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__
+ << "Changing service pointer from thread"
+ << QThread::currentThread();
includedPointer->type |= QLowEnergyService::IncludedService;
servicePointer->includedServices.append(includedUuid);
@@ -566,6 +547,9 @@ void QLowEnergyControllerPrivateWinRT::discoverServices()
Q_ASSERT_SUCCEEDED(hr);
const QBluetoothUuid service(guuid);
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__
+ << "Changing service pointer from thread"
+ << QThread::currentThread();
QSharedPointer<QLowEnergyServicePrivate> pointer;
if (serviceList.contains(service)) {
pointer = serviceList.value(service);
@@ -605,6 +589,8 @@ void QLowEnergyControllerPrivateWinRT::discoverServiceDetails(const QBluetoothUu
//update service data
QSharedPointer<QLowEnergyServicePrivate> pointer = serviceList.value(service);
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+ << QThread::currentThread();
pointer->setState(QLowEnergyService::DiscoveringServices);
ComPtr<IGattDeviceService2> deviceService2;
@@ -698,6 +684,8 @@ void QLowEnergyControllerPrivateWinRT::readCharacteristic(const QSharedPointer<Q
const QLowEnergyHandle charHandle)
{
qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle;
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+ << QThread::currentThread();
Q_ASSERT(!service.isNull());
if (role == QLowEnergyController::PeripheralRole) {
service->setError(QLowEnergyService::CharacteristicReadError);
@@ -763,6 +751,8 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowE
const QLowEnergyHandle descHandle)
{
qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << descHandle;
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+ << QThread::currentThread();
Q_ASSERT(!service.isNull());
if (role == QLowEnergyController::PeripheralRole) {
service->setError(QLowEnergyService::DescriptorReadError);
@@ -779,7 +769,7 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowE
HRESULT hr;
hr = QEventDispatcherWinRT::runOnXamlThread([charHandle, descHandle, service, this]() {
- QLowEnergyServicePrivate::CharData charData = service->characteristicList.value(charHandle);
+ const QLowEnergyServicePrivate::CharData charData = service->characteristicList.value(charHandle);
ComPtr<IGattCharacteristic> characteristic = getNativeCharacteristic(service->uuid, charData.uuid);
if (!characteristic) {
qCDebug(QT_BT_WINRT) << "Could not obtain native characteristic" << charData.uuid
@@ -791,12 +781,13 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowE
// Get native descriptor
if (!charData.descriptorList.contains(descHandle))
qCDebug(QT_BT_WINRT) << "Descriptor" << descHandle << "cannot be found in characteristic" << charHandle;
- QLowEnergyServicePrivate::DescData descData = charData.descriptorList.value(descHandle);
- if (descData.uuid == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) {
+ const QLowEnergyServicePrivate::DescData descData = charData.descriptorList.value(descHandle);
+ const QBluetoothUuid descUuid = descData.uuid;
+ if (descUuid == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) {
ComPtr<IAsyncOperation<ClientCharConfigDescriptorResult *>> readOp;
HRESULT hr = characteristic->ReadClientCharacteristicConfigurationDescriptorAsync(&readOp);
Q_ASSERT_SUCCEEDED(hr);
- auto readCompletedLambda = [&charData, charHandle, &descData, descHandle, service]
+ auto readCompletedLambda = [charHandle, descHandle, service]
(IAsyncOperation<ClientCharConfigDescriptorResult *> *op, AsyncStatus status)
{
if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
@@ -837,9 +828,11 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowE
service->setError(QLowEnergyService::DescriptorReadError);
return S_OK;
}
+ QLowEnergyServicePrivate::DescData descData;
+ descData.uuid = QBluetoothUuid::ClientCharacteristicConfiguration;
descData.value = QByteArray(2, Qt::Uninitialized);
qToLittleEndian(result, descData.value.data());
- charData.descriptorList.insert(descHandle, descData);
+ service->characteristicList[charHandle].descriptorList[descHandle] = descData;
emit service->descriptorRead(QLowEnergyDescriptor(service, charHandle, descHandle),
descData.value);
return S_OK;
@@ -857,7 +850,7 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowE
ComPtr<IAsyncOperation<GattReadResult*>> readOp;
hr = descriptor->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached, &readOp);
Q_ASSERT_SUCCEEDED(hr);
- auto readCompletedLambda = [&charData, charHandle, &descData, descHandle, service]
+ auto readCompletedLambda = [charHandle, descHandle, descUuid, service]
(IAsyncOperation<GattReadResult*> *op, AsyncStatus status)
{
if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
@@ -873,11 +866,12 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowE
service->setError(QLowEnergyService::DescriptorReadError);
return S_OK;
}
- if (descData.uuid == QBluetoothUuid::CharacteristicUserDescription)
+ QLowEnergyServicePrivate::DescData descData;
+ if (descUuid == QBluetoothUuid::CharacteristicUserDescription)
descData.value = byteArrayFromGattResult(descriptorValue, true);
else
descData.value = byteArrayFromGattResult(descriptorValue);
- charData.descriptorList.insert(descHandle, descData);
+ service->characteristicList[charHandle].descriptorList[descHandle] = descData;
emit service->descriptorRead(QLowEnergyDescriptor(service, charHandle, descHandle),
descData.value);
return S_OK;
@@ -895,6 +889,8 @@ void QLowEnergyControllerPrivateWinRT::writeCharacteristic(const QSharedPointer<
QLowEnergyService::WriteMode mode)
{
qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << newValue << mode;
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+ << QThread::currentThread();
Q_ASSERT(!service.isNull());
if (role == QLowEnergyController::PeripheralRole) {
service->setError(QLowEnergyService::CharacteristicWriteError);
@@ -985,6 +981,8 @@ void QLowEnergyControllerPrivateWinRT::writeDescriptor(
const QByteArray &newValue)
{
qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << descHandle << newValue;
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+ << QThread::currentThread();
Q_ASSERT(!service.isNull());
if (role == QLowEnergyController::PeripheralRole) {
service->setError(QLowEnergyService::DescriptorWriteError);
@@ -1128,9 +1126,12 @@ void QLowEnergyControllerPrivateWinRT::addToGenericAttributeList(const QLowEnerg
Q_UNIMPLEMENTED();
}
-void QLowEnergyControllerPrivateWinRT::characteristicChanged(
- int charHandle, const QByteArray &data)
+void QLowEnergyControllerPrivateWinRT::handleCharacteristicChanged(
+ quint16 charHandle, const QByteArray &data)
{
+ qCDebug(QT_BT_WINRT) << __FUNCTION__ << charHandle << data;
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+ << QThread::currentThread();
QSharedPointer<QLowEnergyServicePrivate> service =
serviceForHandle(charHandle);
if (service.isNull())
diff --git a/src/bluetooth/qlowenergycontroller_winrt_new.cpp b/src/bluetooth/qlowenergycontroller_winrt_new.cpp
index 1f70807e..a22064fd 100644
--- a/src/bluetooth/qlowenergycontroller_winrt_new.cpp
+++ b/src/bluetooth/qlowenergycontroller_winrt_new.cpp
@@ -39,7 +39,9 @@
#include "qlowenergycontroller_winrt_new_p.h"
#include "qlowenergycontroller_winrt_p.h"
+#include "qbluetoothutils_winrt_p.h"
+#include <QtBluetooth/qbluetoothlocaldevice.h>
#include <QtBluetooth/QLowEnergyCharacteristicData>
#include <QtBluetooth/QLowEnergyDescriptorData>
#include <QtBluetooth/private/qbluetoothutils_winrt_p.h>
@@ -56,6 +58,7 @@
#include <robuffer.h>
#include <windows.devices.enumeration.h>
#include <windows.devices.bluetooth.h>
+#include <windows.devices.bluetooth.genericattributeprofile.h>
#include <windows.foundation.collections.h>
#include <windows.foundation.metadata.h>
#include <windows.storage.streams.h>
@@ -78,7 +81,39 @@ typedef ITypedEventHandler<GattCharacteristic *, GattValueChangedEventArgs *> Va
typedef GattReadClientCharacteristicConfigurationDescriptorResult ClientCharConfigDescriptorResult;
typedef IGattReadClientCharacteristicConfigurationDescriptorResult IClientCharConfigDescriptorResult;
+#define EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr, ret) \
+ if (FAILED(hr)) { \
+ emitErrorAndQuitThread(hr); \
+ ret; \
+ }
+
+#define WARN_AND_CONTINUE_IF_FAILED(hr, msg) \
+ if (FAILED(hr)) { \
+ qCWarning(QT_BT_WINRT) << msg; \
+ continue; \
+ }
+
+#define CHECK_FOR_DEVICE_CONNECTION_ERROR_IMPL(this, hr, msg, ret) \
+ if (FAILED(hr)) { \
+ qCWarning(QT_BT_WINRT) << msg; \
+ this->unregisterFromStatusChanges(); \
+ this->setError(QLowEnergyController::ConnectionError); \
+ this->setState(QLowEnergyController::UnconnectedState); \
+ ret; \
+ }
+
+#define CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, msg, ret) \
+ CHECK_FOR_DEVICE_CONNECTION_ERROR_IMPL(this, hr, msg, ret)
+
+#define CHECK_HR_AND_SET_SERVICE_ERROR(hr, msg, service, error, ret) \
+ if (FAILED(hr)) { \
+ qCDebug(QT_BT_WINRT) << msg; \
+ service->setError(error); \
+ ret; \
+ }
+
Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT)
+Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT_SERVICE_THREAD)
QLowEnergyControllerPrivate *createWinRTLowEnergyController()
{
@@ -91,31 +126,16 @@ QLowEnergyControllerPrivate *createWinRTLowEnergyController()
return new QLowEnergyControllerPrivateWinRT();
}
-static QByteArray byteArrayFromBuffer(const ComPtr<IBuffer> &buffer, bool isWCharString = false)
-{
- ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteAccess;
- HRESULT hr = buffer.As(&byteAccess);
- Q_ASSERT_SUCCEEDED(hr);
- char *data;
- hr = byteAccess->Buffer(reinterpret_cast<byte **>(&data));
- Q_ASSERT_SUCCEEDED(hr);
- UINT32 size;
- hr = buffer->get_Length(&size);
- Q_ASSERT_SUCCEEDED(hr);
- if (isWCharString) {
- QString valueString = QString::fromUtf16(reinterpret_cast<ushort *>(data)).left(size / 2);
- return valueString.toUtf8();
- }
- return QByteArray(data, int(size));
-}
-
static QByteArray byteArrayFromGattResult(const ComPtr<IGattReadResult> &gattResult,
bool isWCharString = false)
{
ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer;
HRESULT hr;
hr = gattResult->get_Value(&buffer);
- Q_ASSERT_SUCCEEDED(hr);
+ if (FAILED(hr) || !buffer) {
+ qCWarning(QT_BT_WINRT) << "Could not obtain buffer from GattReadResult";
+ return QByteArray();
+ }
return byteArrayFromBuffer(buffer, isWCharString);
}
@@ -124,7 +144,7 @@ class QWinRTLowEnergyServiceHandlerNew : public QObject
Q_OBJECT
public:
QWinRTLowEnergyServiceHandlerNew(const QBluetoothUuid &service,
- const ComPtr<IGattDeviceService2> &deviceService)
+ const ComPtr<IGattDeviceService3> &deviceService)
: mService(service)
, mDeviceService(deviceService)
{
@@ -138,58 +158,47 @@ public:
public slots:
void obtainCharList()
{
- QVector<QBluetoothUuid> indicateChars;
- quint16 startHandle = 0;
- quint16 endHandle = 0;
+ mIndicateChars.clear();
qCDebug(QT_BT_WINRT) << __FUNCTION__;
- ComPtr<IVectorView<GattCharacteristic *>> characteristics;
- HRESULT hr = mDeviceService->GetAllCharacteristics(&characteristics);
- Q_ASSERT_SUCCEEDED(hr);
- if (!characteristics) {
- emit charListObtained(mService, mCharacteristicList, indicateChars, startHandle, endHandle);
- QThread::currentThread()->quit();
+ ComPtr<IAsyncOperation<GattCharacteristicsResult *>> characteristicsOp;
+ ComPtr<IGattCharacteristicsResult> characteristicsResult;
+ HRESULT hr = mDeviceService->GetCharacteristicsAsync(&characteristicsOp);
+ EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr, return);
+ hr = QWinRTFunctions::await(characteristicsOp, characteristicsResult.GetAddressOf(),
+ QWinRTFunctions::ProcessMainThreadEvents, 5000);
+ EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr, return);
+ GattCommunicationStatus status;
+ hr = characteristicsResult->get_Status(&status);
+ EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr, return);
+ if (status != GattCommunicationStatus_Success) {
+ emitErrorAndQuitThread(QLatin1String("Could not obtain char list"));
return;
}
+ ComPtr<IVectorView<GattCharacteristic *>> characteristics;
+ hr = characteristicsResult->get_Characteristics(&characteristics);
+ EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr, return);
uint characteristicsCount;
hr = characteristics->get_Size(&characteristicsCount);
+ EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr, return);
- // If there are no characteristics, we assume that the device is not paired (and not
- // discovered by Windows) and we use new API (GetCharacteristicsAsync) to discover them
- // without pairing.
- if (characteristicsCount == 0) {
- ComPtr<IGattDeviceService3> deviceService3;
- hr = mDeviceService.As(&deviceService3);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IAsyncOperation<GattCharacteristicsResult*>> asyncResult;
- deviceService3->GetCharacteristicsAsync(&asyncResult);
- hr = asyncResult->put_Completed(
- Callback<IAsyncOperationCompletedHandler<GattCharacteristicsResult*>>(
- [this](IAsyncOperation<GattCharacteristicsResult*> *, AsyncStatus status) {
- if (status != AsyncStatus::Completed) {
- qCDebug(QT_BT_WINRT) << "Could not obtain characteristics";
- return S_OK;
- }
- // TODO We should check if we found any characteristics. It makes no sense but
- // there is a possibility that device doesn't state any characteristics under a service.
- // So, for sanity, we should not continue endless loop here.
- obtainCharList();
- return S_OK;
- }).Get());
- Q_ASSERT_SUCCEEDED(hr);
- return;
- }
-
- Q_ASSERT_SUCCEEDED(hr);
mCharacteristicsCountToBeDiscovered = characteristicsCount;
for (uint i = 0; i < characteristicsCount; ++i) {
ComPtr<IGattCharacteristic> characteristic;
hr = characteristics->GetAt(i, &characteristic);
- Q_ASSERT_SUCCEEDED(hr);
+ if (FAILED(hr)) {
+ qCWarning(QT_BT_WINRT) << "Could not obtain characteristic at" << i;
+ --mCharacteristicsCountToBeDiscovered;
+ continue;
+ }
ComPtr<IGattCharacteristic3> characteristic3;
hr = characteristic.As(&characteristic3);
- Q_ASSERT_SUCCEEDED(hr);
+ if (FAILED(hr)) {
+ qCWarning(QT_BT_WINRT) << "Could not cast characteristic";
+ --mCharacteristicsCountToBeDiscovered;
+ continue;
+ }
// For some strange reason, Windows doesn't discover descriptors of characteristics (if not paired).
// Qt API assumes that all characteristics and their descriptors are discovered in one go.
@@ -197,157 +206,246 @@ public slots:
// when GetDescriptorsAsync for all characteristics return.
ComPtr<IAsyncOperation<GattDescriptorsResult*>> descAsyncResult;
hr = characteristic3->GetDescriptorsAsync(&descAsyncResult);
- Q_ASSERT_SUCCEEDED(hr);
+ if (FAILED(hr)) {
+ qCWarning(QT_BT_WINRT) << "Could not obtain list of descriptors";
+ --mCharacteristicsCountToBeDiscovered;
+ continue;
+ }
hr = descAsyncResult->put_Completed(
- Callback<IAsyncOperationCompletedHandler<GattDescriptorsResult*>>(
- [this, characteristic](IAsyncOperation<GattDescriptorsResult*> *, AsyncStatus status) {
- if (status != AsyncStatus::Completed) {
- qCDebug(QT_BT_WINRT) << "Could not obtain descriptors";
+ Callback<IAsyncOperationCompletedHandler<GattDescriptorsResult*>>(
+ [this, characteristic]
+ (IAsyncOperation<GattDescriptorsResult *> *op,
+ AsyncStatus status) {
+ if (status != AsyncStatus::Completed) {
+ qCWarning(QT_BT_WINRT) << "Descriptor operation unsuccessful";
+ --mCharacteristicsCountToBeDiscovered;
+ checkAllCharacteristicsDiscovered();
+ return S_OK;
+ }
+ quint16 handle;
+
+ HRESULT hr = characteristic->get_AttributeHandle(&handle);
+ if (FAILED(hr)) {
+ qCWarning(QT_BT_WINRT) << "Could not obtain characteristic's attribute handle";
+ --mCharacteristicsCountToBeDiscovered;
+ checkAllCharacteristicsDiscovered();
+ return S_OK;
+ }
+ QLowEnergyServicePrivate::CharData charData;
+ charData.valueHandle = handle + 1;
+ if (mStartHandle == 0 || mStartHandle > handle)
+ mStartHandle = handle;
+ if (mEndHandle == 0 || mEndHandle < handle)
+ mEndHandle = handle;
+ GUID guuid;
+ hr = characteristic->get_Uuid(&guuid);
+ if (FAILED(hr)) {
+ qCWarning(QT_BT_WINRT) << "Could not obtain characteristic's Uuid";
+ --mCharacteristicsCountToBeDiscovered;
+ checkAllCharacteristicsDiscovered();
+ return S_OK;
+ }
+ charData.uuid = QBluetoothUuid(guuid);
+ GattCharacteristicProperties properties;
+ hr = characteristic->get_CharacteristicProperties(&properties);
+ if (FAILED(hr)) {
+ qCWarning(QT_BT_WINRT) << "Could not obtain characteristic's properties";
+ --mCharacteristicsCountToBeDiscovered;
+ checkAllCharacteristicsDiscovered();
+ return S_OK;
+ }
+ charData.properties = QLowEnergyCharacteristic::PropertyTypes(properties & 0xff);
+ if (charData.properties & QLowEnergyCharacteristic::Read) {
+ ComPtr<IAsyncOperation<GattReadResult *>> readOp;
+ hr = characteristic->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached,
+ &readOp);
+ if (FAILED(hr)) {
+ qCWarning(QT_BT_WINRT) << "Could not read characteristic";
+ --mCharacteristicsCountToBeDiscovered;
+ checkAllCharacteristicsDiscovered();
return S_OK;
}
- quint16 handle;
-
- HRESULT hr = characteristic->get_AttributeHandle(&handle);
- Q_ASSERT_SUCCEEDED(hr);
- QLowEnergyServicePrivate::CharData charData;
- charData.valueHandle = handle + 1;
- if (mStartHandle == 0 || mStartHandle > handle)
- mStartHandle = handle;
- if (mEndHandle == 0 || mEndHandle < handle)
- mEndHandle = handle;
- GUID guuid;
- hr = characteristic->get_Uuid(&guuid);
- Q_ASSERT_SUCCEEDED(hr);
- charData.uuid = QBluetoothUuid(guuid);
- GattCharacteristicProperties properties;
- hr = characteristic->get_CharacteristicProperties(&properties);
- Q_ASSERT_SUCCEEDED(hr);
- charData.properties = QLowEnergyCharacteristic::PropertyTypes(properties & 0xff);
- if (charData.properties & QLowEnergyCharacteristic::Read) {
- ComPtr<IAsyncOperation<GattReadResult *>> readOp;
- hr = characteristic->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached,
- &readOp);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IGattReadResult> readResult;
- hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf());
- Q_ASSERT_SUCCEEDED(hr);
- if (readResult)
- charData.value = byteArrayFromGattResult(readResult);
+ ComPtr<IGattReadResult> readResult;
+ hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf());
+ if (FAILED(hr)) {
+ qCWarning(QT_BT_WINRT) << "Could not obtain characteristic read result";
+ --mCharacteristicsCountToBeDiscovered;
+ checkAllCharacteristicsDiscovered();
+ return S_OK;
}
+ if (!readResult)
+ qCWarning(QT_BT_WINRT) << "Characteristic read result is null";
+ else
+ charData.value = byteArrayFromGattResult(readResult);
+ }
+ mCharacteristicList.insert(handle, charData);
- QVector<QBluetoothUuid> indicateChars;
- ComPtr<IVectorView<GattDescriptor *>> descriptors;
-
- ComPtr<IGattCharacteristic2> characteristic2;
- hr = characteristic.As(&characteristic2);
- Q_ASSERT_SUCCEEDED(hr);
-
- hr = characteristic2->GetAllDescriptors(&descriptors);
- Q_ASSERT_SUCCEEDED(hr);
-
-
- uint descriptorCount;
- hr = descriptors->get_Size(&descriptorCount);
- Q_ASSERT_SUCCEEDED(hr);
- for (uint j = 0; j < descriptorCount; ++j) {
- QLowEnergyServicePrivate::DescData descData;
- ComPtr<IGattDescriptor> descriptor;
- hr = descriptors->GetAt(j, &descriptor);
- Q_ASSERT_SUCCEEDED(hr);
- quint16 descHandle;
- hr = descriptor->get_AttributeHandle(&descHandle);
- Q_ASSERT_SUCCEEDED(hr);
- GUID descriptorUuid;
- hr = descriptor->get_Uuid(&descriptorUuid);
- Q_ASSERT_SUCCEEDED(hr);
- descData.uuid = QBluetoothUuid(descriptorUuid);
- if (descData.uuid == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) {
- ComPtr<IAsyncOperation<ClientCharConfigDescriptorResult *>> readOp;
- hr = characteristic->ReadClientCharacteristicConfigurationDescriptorAsync(&readOp);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IClientCharConfigDescriptorResult> readResult;
- hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf());
- Q_ASSERT_SUCCEEDED(hr);
- GattClientCharacteristicConfigurationDescriptorValue value;
- hr = readResult->get_ClientCharacteristicConfigurationDescriptor(&value);
- Q_ASSERT_SUCCEEDED(hr);
- quint16 result = 0;
- bool correct = false;
- if (value & GattClientCharacteristicConfigurationDescriptorValue_Indicate) {
- result |= GattClientCharacteristicConfigurationDescriptorValue_Indicate;
- correct = true;
- }
- if (value & GattClientCharacteristicConfigurationDescriptorValue_Notify) {
- result |= GattClientCharacteristicConfigurationDescriptorValue_Notify;
- correct = true;
- }
- if (value == GattClientCharacteristicConfigurationDescriptorValue_None) {
- correct = true;
- }
- if (!correct)
- continue;
-
- descData.value = QByteArray(2, Qt::Uninitialized);
- qToLittleEndian(result, descData.value.data());
- indicateChars << charData.uuid;
- } else {
- ComPtr<IAsyncOperation<GattReadResult *>> readOp;
- hr = descriptor->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached,
- &readOp);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IGattReadResult> readResult;
- hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf());
- Q_ASSERT_SUCCEEDED(hr);
- if (descData.uuid == QBluetoothUuid::CharacteristicUserDescription)
- descData.value = byteArrayFromGattResult(readResult, true);
- else
- descData.value = byteArrayFromGattResult(readResult);
+ ComPtr<IVectorView<GattDescriptor *>> descriptors;
+
+ ComPtr<IGattDescriptorsResult> result;
+ hr = op->GetResults(&result);
+ if (FAILED(hr)) {
+ qCWarning(QT_BT_WINRT) << "Could not obtain descriptor read result";
+ --mCharacteristicsCountToBeDiscovered;
+ checkAllCharacteristicsDiscovered();
+ return S_OK;
+ }
+ GattCommunicationStatus commStatus;
+ hr = result->get_Status(&commStatus);
+ if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
+ qCWarning(QT_BT_WINRT) << "Descriptor operation failed";
+ --mCharacteristicsCountToBeDiscovered;
+ checkAllCharacteristicsDiscovered();
+ return S_OK;
+ }
+
+ hr = result->get_Descriptors(&descriptors);
+ if (FAILED(hr)) {
+ qCWarning(QT_BT_WINRT) << "Could not obtain list of descriptors";
+ --mCharacteristicsCountToBeDiscovered;
+ checkAllCharacteristicsDiscovered();
+ return S_OK;
+ }
+
+ uint descriptorCount;
+ hr = descriptors->get_Size(&descriptorCount);
+ if (FAILED(hr)) {
+ qCWarning(QT_BT_WINRT) << "Could not obtain list of descriptors' size";
+ --mCharacteristicsCountToBeDiscovered;
+ checkAllCharacteristicsDiscovered();
+ return S_OK;
+ }
+ for (uint j = 0; j < descriptorCount; ++j) {
+ QLowEnergyServicePrivate::DescData descData;
+ ComPtr<IGattDescriptor> descriptor;
+ hr = descriptors->GetAt(j, &descriptor);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain descriptor")
+ quint16 descHandle;
+ hr = descriptor->get_AttributeHandle(&descHandle);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain descriptor's attribute handle")
+ GUID descriptorUuid;
+ hr = descriptor->get_Uuid(&descriptorUuid);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain descriptor's Uuid")
+ descData.uuid = QBluetoothUuid(descriptorUuid);
+ charData.descriptorList.insert(descHandle, descData);
+ if (descData.uuid == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) {
+ ComPtr<IAsyncOperation<ClientCharConfigDescriptorResult *>> readOp;
+ hr = characteristic->ReadClientCharacteristicConfigurationDescriptorAsync(&readOp);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not read descriptor value")
+ ComPtr<IClientCharConfigDescriptorResult> readResult;
+ hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf());
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not await descriptor read result")
+ GattClientCharacteristicConfigurationDescriptorValue value;
+ hr = readResult->get_ClientCharacteristicConfigurationDescriptor(&value);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not get descriptor value from result")
+ quint16 result = 0;
+ bool correct = false;
+ if (value & GattClientCharacteristicConfigurationDescriptorValue_Indicate) {
+ result |= GattClientCharacteristicConfigurationDescriptorValue_Indicate;
+ correct = true;
}
- charData.descriptorList.insert(descHandle, descData);
- }
+ if (value & GattClientCharacteristicConfigurationDescriptorValue_Notify) {
+ result |= GattClientCharacteristicConfigurationDescriptorValue_Notify;
+ correct = true;
+ }
+ if (value == GattClientCharacteristicConfigurationDescriptorValue_None) {
+ correct = true;
+ }
+ if (!correct)
+ continue;
- mCharacteristicList.insert(handle, charData);
- mCharacteristicsCountToBeDiscovered--;
- if (mCharacteristicsCountToBeDiscovered == 0) {
- emit charListObtained(mService, mCharacteristicList, indicateChars,
- mStartHandle, mEndHandle);
- QThread::currentThread()->quit();
+ descData.value = QByteArray(2, Qt::Uninitialized);
+ qToLittleEndian(result, descData.value.data());
+ mIndicateChars << charData.uuid;
+ } else {
+ ComPtr<IAsyncOperation<GattReadResult *>> readOp;
+ hr = descriptor->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached,
+ &readOp);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not read descriptor value")
+ ComPtr<IGattReadResult> readResult;
+ hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf());
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could await descriptor read result")
+ if (descData.uuid == QBluetoothUuid::CharacteristicUserDescription)
+ descData.value = byteArrayFromGattResult(readResult, true);
+ else
+ descData.value = byteArrayFromGattResult(readResult);
}
- return S_OK;
- }).Get());
- Q_ASSERT_SUCCEEDED(hr);
+ charData.descriptorList.insert(descHandle, descData);
+ }
+
+ mCharacteristicList.insert(handle, charData);
+ --mCharacteristicsCountToBeDiscovered;
+ checkAllCharacteristicsDiscovered();
+ return S_OK;
+ }).Get());
+ if (FAILED(hr)) {
+ qCWarning(QT_BT_WINRT) << "Could not register descriptor callback";
+ --mCharacteristicsCountToBeDiscovered;
+ continue;
+ }
}
+ checkAllCharacteristicsDiscovered();
}
+private:
+ bool checkAllCharacteristicsDiscovered();
+ void emitErrorAndQuitThread(HRESULT hr);
+ void emitErrorAndQuitThread(const QString &error);
+
public:
QBluetoothUuid mService;
- ComPtr<IGattDeviceService2> mDeviceService;
+ ComPtr<IGattDeviceService3> mDeviceService;
QHash<QLowEnergyHandle, QLowEnergyServicePrivate::CharData> mCharacteristicList;
uint mCharacteristicsCountToBeDiscovered;
quint16 mStartHandle = 0;
quint16 mEndHandle = 0;
+ QVector<QBluetoothUuid> mIndicateChars;
signals:
void charListObtained(const QBluetoothUuid &service, QHash<QLowEnergyHandle,
QLowEnergyServicePrivate::CharData> charList,
QVector<QBluetoothUuid> indicateChars,
QLowEnergyHandle startHandle, QLowEnergyHandle endHandle);
+ void errorOccured(const QString &error);
};
+bool QWinRTLowEnergyServiceHandlerNew::checkAllCharacteristicsDiscovered()
+{
+ if (mCharacteristicsCountToBeDiscovered == 0) {
+ emit charListObtained(mService, mCharacteristicList, mIndicateChars,
+ mStartHandle, mEndHandle);
+ QThread::currentThread()->quit();
+ return true;
+ }
+
+ return false;
+}
+
+void QWinRTLowEnergyServiceHandlerNew::emitErrorAndQuitThread(HRESULT hr)
+{
+ emitErrorAndQuitThread(qt_error_string(hr));
+}
+
+void QWinRTLowEnergyServiceHandlerNew::emitErrorAndQuitThread(const QString &error)
+{
+ emit errorOccured(error);
+ QThread::currentThread()->quit();
+}
+
QLowEnergyControllerPrivateWinRTNew::QLowEnergyControllerPrivateWinRTNew()
: QLowEnergyControllerPrivate()
{
registerQLowEnergyControllerMetaType();
+ connect(this, &QLowEnergyControllerPrivateWinRTNew::characteristicChanged,
+ this, &QLowEnergyControllerPrivateWinRTNew::handleCharacteristicChanged,
+ Qt::QueuedConnection);
}
QLowEnergyControllerPrivateWinRTNew::~QLowEnergyControllerPrivateWinRTNew()
{
- if (mDevice && mStatusChangedToken.value)
- mDevice->remove_ConnectionStatusChanged(mStatusChangedToken);
-
- qCDebug(QT_BT_WINRT) << "Unregistering " << mValueChangedTokens.count() << " value change tokens";
- for (const ValueChangedEntry &entry : qAsConst(mValueChangedTokens))
- entry.characteristic->remove_ValueChanged(entry.token);
+ unregisterFromStatusChanges();
+ unregisterFromValueChanges();
+ mAbortPending = true;
}
void QLowEnergyControllerPrivateWinRTNew::init()
@@ -357,6 +455,7 @@ void QLowEnergyControllerPrivateWinRTNew::init()
void QLowEnergyControllerPrivateWinRTNew::connectToDevice()
{
qCDebug(QT_BT_WINRT) << __FUNCTION__;
+ mAbortPending = false;
Q_Q(QLowEnergyController);
if (remoteDevice.isNull()) {
qWarning() << "Invalid/null remote device address";
@@ -370,162 +469,46 @@ void QLowEnergyControllerPrivateWinRTNew::connectToDevice()
HRESULT hr = GetActivationFactory(
HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_BluetoothLEDevice).Get(),
&deviceStatics);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain device factory", return)
ComPtr<IAsyncOperation<BluetoothLEDevice *>> deviceFromIdOperation;
hr = deviceStatics->FromBluetoothAddressAsync(remoteDevice.toUInt64(), &deviceFromIdOperation);
- Q_ASSERT_SUCCEEDED(hr);
- hr = QWinRTFunctions::await(deviceFromIdOperation, mDevice.GetAddressOf());
- Q_ASSERT_SUCCEEDED(hr);
-
- if (!mDevice) {
- qCDebug(QT_BT_WINRT) << "Could not find LE device";
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not find LE device from address", return)
+ hr = QWinRTFunctions::await(deviceFromIdOperation, mDevice.GetAddressOf(),
+ QWinRTFunctions::ProcessMainThreadEvents, 5000);
+ if (FAILED(hr) || !mDevice) {
+ qCWarning(QT_BT_WINRT) << "Could not find LE device";
setError(QLowEnergyController::InvalidBluetoothAdapterError);
setState(QLowEnergyController::UnconnectedState);
+ return;
}
BluetoothConnectionStatus status;
hr = mDevice->get_ConnectionStatus(&status);
- Q_ASSERT_SUCCEEDED(hr);
- hr = QEventDispatcherWinRT::runOnXamlThread([this, q]() {
- HRESULT hr;
- hr = mDevice->add_ConnectionStatusChanged(
- Callback<StatusHandler>([this, q](IBluetoothLEDevice *dev, IInspectable *) {
- BluetoothConnectionStatus status;
- HRESULT hr;
- hr = dev->get_ConnectionStatus(&status);
- Q_ASSERT_SUCCEEDED(hr);
- if (state == QLowEnergyController::ConnectingState
- && status == BluetoothConnectionStatus::BluetoothConnectionStatus_Connected) {
- setState(QLowEnergyController::ConnectedState);
- emit q->connected();
- } else if (state == QLowEnergyController::ConnectedState
- && status == BluetoothConnectionStatus::BluetoothConnectionStatus_Disconnected) {
- setError(QLowEnergyController::RemoteHostClosedError);
- setState(QLowEnergyController::UnconnectedState);
- emit q->disconnected();
- }
- return S_OK;
- }).Get(), &mStatusChangedToken);
- Q_ASSERT_SUCCEEDED(hr);
- return S_OK;
- });
- Q_ASSERT_SUCCEEDED(hr);
-
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain device's connection status", return)
if (status == BluetoothConnectionStatus::BluetoothConnectionStatus_Connected) {
setState(QLowEnergyController::ConnectedState);
emit q->connected();
return;
}
- ComPtr<IVectorView <GattDeviceService *>> deviceServices;
- hr = mDevice->get_GattServices(&deviceServices);
- Q_ASSERT_SUCCEEDED(hr);
- uint serviceCount;
- hr = deviceServices->get_Size(&serviceCount);
- Q_ASSERT_SUCCEEDED(hr);
-
- // Windows doesn't provide any explicit connect/reconnect. We need to 'start using' the device
- // and windows will initiate connection as a cause of that.
- if (serviceCount == 0) {
- // If we don't have any services discovered yet (for devices not paired), the simplest
- // way to initiate connect is to start discovering services. It's not exactly how Qt API
- // expects it to be but IMHO doesn't do any harm either. Services will already be discovered
- // when coonnection state changes to 'connected'.
- ComPtr<IBluetoothLEDevice3> device3;
- hr = mDevice.As(&device3);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IAsyncOperation<GenericAttributeProfile::GattDeviceServicesResult *>> asyncResult;
- hr = device3->GetGattServicesAsync(&asyncResult);
- Q_ASSERT_SUCCEEDED(hr);
- hr = asyncResult->put_Completed(
- Callback<IAsyncOperationCompletedHandler<GenericAttributeProfile::GattDeviceServicesResult *>>(
- [this, q](IAsyncOperation<GenericAttributeProfile::GattDeviceServicesResult *> *, AsyncStatus status) {
- if (status != AsyncStatus::Completed) {
- qCDebug(QT_BT_WINRT) << "Could not obtain services";
- return S_OK;
- }
- setState(QLowEnergyController::ConnectedState);
- emit q->connected();
- return S_OK;
- }).Get());
- Q_ASSERT_SUCCEEDED(hr);
- } else {
- // Windows Phone automatically connects to the device as soon as a service value is read/written.
- // Thus we read one value in order to establish the connection.
- for (uint i = 0; i < serviceCount; ++i) {
- ComPtr<IGattDeviceService> service;
- hr = deviceServices->GetAt(i, &service);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IGattDeviceService2> service2;
- hr = service.As(&service2);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IVectorView<GattCharacteristic *>> characteristics;
- hr = service2->GetAllCharacteristics(&characteristics);
- if (hr == E_ACCESSDENIED) {
- // Everything will work as expected up until this point if the manifest capabilties
- // for bluetooth LE are not set.
- qCWarning(QT_BT_WINRT) << "Could not obtain characteristic list. Please check your "
- "manifest capabilities";
- setState(QLowEnergyController::UnconnectedState);
- setError(QLowEnergyController::ConnectionError);
- return;
- } else if (FAILED(hr)) {
- qCWarning(QT_BT_WINRT) << "Connecting to device failed: "
- << qt_error_string(hr);
- setError(QLowEnergyController::ConnectionError);
- setState(QLowEnergyController::UnconnectedState);
- return;
- }
- uint characteristicsCount;
- hr = characteristics->get_Size(&characteristicsCount);
- Q_ASSERT_SUCCEEDED(hr);
- for (uint j = 0; j < characteristicsCount; ++j) {
- ComPtr<IGattCharacteristic> characteristic;
- hr = characteristics->GetAt(j, &characteristic);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IAsyncOperation<GattReadResult *>> op;
- GattCharacteristicProperties props;
- hr = characteristic->get_CharacteristicProperties(&props);
- Q_ASSERT_SUCCEEDED(hr);
- if (!(props & GattCharacteristicProperties_Read))
- continue;
- hr = characteristic->ReadValueWithCacheModeAsync(BluetoothCacheMode::BluetoothCacheMode_Uncached, &op);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IGattReadResult> result;
- hr = QWinRTFunctions::await(op, result.GetAddressOf());
- if (hr == E_INVALIDARG) {
- // E_INVALIDARG happens when user tries to connect to a device that was paired
- // before but is not available.
- qCDebug(QT_BT_WINRT) << "Could not obtain characteristic read result that triggers"
- "device connection. Is the device reachable?";
- setError(QLowEnergyController::ConnectionError);
- setState(QLowEnergyController::UnconnectedState);
- return;
- }
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer;
- hr = result->get_Value(&buffer);
- Q_ASSERT_SUCCEEDED(hr);
- if (!buffer) {
- qCDebug(QT_BT_WINRT) << "Problem reading value";
- setError(QLowEnergyController::ConnectionError);
- setState(QLowEnergyController::UnconnectedState);
- }
- return;
- }
- }
- }
+ QBluetoothLocalDevice localDevice;
+ QBluetoothLocalDevice::Pairing pairing = localDevice.pairingStatus(remoteDevice);
+ if (pairing == QBluetoothLocalDevice::Unpaired)
+ connectToUnpairedDevice();
+ else
+ connectToPairedDevice();
}
void QLowEnergyControllerPrivateWinRTNew::disconnectFromDevice()
{
qCDebug(QT_BT_WINRT) << __FUNCTION__;
Q_Q(QLowEnergyController);
+ setState(QLowEnergyController::ClosingState);
+ unregisterFromValueChanges();
+ unregisterFromStatusChanges();
+ mAbortPending = true;
+ mDevice = nullptr;
setState(QLowEnergyController::UnconnectedState);
emit q->disconnected();
- if (mDevice && mStatusChangedToken.value) {
- mDevice->remove_ConnectionStatusChanged(mStatusChangedToken);
- mStatusChangedToken.value = 0;
- }
}
ComPtr<IGattDeviceService> QLowEnergyControllerPrivateWinRTNew::getNativeService(
@@ -546,9 +529,30 @@ ComPtr<IGattCharacteristic> QLowEnergyControllerPrivateWinRTNew::getNativeCharac
if (!service)
return nullptr;
- ComPtr<IVectorView<GattCharacteristic *>> characteristics;
- HRESULT hr = service->GetCharacteristics(charUuid, &characteristics);
+ ComPtr<IGattDeviceService3> service3;
+ HRESULT hr = service.As(&service3);
+ RETURN_IF_FAILED("Could not cast service", return nullptr);
+
+ ComPtr<IAsyncOperation<GattCharacteristicsResult *>> op;
+ ComPtr<IGattCharacteristicsResult> result;
+ hr = service3->GetCharacteristicsForUuidAsync(charUuid, &op);
RETURN_IF_FAILED("Could not obtain native characteristics for service", return nullptr);
+ hr = QWinRTFunctions::await(op, result.GetAddressOf(), QWinRTFunctions::ProcessMainThreadEvents, 5000);
+ RETURN_IF_FAILED("Could not await completion of characteristic operation", return nullptr);
+ GattCommunicationStatus status;
+ hr = result->get_Status(&status);
+ if (FAILED(hr) || status != GattCommunicationStatus_Success) {
+ qErrnoWarning(hr, "Native characteristic operation failed.");
+ return nullptr;
+ }
+ ComPtr<IVectorView<GattCharacteristic *>> characteristics;
+ hr = result->get_Characteristics(&characteristics);
+ RETURN_IF_FAILED("Could not obtain characteristic list.", return nullptr);
+ uint size;
+ hr = characteristics->get_Size(&size);
+ RETURN_IF_FAILED("Could not obtain characteristic list's size.", return nullptr);
+ if (size != 1)
+ qErrnoWarning("More than 1 characteristic found.");
ComPtr<IGattCharacteristic> characteristic;
hr = characteristics->GetAt(0, &characteristic);
RETURN_IF_FAILED("Could not obtain first characteristic for service", return nullptr);
@@ -564,59 +568,152 @@ void QLowEnergyControllerPrivateWinRTNew::registerForValueChanges(const QBluetoo
GUID guuid;
HRESULT hr;
hr = entry.characteristic->get_Uuid(&guuid);
- Q_ASSERT_SUCCEEDED(hr);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain characteristic's Uuid")
if (QBluetoothUuid(guuid) == charUuid)
return;
}
ComPtr<IGattCharacteristic> characteristic = getNativeCharacteristic(serviceUuid, charUuid);
+ if (!characteristic) {
+ qCDebug(QT_BT_WINRT).nospace() << "Could not obtain native characteristic " << charUuid
+ << " from service " << serviceUuid << ". Qt will not be able to signal"
+ << " changes for this characteristic.";
+ return;
+ }
EventRegistrationToken token;
HRESULT hr;
hr = characteristic->add_ValueChanged(
- Callback<ValueChangedHandler>(
- [this](IGattCharacteristic *characteristic, IGattValueChangedEventArgs *args) {
- HRESULT hr;
- quint16 handle;
- hr = characteristic->get_AttributeHandle(&handle);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IBuffer> buffer;
- hr = args->get_CharacteristicValue(&buffer);
- Q_ASSERT_SUCCEEDED(hr);
- characteristicChanged(handle, byteArrayFromBuffer(buffer));
- return S_OK;
- }).Get(), &token);
- Q_ASSERT_SUCCEEDED(hr);
+ Callback<ValueChangedHandler>(this, &QLowEnergyControllerPrivateWinRTNew::onValueChange).Get(),
+ &token);
+ RETURN_IF_FAILED("Could not register characteristic for value changes", return)
mValueChangedTokens.append(ValueChangedEntry(characteristic, token));
qCDebug(QT_BT_WINRT) << "Characteristic" << charUuid << "in service"
<< serviceUuid << "registered for value changes";
}
+void QLowEnergyControllerPrivateWinRTNew::unregisterFromValueChanges()
+{
+ qCDebug(QT_BT_WINRT) << "Unregistering " << mValueChangedTokens.count() << " value change tokens";
+ HRESULT hr;
+ for (const ValueChangedEntry &entry : qAsConst(mValueChangedTokens)) {
+ if (!entry.characteristic) {
+ qCWarning(QT_BT_WINRT) << "Unregistering from value changes for characteristic failed."
+ << "Characteristic has been deleted";
+ continue;
+ }
+ hr = entry.characteristic->remove_ValueChanged(entry.token);
+ if (FAILED(hr))
+ qCWarning(QT_BT_WINRT) << "Unregistering from value changes for characteristic failed.";
+ }
+ mValueChangedTokens.clear();
+}
+
+HRESULT QLowEnergyControllerPrivateWinRTNew::onValueChange(IGattCharacteristic *characteristic, IGattValueChangedEventArgs *args)
+{
+ HRESULT hr;
+ quint16 handle;
+ hr = characteristic->get_AttributeHandle(&handle);
+ RETURN_IF_FAILED("Could not obtain characteristic's handle", return S_OK)
+ ComPtr<IBuffer> buffer;
+ hr = args->get_CharacteristicValue(&buffer);
+ RETURN_IF_FAILED("Could not obtain characteristic's value", return S_OK)
+ emit characteristicChanged(handle, byteArrayFromBuffer(buffer));
+ return S_OK;
+}
+
+bool QLowEnergyControllerPrivateWinRTNew::registerForStatusChanges()
+{
+ if (!mDevice)
+ return false;
+
+ qCDebug(QT_BT_WINRT) << __FUNCTION__;
+
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([this]() {
+ HRESULT hr;
+ hr = mDevice->add_ConnectionStatusChanged(
+ Callback<StatusHandler>(this, &QLowEnergyControllerPrivateWinRTNew::onStatusChange).Get(),
+ &mStatusChangedToken);
+ RETURN_IF_FAILED("Could not register connection status callback", return hr)
+ return S_OK;
+ });
+ RETURN_FALSE_IF_FAILED("Could not add status callback on Xaml thread")
+ return true;
+}
+
+void QLowEnergyControllerPrivateWinRTNew::unregisterFromStatusChanges()
+{
+ qCDebug(QT_BT_WINRT) << __FUNCTION__;
+ if (mDevice && mStatusChangedToken.value) {
+ mDevice->remove_ConnectionStatusChanged(mStatusChangedToken);
+ mStatusChangedToken.value = 0;
+ }
+}
+
+HRESULT QLowEnergyControllerPrivateWinRTNew::onStatusChange(IBluetoothLEDevice *dev, IInspectable *)
+{
+ Q_Q(QLowEnergyController);
+ BluetoothConnectionStatus status;
+ HRESULT hr;
+ hr = dev->get_ConnectionStatus(&status);
+ RETURN_IF_FAILED("Could not obtain connection status", return S_OK)
+ if (state == QLowEnergyController::ConnectingState
+ && status == BluetoothConnectionStatus::BluetoothConnectionStatus_Connected) {
+ setState(QLowEnergyController::ConnectedState);
+ emit q->connected();
+ } else if (state != QLowEnergyController::UnconnectedState
+ && status == BluetoothConnectionStatus::BluetoothConnectionStatus_Disconnected) {
+ invalidateServices();
+ unregisterFromValueChanges();
+ unregisterFromStatusChanges();
+ mDevice = nullptr;
+ setError(QLowEnergyController::RemoteHostClosedError);
+ setState(QLowEnergyController::UnconnectedState);
+ emit q->disconnected();
+ }
+ return S_OK;
+}
+
void QLowEnergyControllerPrivateWinRTNew::obtainIncludedServices(
QSharedPointer<QLowEnergyServicePrivate> servicePointer,
ComPtr<IGattDeviceService> service)
{
Q_Q(QLowEnergyController);
- ComPtr<IGattDeviceService2> service2;
- HRESULT hr = service.As(&service2);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IVectorView<GattDeviceService *>> includedServices;
- hr = service2->GetAllIncludedServices(&includedServices);
+ ComPtr<IGattDeviceService3> service3;
+ HRESULT hr = service.As(&service3);
+ RETURN_IF_FAILED("Could not cast service", return);
+ ComPtr<IAsyncOperation<GattDeviceServicesResult *>> op;
+ hr = service3->GetIncludedServicesAsync(&op);
// Some devices return ERROR_ACCESS_DISABLED_BY_POLICY
- if (FAILED(hr))
+ RETURN_IF_FAILED("Could not obtain included services", return);
+ ComPtr<IGattDeviceServicesResult> result;
+ hr = QWinRTFunctions::await(op, result.GetAddressOf(), QWinRTFunctions::ProcessMainThreadEvents, 5000);
+ RETURN_IF_FAILED("Could not await service operation", return);
+ GattCommunicationStatus status;
+ hr = result->get_Status(&status);
+ if (FAILED(hr) || status != GattCommunicationStatus_Success) {
+ qErrnoWarning("Could not obtain list of included services");
return;
+ }
+ ComPtr<IVectorView<GattDeviceService *>> includedServices;
+ hr = result->get_Services(&includedServices);
+ RETURN_IF_FAILED("Could not obtain service list", return);
uint count;
hr = includedServices->get_Size(&count);
- Q_ASSERT_SUCCEEDED(hr);
+ RETURN_IF_FAILED("Could not obtain service list's size", return);
for (uint i = 0; i < count; ++i) {
ComPtr<IGattDeviceService> includedService;
hr = includedServices->GetAt(i, &includedService);
- Q_ASSERT_SUCCEEDED(hr);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service from list");
GUID guuid;
hr = includedService->get_Uuid(&guuid);
- Q_ASSERT_SUCCEEDED(hr);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain included service's Uuid");
const QBluetoothUuid includedUuid(guuid);
QSharedPointer<QLowEnergyServicePrivate> includedPointer;
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__
+ << "Changing service pointer from thread"
+ << QThread::currentThread();
if (serviceList.contains(includedUuid)) {
includedPointer = serviceList.value(includedUuid);
} else {
@@ -636,68 +733,89 @@ void QLowEnergyControllerPrivateWinRTNew::obtainIncludedServices(
}
}
-void QLowEnergyControllerPrivateWinRTNew::discoverServices()
+HRESULT QLowEnergyControllerPrivateWinRTNew::onServiceDiscoveryFinished(ABI::Windows::Foundation::IAsyncOperation<GattDeviceServicesResult *> *op, AsyncStatus status)
{
Q_Q(QLowEnergyController);
+ if (status != AsyncStatus::Completed) {
+ qCDebug(QT_BT_WINRT) << "Could not obtain services";
+ return S_OK;
+ }
+ ComPtr<IGattDeviceServicesResult> result;
+ ComPtr<IVectorView<GattDeviceService *>> deviceServices;
+ HRESULT hr = op->GetResults(&result);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service discovery result",
+ return S_OK);
+ GattCommunicationStatus commStatus;
+ hr = result->get_Status(&commStatus);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service discovery status",
+ return S_OK);
+ if (commStatus != GattCommunicationStatus_Success)
+ return S_OK;
+
+ hr = result->get_Services(&deviceServices);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service list",
+ return S_OK);
+
+ uint serviceCount;
+ hr = deviceServices->get_Size(&serviceCount);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service list size",
+ return S_OK);
+ for (uint i = 0; i < serviceCount; ++i) {
+ ComPtr<IGattDeviceService> deviceService;
+ hr = deviceServices->GetAt(i, &deviceService);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service");
+ GUID guuid;
+ hr = deviceService->get_Uuid(&guuid);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service's Uuid");
+ const QBluetoothUuid service(guuid);
+
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__
+ << "Changing service pointer from thread"
+ << QThread::currentThread();
+ QSharedPointer<QLowEnergyServicePrivate> pointer;
+ if (serviceList.contains(service)) {
+ pointer = serviceList.value(service);
+ } else {
+ QLowEnergyServicePrivate *priv = new QLowEnergyServicePrivate();
+ priv->uuid = service;
+ priv->setController(this);
+
+ pointer = QSharedPointer<QLowEnergyServicePrivate>(priv);
+ serviceList.insert(service, pointer);
+ }
+ pointer->type |= QLowEnergyService::PrimaryService;
+ obtainIncludedServices(pointer, deviceService);
+
+ emit q->serviceDiscovered(service);
+ }
+
+ setState(QLowEnergyController::DiscoveredState);
+ emit q->discoveryFinished();
+
+ return S_OK;
+}
+
+void QLowEnergyControllerPrivateWinRTNew::discoverServices()
+{
qCDebug(QT_BT_WINRT) << "Service discovery initiated";
ComPtr<IBluetoothLEDevice3> device3;
HRESULT hr = mDevice.As(&device3);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not cast device", return);
ComPtr<IAsyncOperation<GenericAttributeProfile::GattDeviceServicesResult *>> asyncResult;
hr = device3->GetGattServicesAsync(&asyncResult);
- Q_ASSERT_SUCCEEDED(hr);
- hr = QEventDispatcherWinRT::runOnXamlThread( [asyncResult, q, this] () {
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain services", return);
+ hr = QEventDispatcherWinRT::runOnXamlThread( [asyncResult, this] () {
HRESULT hr = asyncResult->put_Completed(
Callback<IAsyncOperationCompletedHandler<GenericAttributeProfile::GattDeviceServicesResult *>>(
- [this, q](IAsyncOperation<GenericAttributeProfile::GattDeviceServicesResult *> *, AsyncStatus status) {
- if (status != AsyncStatus::Completed) {
- qCDebug(QT_BT_WINRT) << "Could not obtain services";
- return S_OK;
- }
- ComPtr<IVectorView<GattDeviceService *>> deviceServices;
- HRESULT hr = mDevice->get_GattServices(&deviceServices);
- Q_ASSERT_SUCCEEDED(hr);
- uint serviceCount;
- hr = deviceServices->get_Size(&serviceCount);
- Q_ASSERT_SUCCEEDED(hr);
- for (uint i = 0; i < serviceCount; ++i) {
- ComPtr<IGattDeviceService> deviceService;
- hr = deviceServices->GetAt(i, &deviceService);
- Q_ASSERT_SUCCEEDED(hr);
- GUID guuid;
- hr = deviceService->get_Uuid(&guuid);
- Q_ASSERT_SUCCEEDED(hr);
- const QBluetoothUuid service(guuid);
-
- QSharedPointer<QLowEnergyServicePrivate> pointer;
- if (serviceList.contains(service)) {
- pointer = serviceList.value(service);
- } else {
- QLowEnergyServicePrivate *priv = new QLowEnergyServicePrivate();
- priv->uuid = service;
- priv->setController(this);
-
- pointer = QSharedPointer<QLowEnergyServicePrivate>(priv);
- serviceList.insert(service, pointer);
- }
- pointer->type |= QLowEnergyService::PrimaryService;
-
- obtainIncludedServices(pointer, deviceService);
-
- emit q->serviceDiscovered(service);
- }
-
- setState(QLowEnergyController::DiscoveredState);
- emit q->discoveryFinished();
-
- return S_OK;
- }).Get());
- Q_ASSERT_SUCCEEDED(hr);
+ this, &QLowEnergyControllerPrivateWinRTNew::onServiceDiscoveryFinished).Get());
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not register service discovery callback",
+ return S_OK)
return hr;
});
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not run registration in Xaml thread",
+ return)
}
void QLowEnergyControllerPrivateWinRTNew::discoverServiceDetails(const QBluetoothUuid &service)
@@ -717,34 +835,48 @@ void QLowEnergyControllerPrivateWinRTNew::discoverServiceDetails(const QBluetoot
//update service data
QSharedPointer<QLowEnergyServicePrivate> pointer = serviceList.value(service);
-
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+ << QThread::currentThread();
pointer->setState(QLowEnergyService::DiscoveringServices);
- ComPtr<IGattDeviceService2> deviceService2;
- HRESULT hr = deviceService.As(&deviceService2);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IVectorView<GattDeviceService *>> deviceServices;
- hr = deviceService2->GetAllIncludedServices(&deviceServices);
- if (FAILED(hr)) { // ERROR_ACCESS_DISABLED_BY_POLICY
- qCDebug(QT_BT_WINRT) << "Could not obtain included services list for" << service;
+ ComPtr<IGattDeviceService3> deviceService3;
+ HRESULT hr = deviceService.As(&deviceService3);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not cast service",
+ pointer, QLowEnergyService::UnknownError, return)
+ ComPtr<IAsyncOperation<GattDeviceServicesResult *>> op;
+ hr = deviceService3->GetIncludedServicesAsync(&op);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain included service list",
+ pointer, QLowEnergyService::UnknownError, return)
+ ComPtr<IGattDeviceServicesResult> result;
+ hr = QWinRTFunctions::await(op, result.GetAddressOf());
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not await service operation",
+ pointer, QLowEnergyService::UnknownError, return)
+ GattCommunicationStatus status;
+ hr = result->get_Status(&status);
+ if (FAILED(hr) || status != GattCommunicationStatus_Success) {
+ qCDebug(QT_BT_WINRT) << "Obtaining list of included services failed";
pointer->setError(QLowEnergyService::UnknownError);
- pointer->setState(QLowEnergyService::InvalidService);
return;
}
+ ComPtr<IVectorView<GattDeviceService *>> deviceServices;
+ hr = result->get_Services(&deviceServices);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain service list from result",
+ pointer, QLowEnergyService::UnknownError, return)
uint serviceCount;
hr = deviceServices->get_Size(&serviceCount);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain included service list's size",
+ pointer, QLowEnergyService::UnknownError, return)
for (uint i = 0; i < serviceCount; ++i) {
ComPtr<IGattDeviceService> includedService;
hr = deviceServices->GetAt(i, &includedService);
- Q_ASSERT_SUCCEEDED(hr);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service from list")
GUID guuid;
hr = includedService->get_Uuid(&guuid);
- Q_ASSERT_SUCCEEDED(hr);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service Uuid")
const QBluetoothUuid service(guuid);
if (service.isNull()) {
qCDebug(QT_BT_WINRT) << "Could not find service";
- return;
+ continue;
}
pointer->includedServices.append(service);
@@ -756,12 +888,14 @@ void QLowEnergyControllerPrivateWinRTNew::discoverServiceDetails(const QBluetoot
}
QWinRTLowEnergyServiceHandlerNew *worker
- = new QWinRTLowEnergyServiceHandlerNew(service, deviceService2);
+ = new QWinRTLowEnergyServiceHandlerNew(service, deviceService3);
QThread *thread = new QThread;
worker->moveToThread(thread);
connect(thread, &QThread::started, worker, &QWinRTLowEnergyServiceHandlerNew::obtainCharList);
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
connect(thread, &QThread::finished, worker, &QObject::deleteLater);
+ connect(worker, &QWinRTLowEnergyServiceHandlerNew::errorOccured,
+ this, &QLowEnergyControllerPrivateWinRTNew::handleServiceHandlerError);
connect(worker, &QWinRTLowEnergyServiceHandlerNew::charListObtained,
[this, thread](const QBluetoothUuid &service, QHash<QLowEnergyHandle,
QLowEnergyServicePrivate::CharData> charList, QVector<QBluetoothUuid> indicateChars,
@@ -783,7 +917,8 @@ void QLowEnergyControllerPrivateWinRTNew::discoverServiceDetails(const QBluetoot
registerForValueChanges(service, indicateChar);
return S_OK;
});
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not register for value changes in Xaml thread",
+ pointer, QLowEnergyService::UnknownError, return)
pointer->setState(QLowEnergyService::ServiceDiscovered);
thread->exit(0);
@@ -815,6 +950,8 @@ void QLowEnergyControllerPrivateWinRTNew::readCharacteristic(
const QLowEnergyHandle charHandle)
{
qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle;
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+ << QThread::currentThread();
Q_ASSERT(!service.isNull());
if (role == QLowEnergyController::PeripheralRole) {
service->setError(QLowEnergyService::CharacteristicReadError);
@@ -843,7 +980,8 @@ void QLowEnergyControllerPrivateWinRTNew::readCharacteristic(
}
ComPtr<IAsyncOperation<GattReadResult*>> readOp;
HRESULT hr = characteristic->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached, &readOp);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not read characteristic",
+ service, QLowEnergyService::CharacteristicReadError, return S_OK)
auto readCompletedLambda = [charData, charHandle, service]
(IAsyncOperation<GattReadResult*> *op, AsyncStatus status)
{
@@ -855,11 +993,8 @@ void QLowEnergyControllerPrivateWinRTNew::readCharacteristic(
ComPtr<IGattReadResult> characteristicValue;
HRESULT hr;
hr = op->GetResults(&characteristicValue);
- if (FAILED(hr)) {
- qCDebug(QT_BT_WINRT) << "Could not obtain result for characteristic" << charHandle;
- service->setError(QLowEnergyService::CharacteristicReadError);
- return S_OK;
- }
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for characteristic",
+ service, QLowEnergyService::CharacteristicReadError, return S_OK)
const QByteArray value = byteArrayFromGattResult(characteristicValue);
QLowEnergyServicePrivate::CharData charData = service->characteristicList.value(charHandle);
@@ -870,10 +1005,12 @@ void QLowEnergyControllerPrivateWinRTNew::readCharacteristic(
};
hr = readOp->put_Completed(Callback<IAsyncOperationCompletedHandler<GattReadResult *>>(
readCompletedLambda).Get());
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not register characteristic read callback",
+ service, QLowEnergyService::CharacteristicReadError, return S_OK)
return S_OK;
});
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not run registration on Xaml thread",
+ service, QLowEnergyService::CharacteristicReadError, return)
}
void QLowEnergyControllerPrivateWinRTNew::readDescriptor(
@@ -882,6 +1019,8 @@ void QLowEnergyControllerPrivateWinRTNew::readDescriptor(
const QLowEnergyHandle descHandle)
{
qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << descHandle;
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+ << QThread::currentThread();
Q_ASSERT(!service.isNull());
if (role == QLowEnergyController::PeripheralRole) {
service->setError(QLowEnergyService::DescriptorReadError);
@@ -898,7 +1037,7 @@ void QLowEnergyControllerPrivateWinRTNew::readDescriptor(
HRESULT hr;
hr = QEventDispatcherWinRT::runOnXamlThread([charHandle, descHandle, service, this]() {
- QLowEnergyServicePrivate::CharData charData = service->characteristicList.value(charHandle);
+ const QLowEnergyServicePrivate::CharData charData = service->characteristicList.value(charHandle);
ComPtr<IGattCharacteristic> characteristic = getNativeCharacteristic(service->uuid, charData.uuid);
if (!characteristic) {
qCDebug(QT_BT_WINRT) << "Could not obtain native characteristic" << charData.uuid
@@ -910,12 +1049,14 @@ void QLowEnergyControllerPrivateWinRTNew::readDescriptor(
// Get native descriptor
if (!charData.descriptorList.contains(descHandle))
qCDebug(QT_BT_WINRT) << "Descriptor" << descHandle << "cannot be found in characteristic" << charHandle;
- QLowEnergyServicePrivate::DescData descData = charData.descriptorList.value(descHandle);
- if (descData.uuid == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) {
+ const QLowEnergyServicePrivate::DescData descData = charData.descriptorList.value(descHandle);
+ const QBluetoothUuid descUuid = descData.uuid;
+ if (descUuid == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) {
ComPtr<IAsyncOperation<ClientCharConfigDescriptorResult *>> readOp;
HRESULT hr = characteristic->ReadClientCharacteristicConfigurationDescriptorAsync(&readOp);
- Q_ASSERT_SUCCEEDED(hr);
- auto readCompletedLambda = [&charData, charHandle, &descData, descHandle, service]
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not read client characteristic configuration",
+ service, QLowEnergyService::DescriptorReadError, return S_OK)
+ auto readCompletedLambda = [charHandle, descHandle, service]
(IAsyncOperation<ClientCharConfigDescriptorResult *> *op, AsyncStatus status)
{
if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
@@ -926,18 +1067,12 @@ void QLowEnergyControllerPrivateWinRTNew::readDescriptor(
ComPtr<IClientCharConfigDescriptorResult> iValue;
HRESULT hr;
hr = op->GetResults(&iValue);
- if (FAILED(hr)) {
- qCDebug(QT_BT_WINRT) << "Could not obtain result for descriptor" << descHandle;
- service->setError(QLowEnergyService::DescriptorReadError);
- return S_OK;
- }
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for descriptor",
+ service, QLowEnergyService::DescriptorReadError, return S_OK)
GattClientCharacteristicConfigurationDescriptorValue value;
hr = iValue->get_ClientCharacteristicConfigurationDescriptor(&value);
- if (FAILED(hr)) {
- qCDebug(QT_BT_WINRT) << "Could not obtain value for descriptor" << descHandle;
- service->setError(QLowEnergyService::DescriptorReadError);
- return S_OK;
- }
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain value for descriptor",
+ service, QLowEnergyService::DescriptorReadError, return S_OK)
quint16 result = 0;
bool correct = false;
if (value & GattClientCharacteristicConfigurationDescriptorValue_Indicate) {
@@ -956,9 +1091,11 @@ void QLowEnergyControllerPrivateWinRTNew::readDescriptor(
service->setError(QLowEnergyService::DescriptorReadError);
return S_OK;
}
+ QLowEnergyServicePrivate::DescData descData;
+ descData.uuid = QBluetoothUuid::ClientCharacteristicConfiguration;
descData.value = QByteArray(2, Qt::Uninitialized);
qToLittleEndian(result, descData.value.data());
- charData.descriptorList.insert(descHandle, descData);
+ service->characteristicList[charHandle].descriptorList[descHandle] = descData;
emit service->descriptorRead(QLowEnergyDescriptor(service, charHandle, descHandle),
descData.value);
return S_OK;
@@ -966,19 +1103,56 @@ void QLowEnergyControllerPrivateWinRTNew::readDescriptor(
hr = readOp->put_Completed(
Callback<IAsyncOperationCompletedHandler<ClientCharConfigDescriptorResult *>>(
readCompletedLambda).Get());
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not register descriptor read callback",
+ service, QLowEnergyService::DescriptorReadError, return S_OK)
return S_OK;
} else {
+ ComPtr<IGattCharacteristic3> characteristic3;
+ HRESULT hr = characteristic.As(&characteristic3);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not cast characteristic",
+ service, QLowEnergyService::DescriptorReadError, return S_OK)
+ ComPtr<IAsyncOperation<GattDescriptorsResult *>> op;
+ hr = characteristic3->GetDescriptorsForUuidAsync(descData.uuid, &op);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain descriptor for uuid",
+ service, QLowEnergyService::DescriptorReadError, return S_OK)
+ ComPtr<IGattDescriptorsResult> result;
+ hr = QWinRTFunctions::await(op, result.GetAddressOf(), QWinRTFunctions::ProcessMainThreadEvents, 5000);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not await descritpor read result",
+ service, QLowEnergyService::DescriptorReadError, return S_OK)
+
+ GattCommunicationStatus commStatus;
+ hr = result->get_Status(&commStatus);
+ if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
+ qErrnoWarning("Could not obtain list of descriptors");
+ service->setError(QLowEnergyService::DescriptorReadError);
+ return S_OK;
+ }
+
ComPtr<IVectorView<GattDescriptor *>> descriptors;
- HRESULT hr = characteristic->GetDescriptors(descData.uuid, &descriptors);
- Q_ASSERT_SUCCEEDED(hr);
+ hr = result->get_Descriptors(&descriptors);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain descriptor list",
+ service, QLowEnergyService::DescriptorReadError, return S_OK)
+ uint size;
+ hr = descriptors->get_Size(&size);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not await descritpor list's size",
+ service, QLowEnergyService::DescriptorReadError, return S_OK)
+ if (size == 0) {
+ qCWarning(QT_BT_WINRT) << "No descriptor with uuid" << descData.uuid << "was found.";
+ service->setError(QLowEnergyService::DescriptorReadError);
+ return S_OK;
+ } else if (size > 1) {
+ qCWarning(QT_BT_WINRT) << "There is more than 1 descriptor with uuid" << descData.uuid;
+ }
+
ComPtr<IGattDescriptor> descriptor;
hr = descriptors->GetAt(0, &descriptor);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain descritpor from list",
+ service, QLowEnergyService::DescriptorReadError, return S_OK)
ComPtr<IAsyncOperation<GattReadResult*>> readOp;
hr = descriptor->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached, &readOp);
- Q_ASSERT_SUCCEEDED(hr);
- auto readCompletedLambda = [&charData, charHandle, &descData, descHandle, service]
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not read descriptor value",
+ service, QLowEnergyService::DescriptorReadError, return S_OK)
+ auto readCompletedLambda = [charHandle, descHandle, descUuid, service]
(IAsyncOperation<GattReadResult*> *op, AsyncStatus status)
{
if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
@@ -994,22 +1168,26 @@ void QLowEnergyControllerPrivateWinRTNew::readDescriptor(
service->setError(QLowEnergyService::DescriptorReadError);
return S_OK;
}
+ QLowEnergyServicePrivate::DescData descData;
+ descData.uuid = descUuid;
if (descData.uuid == QBluetoothUuid::CharacteristicUserDescription)
descData.value = byteArrayFromGattResult(descriptorValue, true);
else
descData.value = byteArrayFromGattResult(descriptorValue);
- charData.descriptorList.insert(descHandle, descData);
+ service->characteristicList[charHandle].descriptorList[descHandle] = descData;
emit service->descriptorRead(QLowEnergyDescriptor(service, charHandle, descHandle),
descData.value);
return S_OK;
};
hr = readOp->put_Completed(Callback<IAsyncOperationCompletedHandler<GattReadResult *>>(
readCompletedLambda).Get());
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not register descriptor read callback",
+ service, QLowEnergyService::DescriptorReadError, return S_OK)
return S_OK;
}
});
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not run registration on Xaml thread",
+ service, QLowEnergyService::DescriptorReadError, return)
}
void QLowEnergyControllerPrivateWinRTNew::writeCharacteristic(
@@ -1019,6 +1197,8 @@ void QLowEnergyControllerPrivateWinRTNew::writeCharacteristic(
QLowEnergyService::WriteMode mode)
{
qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << newValue << mode;
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+ << QThread::currentThread();
Q_ASSERT(!service.isNull());
if (role == QLowEnergyController::PeripheralRole) {
service->setError(QLowEnergyService::CharacteristicWriteError);
@@ -1053,26 +1233,33 @@ void QLowEnergyControllerPrivateWinRTNew::writeCharacteristic(
HRESULT hr = GetActivationFactory(
HStringReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
&bufferFactory);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain buffer factory",
+ service, QLowEnergyService::CharacteristicWriteError, return S_OK)
ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer;
const quint32 length = quint32(newValue.length());
hr = bufferFactory->Create(length, &buffer);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not create buffer",
+ service, QLowEnergyService::CharacteristicWriteError, return S_OK)
hr = buffer->put_Length(length);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not set buffer length",
+ service, QLowEnergyService::CharacteristicWriteError, return S_OK)
ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteAccess;
hr = buffer.As(&byteAccess);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not cast buffer",
+ service, QLowEnergyService::CharacteristicWriteError, return S_OK)
byte *bytes;
hr = byteAccess->Buffer(&bytes);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not set buffer",
+ service, QLowEnergyService::CharacteristicWriteError, return S_OK)
memcpy(bytes, newValue, length);
ComPtr<IAsyncOperation<GattCommunicationStatus>> writeOp;
GattWriteOption option = writeWithResponse ? GattWriteOption_WriteWithResponse
: GattWriteOption_WriteWithoutResponse;
hr = characteristic->WriteValueWithOptionAsync(buffer.Get(), option, &writeOp);
- Q_ASSERT_SUCCEEDED(hr);
- auto writeCompletedLambda =[charData, charHandle, newValue, service, writeWithResponse, this]
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could write characteristic",
+ service, QLowEnergyService::CharacteristicWriteError, return S_OK)
+ QPointer<QLowEnergyControllerPrivateWinRTNew> thisPtr(this);
+ auto writeCompletedLambda = [charData, charHandle, newValue, service, writeWithResponse, thisPtr]
(IAsyncOperation<GattCommunicationStatus> *op, AsyncStatus status)
{
if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
@@ -1089,7 +1276,8 @@ void QLowEnergyControllerPrivateWinRTNew::writeCharacteristic(
service->setError(QLowEnergyService::CharacteristicWriteError);
return S_OK;
}
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain characteristic write result",
+ service, QLowEnergyService::CharacteristicWriteError, return S_OK)
if (result != GattCommunicationStatus_Success) {
qCDebug(QT_BT_WINRT) << "Characteristic" << charHandle << "write operation failed";
service->setError(QLowEnergyService::CharacteristicWriteError);
@@ -1098,7 +1286,7 @@ void QLowEnergyControllerPrivateWinRTNew::writeCharacteristic(
// only update cache when property is readable. Otherwise it remains
// empty.
if (charData.properties & QLowEnergyCharacteristic::Read)
- updateValueOfCharacteristic(charHandle, newValue, false);
+ thisPtr->updateValueOfCharacteristic(charHandle, newValue, false);
if (writeWithResponse)
emit service->characteristicWritten(QLowEnergyCharacteristic(service, charHandle),
newValue);
@@ -1107,10 +1295,12 @@ void QLowEnergyControllerPrivateWinRTNew::writeCharacteristic(
hr = writeOp->put_Completed(
Callback<IAsyncOperationCompletedHandler<GattCommunicationStatus>>(
writeCompletedLambda).Get());
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not register characteristic write callback",
+ service, QLowEnergyService::CharacteristicWriteError, return S_OK)
return S_OK;
});
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not run registration on Xaml thread",
+ service, QLowEnergyService::CharacteristicWriteError, return)
}
void QLowEnergyControllerPrivateWinRTNew::writeDescriptor(
@@ -1120,6 +1310,8 @@ void QLowEnergyControllerPrivateWinRTNew::writeDescriptor(
const QByteArray &newValue)
{
qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << descHandle << newValue;
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+ << QThread::currentThread();
Q_ASSERT(!service.isNull());
if (role == QLowEnergyController::PeripheralRole) {
service->setError(QLowEnergyService::DescriptorWriteError);
@@ -1174,8 +1366,10 @@ void QLowEnergyControllerPrivateWinRTNew::writeDescriptor(
}
ComPtr<IAsyncOperation<enum GattCommunicationStatus>> writeOp;
HRESULT hr = characteristic->WriteClientCharacteristicConfigurationDescriptorAsync(value, &writeOp);
- Q_ASSERT_SUCCEEDED(hr);
- auto writeCompletedLambda = [charHandle, descHandle, newValue, service, this]
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not write client characteristic configuration",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
+ QPointer<QLowEnergyControllerPrivateWinRTNew> thisPtr(this);
+ auto writeCompletedLambda = [charHandle, descHandle, newValue, service, thisPtr]
(IAsyncOperation<GattCommunicationStatus> *op, AsyncStatus status)
{
if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
@@ -1186,17 +1380,14 @@ void QLowEnergyControllerPrivateWinRTNew::writeDescriptor(
GattCommunicationStatus result;
HRESULT hr;
hr = op->GetResults(&result);
- if (FAILED(hr)) {
- qCDebug(QT_BT_WINRT) << "Could not obtain result for descriptor" << descHandle;
- service->setError(QLowEnergyService::DescriptorWriteError);
- return S_OK;
- }
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for descriptor",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
if (result != GattCommunicationStatus_Success) {
- qCDebug(QT_BT_WINRT) << "Descriptor" << descHandle << "write operation failed";
+ qCWarning(QT_BT_WINRT) << "Descriptor" << descHandle << "write operation failed";
service->setError(QLowEnergyService::DescriptorWriteError);
return S_OK;
}
- updateValueOfDescriptor(charHandle, descHandle, newValue, false);
+ thisPtr->updateValueOfDescriptor(charHandle, descHandle, newValue, false);
emit service->descriptorWritten(QLowEnergyDescriptor(service, charHandle, descHandle),
newValue);
return S_OK;
@@ -1204,36 +1395,75 @@ void QLowEnergyControllerPrivateWinRTNew::writeDescriptor(
hr = writeOp->put_Completed(
Callback<IAsyncOperationCompletedHandler<GattCommunicationStatus >>(
writeCompletedLambda).Get());
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not register descriptor write callback",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
} else {
+ ComPtr<IGattCharacteristic3> characteristic3;
+ HRESULT hr = characteristic.As(&characteristic3);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not cast characteristic",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
+ ComPtr<IAsyncOperation<GattDescriptorsResult *>> op;
+ hr = characteristic3->GetDescriptorsForUuidAsync(descData.uuid, &op);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain descriptor from Uuid",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
+ ComPtr<IGattDescriptorsResult> result;
+ hr = QWinRTFunctions::await(op, result.GetAddressOf(), QWinRTFunctions::ProcessMainThreadEvents, 5000);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not await descriptor operation",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
+ GattCommunicationStatus commStatus;
+ hr = result->get_Status(&commStatus);
+ if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
+ qCWarning(QT_BT_WINRT) << "Descriptor operation failed";
+ service->setError(QLowEnergyService::DescriptorWriteError);
+ return S_OK;
+ }
ComPtr<IVectorView<GattDescriptor *>> descriptors;
- HRESULT hr = characteristic->GetDescriptors(descData.uuid, &descriptors);
- Q_ASSERT_SUCCEEDED(hr);
+ hr = result->get_Descriptors(&descriptors);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain list of descriptors",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
+ uint size;
+ hr = descriptors->get_Size(&size);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain list of descriptors' size",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
+ if (size == 0) {
+ qCWarning(QT_BT_WINRT) << "No descriptor with uuid" << descData.uuid << "was found.";
+ return S_OK;
+ } else if (size > 1) {
+ qCWarning(QT_BT_WINRT) << "There is more than 1 descriptor with uuid" << descData.uuid;
+ }
ComPtr<IGattDescriptor> descriptor;
hr = descriptors->GetAt(0, &descriptor);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain descriptor",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
ComPtr<ABI::Windows::Storage::Streams::IBufferFactory> bufferFactory;
hr = GetActivationFactory(
HStringReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
&bufferFactory);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain buffer factory",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer;
const quint32 length = quint32(newValue.length());
hr = bufferFactory->Create(length, &buffer);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not create buffer",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
hr = buffer->put_Length(length);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not set buffer length",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteAccess;
hr = buffer.As(&byteAccess);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not cast buffer",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
byte *bytes;
hr = byteAccess->Buffer(&bytes);
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not set buffer",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
memcpy(bytes, newValue, length);
ComPtr<IAsyncOperation<GattCommunicationStatus>> writeOp;
hr = descriptor->WriteValueAsync(buffer.Get(), &writeOp);
- Q_ASSERT_SUCCEEDED(hr);
- auto writeCompletedLambda = [charHandle, descHandle, newValue, service, this]
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not write descriptor value",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
+ QPointer<QLowEnergyControllerPrivateWinRTNew> thisPtr(this);
+ auto writeCompletedLambda = [charHandle, descHandle, newValue, service, thisPtr]
(IAsyncOperation<GattCommunicationStatus> *op, AsyncStatus status)
{
if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
@@ -1244,17 +1474,14 @@ void QLowEnergyControllerPrivateWinRTNew::writeDescriptor(
GattCommunicationStatus result;
HRESULT hr;
hr = op->GetResults(&result);
- if (FAILED(hr)) {
- qCDebug(QT_BT_WINRT) << "Could not obtain result for descriptor" << descHandle;
- service->setError(QLowEnergyService::DescriptorWriteError);
- return S_OK;
- }
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for descriptor",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
if (result != GattCommunicationStatus_Success) {
qCDebug(QT_BT_WINRT) << "Descriptor" << descHandle << "write operation failed";
service->setError(QLowEnergyService::DescriptorWriteError);
return S_OK;
}
- updateValueOfDescriptor(charHandle, descHandle, newValue, false);
+ thisPtr->updateValueOfDescriptor(charHandle, descHandle, newValue, false);
emit service->descriptorWritten(QLowEnergyDescriptor(service, charHandle, descHandle),
newValue);
return S_OK;
@@ -1262,12 +1489,14 @@ void QLowEnergyControllerPrivateWinRTNew::writeDescriptor(
hr = writeOp->put_Completed(
Callback<IAsyncOperationCompletedHandler<GattCommunicationStatus>>(
writeCompletedLambda).Get());
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not register descriptor write callback",
+ service, QLowEnergyService::DescriptorWriteError, return S_OK)
return S_OK;
}
return S_OK;
});
- Q_ASSERT_SUCCEEDED(hr);
+ CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not run registration on Xaml thread",
+ service, QLowEnergyService::DescriptorWriteError, return)
}
@@ -1277,9 +1506,12 @@ void QLowEnergyControllerPrivateWinRTNew::addToGenericAttributeList(const QLowEn
Q_UNIMPLEMENTED();
}
-void QLowEnergyControllerPrivateWinRTNew::characteristicChanged(
+void QLowEnergyControllerPrivateWinRTNew::handleCharacteristicChanged(
quint16 charHandle, const QByteArray &data)
{
+ qCDebug(QT_BT_WINRT) << __FUNCTION__ << charHandle << data;
+ qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+ << QThread::currentThread();
QSharedPointer<QLowEnergyServicePrivate> service =
serviceForHandle(charHandle);
if (service.isNull())
@@ -1302,6 +1534,170 @@ void QLowEnergyControllerPrivateWinRTNew::characteristicChanged(
emit service->characteristicChanged(characteristic, data);
}
+void QLowEnergyControllerPrivateWinRTNew::handleServiceHandlerError(const QString &error)
+{
+ if (state != QLowEnergyController::DiscoveringState)
+ return;
+
+ qCWarning(QT_BT_WINRT) << "Error while discovering services:" << error;
+ setState(QLowEnergyController::UnconnectedState);
+ setError(QLowEnergyController::ConnectionError);
+}
+
+void QLowEnergyControllerPrivateWinRTNew::connectToPairedDevice()
+{
+ Q_Q(QLowEnergyController);
+ ComPtr<IBluetoothLEDevice3> device3;
+ HRESULT hr = mDevice.As(&device3);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not cast device", return)
+ ComPtr<IAsyncOperation<GattDeviceServicesResult *>> deviceServicesOp;
+ while (!mAbortPending) {
+ hr = device3->GetGattServicesAsync(&deviceServicesOp);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain services", return)
+ ComPtr<IGattDeviceServicesResult> deviceServicesResult;
+ hr = QWinRTFunctions::await(deviceServicesOp, deviceServicesResult.GetAddressOf(),
+ QWinRTFunctions::ProcessThreadEvents, 5000);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not await services operation", return)
+
+ GattCommunicationStatus commStatus;
+ hr = deviceServicesResult->get_Status(&commStatus);
+ if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
+ qCWarning(QT_BT_WINRT()) << "Service operation failed";
+ setError(QLowEnergyController::ConnectionError);
+ setState(QLowEnergyController::UnconnectedState);
+ unregisterFromStatusChanges();
+ return;
+ }
+
+ ComPtr<IVectorView <GattDeviceService *>> deviceServices;
+ hr = deviceServicesResult->get_Services(&deviceServices);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain list of services", return)
+ uint serviceCount;
+ hr = deviceServices->get_Size(&serviceCount);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service count", return)
+
+ if (serviceCount == 0) {
+ qCWarning(QT_BT_WINRT()) << "Found devices without services";
+ setError(QLowEnergyController::ConnectionError);
+ setState(QLowEnergyController::UnconnectedState);
+ unregisterFromStatusChanges();
+ return;
+ }
+
+ // Windows automatically connects to the device as soon as a service value is read/written.
+ // Thus we read one value in order to establish the connection.
+ for (uint i = 0; i < serviceCount; ++i) {
+ ComPtr<IGattDeviceService> service;
+ hr = deviceServices->GetAt(i, &service);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service", return);
+ ComPtr<IGattDeviceService3> service3;
+ hr = service.As(&service3);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not cast service", return);
+ ComPtr<IAsyncOperation<GattCharacteristicsResult *>> characteristicsOp;
+ hr = service3->GetCharacteristicsAsync(&characteristicsOp);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain characteristic", return);
+ ComPtr<IGattCharacteristicsResult> characteristicsResult;
+ hr = QWinRTFunctions::await(characteristicsOp, characteristicsResult.GetAddressOf(),
+ QWinRTFunctions::ProcessThreadEvents, 5000);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not await characteristic operation", return);
+ GattCommunicationStatus commStatus;
+ hr = characteristicsResult->get_Status(&commStatus);
+ if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
+ qCWarning(QT_BT_WINRT) << "Characteristic operation failed";
+ break;
+ }
+ ComPtr<IVectorView<GattCharacteristic *>> characteristics;
+ hr = characteristicsResult->get_Characteristics(&characteristics);
+ if (hr == E_ACCESSDENIED) {
+ // Everything will work as expected up until this point if the manifest capabilties
+ // for bluetooth LE are not set.
+ qCWarning(QT_BT_WINRT) << "Could not obtain characteristic list. Please check your "
+ "manifest capabilities";
+ setState(QLowEnergyController::UnconnectedState);
+ setError(QLowEnergyController::ConnectionError);
+ unregisterFromStatusChanges();
+ return;
+ }
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain characteristic list", return);
+ uint characteristicsCount;
+ hr = characteristics->get_Size(&characteristicsCount);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain characteristic list's size", return);
+ for (uint j = 0; j < characteristicsCount; ++j) {
+ ComPtr<IGattCharacteristic> characteristic;
+ hr = characteristics->GetAt(j, &characteristic);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain characteristic", return);
+ ComPtr<IAsyncOperation<GattReadResult *>> op;
+ GattCharacteristicProperties props;
+ hr = characteristic->get_CharacteristicProperties(&props);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain characteristic's properties", return);
+ if (!(props & GattCharacteristicProperties_Read))
+ continue;
+ hr = characteristic->ReadValueWithCacheModeAsync(BluetoothCacheMode::BluetoothCacheMode_Uncached, &op);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not read characteristic value", return);
+ ComPtr<IGattReadResult> result;
+ hr = QWinRTFunctions::await(op, result.GetAddressOf(), QWinRTFunctions::ProcessThreadEvents, 500);
+ // E_ILLEGAL_METHOD_CALL will be the result for a device, that is not reachable at
+ // the moment. In this case we should jump back into the outer loop and keep trying.
+ if (hr == E_ILLEGAL_METHOD_CALL)
+ break;
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not await characteristic read", return);
+ ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer;
+ hr = result->get_Value(&buffer);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain characteristic value", return);
+ if (!buffer) {
+ qCDebug(QT_BT_WINRT) << "Problem reading value";
+ break;
+ }
+
+ setState(QLowEnergyController::ConnectedState);
+ emit q->connected();
+ if (!registerForStatusChanges()) {
+ setError(QLowEnergyController::ConnectionError);
+ setState(QLowEnergyController::UnconnectedState);
+ return;
+ }
+ return;
+ }
+ }
+ }
+}
+
+void QLowEnergyControllerPrivateWinRTNew::connectToUnpairedDevice()
+{
+ if (!registerForStatusChanges()) {
+ setError(QLowEnergyController::ConnectionError);
+ setState(QLowEnergyController::UnconnectedState);
+ return;
+ }
+ ComPtr<IBluetoothLEDevice3> device3;
+ HRESULT hr = mDevice.As(&device3);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not cast device", return)
+ ComPtr<IGattDeviceServicesResult> deviceServicesResult;
+ while (!mAbortPending) {
+ ComPtr<IAsyncOperation<GattDeviceServicesResult *>> deviceServicesOp;
+ hr = device3->GetGattServicesAsync(&deviceServicesOp);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain services", return)
+ hr = QWinRTFunctions::await(deviceServicesOp, deviceServicesResult.GetAddressOf(),
+ QWinRTFunctions::ProcessMainThreadEvents);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not await services operation", return)
+
+ GattCommunicationStatus commStatus;
+ hr = deviceServicesResult->get_Status(&commStatus);
+ if (commStatus == GattCommunicationStatus_Unreachable)
+ continue;
+
+ if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
+ qCWarning(QT_BT_WINRT()) << "Service operation failed";
+ setError(QLowEnergyController::ConnectionError);
+ setState(QLowEnergyController::UnconnectedState);
+ unregisterFromStatusChanges();
+ return;
+ }
+
+ break;
+ }
+}
+
QT_END_NAMESPACE
#include "qlowenergycontroller_winrt_new.moc"
diff --git a/src/bluetooth/qlowenergycontroller_winrt_new_p.h b/src/bluetooth/qlowenergycontroller_winrt_new_p.h
index 716d2d07..c31408be 100644
--- a/src/bluetooth/qlowenergycontroller_winrt_new_p.h
+++ b/src/bluetooth/qlowenergycontroller_winrt_new_p.h
@@ -60,8 +60,22 @@
#include "qlowenergycontroller.h"
#include "qlowenergycontrollerbase_p.h"
+namespace ABI {
+ namespace Windows {
+ namespace Devices {
+ namespace Bluetooth {
+ struct IBluetoothLEDevice;
+ }
+ }
+ namespace Foundation {
+ template <typename T> struct IAsyncOperation;
+ enum class AsyncStatus;
+ }
+ }
+}
+
#include <wrl.h>
-#include <windows.devices.bluetooth.h>
+#include <windows.devices.bluetooth.genericattributeprofile.h>
#include <functional>
@@ -116,10 +130,18 @@ public:
void addToGenericAttributeList(const QLowEnergyServiceData &service,
QLowEnergyHandle startHandle) override;
-private slots:
+signals:
void characteristicChanged(quint16 charHandle, const QByteArray &data);
+private slots:
+ void handleCharacteristicChanged(quint16 charHandle, const QByteArray &data);
+ void handleServiceHandlerError(const QString &error);
+
private:
+ void connectToPairedDevice();
+ void connectToUnpairedDevice();
+
+ bool mAbortPending = false;
Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice> mDevice;
EventRegistrationToken mStatusChangedToken;
struct ValueChangedEntry {
@@ -140,10 +162,18 @@ private:
Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> getNativeCharacteristic(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid);
void registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid);
+ void unregisterFromValueChanges();
+ HRESULT onValueChange(ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic *characteristic,
+ ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattValueChangedEventArgs *args);
+
+ bool registerForStatusChanges();
+ void unregisterFromStatusChanges();
+ HRESULT onStatusChange(ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice *dev, IInspectable *);
void obtainIncludedServices(QSharedPointer<QLowEnergyServicePrivate> servicePointer,
Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> nativeService);
-
+ HRESULT onServiceDiscoveryFinished(ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDeviceServicesResult *> *op,
+ ABI::Windows::Foundation::AsyncStatus status);
};
QT_END_NAMESPACE
diff --git a/src/bluetooth/qlowenergycontroller_winrt_p.h b/src/bluetooth/qlowenergycontroller_winrt_p.h
index 783a71fa..fedc52d9 100644
--- a/src/bluetooth/qlowenergycontroller_winrt_p.h
+++ b/src/bluetooth/qlowenergycontroller_winrt_p.h
@@ -114,8 +114,11 @@ public:
void addToGenericAttributeList(const QLowEnergyServiceData &service,
QLowEnergyHandle startHandle) override;
+signals:
+ void characteristicChanged(quint16 charHandle, const QByteArray &data);
+
private slots:
- void characteristicChanged(int charHandle, const QByteArray &data);
+ void handleCharacteristicChanged(quint16 charHandle, const QByteArray &data);
private:
Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice> mDevice;
@@ -138,6 +141,7 @@ private:
Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> getNativeCharacteristic(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid);
void registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid);
+ void unregisterFromValueChanges();
void obtainIncludedServices(QSharedPointer<QLowEnergyServicePrivate> servicePointer,
Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> nativeService);
diff --git a/src/bluetooth/qlowenergycontrollerbase.cpp b/src/bluetooth/qlowenergycontrollerbase.cpp
index 86108648..059bd41b 100644
--- a/src/bluetooth/qlowenergycontrollerbase.cpp
+++ b/src/bluetooth/qlowenergycontrollerbase.cpp
@@ -61,7 +61,7 @@ QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate()
bool QLowEnergyControllerPrivate::isValidLocalAdapter()
{
-#ifdef QT_WINRT_BLUETOOTH
+#if defined(QT_WINRT_BLUETOOTH) || defined(Q_OS_DARWIN)
return true;
#endif
if (localAdapter.isNull())
@@ -106,6 +106,9 @@ void QLowEnergyControllerPrivate::setError(
case QLowEnergyController::RemoteHostClosedError:
errorString = QLowEnergyController::tr("Remote device closed the connection");
break;
+ case QLowEnergyController::AuthorizationError:
+ errorString = QLowEnergyController::tr("Failed to authorize on the remote device");
+ break;
case QLowEnergyController::NoError:
return;
default:
diff --git a/src/bluetooth/qlowenergycontrollerbase_p.h b/src/bluetooth/qlowenergycontrollerbase_p.h
index a8d1c676..169ba07b 100644
--- a/src/bluetooth/qlowenergycontrollerbase_p.h
+++ b/src/bluetooth/qlowenergycontrollerbase_p.h
@@ -51,24 +51,6 @@
// We mean it.
//
-#if defined(QT_OSX_BLUETOOTH) || defined(QT_IOS_BLUETOOTH)
-
-#include <QtCore/qglobal.h>
-#include <QtCore/qobject.h>
-
-QT_BEGIN_NAMESPACE
-
-class QLowEnergyControllerPrivate : public QObject
-{
-public:
- // This class is required to make shared pointer machinery and
- // moc (== Obj-C syntax) happy on both OS X and iOS.
-};
-
-QT_END_NAMESPACE
-
-#else
-
#include <qglobal.h>
#include <QtCore/qobject.h>
@@ -135,7 +117,6 @@ public:
virtual QLowEnergyService *addServiceHelper(
const QLowEnergyServiceData &service);
-
// common backend methods
bool isValidLocalAdapter();
void setError(QLowEnergyController::Error newError);
@@ -174,6 +155,7 @@ protected:
QLowEnergyHandle lastLocalHandle{};
QString remoteName; // device name of the remote
+ QBluetoothUuid deviceUuid; // quite useless anywhere but Darwin (CoreBluetooth).
Q_DECLARE_PUBLIC(QLowEnergyController)
QLowEnergyController *q_ptr;
@@ -181,6 +163,4 @@ protected:
QT_END_NAMESPACE
-#endif //defined(QT_OSX_BLUETOOTH) || defined(QT_IOS_BLUETOOTH)
-
#endif // QLOWENERGYCONTROLLERPRIVATEBASE_P_H
diff --git a/src/bluetooth/qlowenergydescriptor.h b/src/bluetooth/qlowenergydescriptor.h
index adfe1203..18bb53c0 100644
--- a/src/bluetooth/qlowenergydescriptor.h
+++ b/src/bluetooth/qlowenergydescriptor.h
@@ -83,8 +83,8 @@ protected:
friend class QLowEnergyControllerPrivateBluez;
friend class QLowEnergyControllerPrivateBluezDBus;
friend class QLowEnergyControllerPrivateCommon;
- friend class QLowEnergyControllerPrivateOSX;
friend class QLowEnergyControllerPrivateWin32;
+ friend class QLowEnergyControllerPrivateDarwin;
friend class QLowEnergyControllerPrivateWinRT;
friend class QLowEnergyControllerPrivateWinRTNew;
QLowEnergyDescriptorPrivate *data = nullptr;
diff --git a/src/bluetooth/qlowenergyservice.cpp b/src/bluetooth/qlowenergyservice.cpp
index 1529d3c2..2e6d1f9b 100644
--- a/src/bluetooth/qlowenergyservice.cpp
+++ b/src/bluetooth/qlowenergyservice.cpp
@@ -47,6 +47,10 @@
#include "qlowenergycontrollerbase_p.h"
#include "qlowenergyserviceprivate_p.h"
+#ifdef Q_OS_DARWIN
+#include "qlowenergycontroller_darwin_p.h"
+#endif // Q_OS_DARWIN
+
QT_BEGIN_NAMESPACE
/*!
@@ -809,6 +813,21 @@ void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor,
d->setError(QLowEnergyService::OperationError);
return;
}
+#ifdef Q_OS_DARWIN
+ if (descriptor.uuid() == QBluetoothUuid::ClientCharacteristicConfiguration) {
+ // We have to identify a special case - ClientCharacteristicConfiguration
+ // since with CoreBluetooth:
+ //
+ // "You cannot use this method to write the value of a client configuration descriptor
+ // (represented by the CBUUIDClientCharacteristicConfigurationString constant),
+ // which describes how notification or indications are configured for a
+ // characteristic’s value with respect to a client. If you want to manage
+ // notifications or indications for a characteristic’s value, you must
+ // use the setNotifyValue:forCharacteristic: method instead."
+ auto controller = static_cast<QLowEnergyControllerPrivateDarwin *>(d->controller.data());
+ return controller->setNotifyValue(descriptor.d_ptr, descriptor.characteristicHandle(), newValue);
+ }
+#endif // Q_OS_DARWIN
d->controller->writeDescriptor(descriptor.d_ptr,
descriptor.characteristicHandle(),
diff --git a/src/bluetooth/qlowenergyservice.h b/src/bluetooth/qlowenergyservice.h
index 9de65a84..a2715471 100644
--- a/src/bluetooth/qlowenergyservice.h
+++ b/src/bluetooth/qlowenergyservice.h
@@ -136,6 +136,7 @@ private:
friend class QLowEnergyControllerPrivate;
friend class QLowEnergyControllerPrivateBluez;
friend class QLowEnergyControllerPrivateAndroid;
+ friend class QLowEnergyControllerPrivateDarwin;
QLowEnergyService(QSharedPointer<QLowEnergyServicePrivate> p,
QObject *parent = nullptr);
};
diff --git a/src/bluetooth/qlowenergyservice_osx.mm b/src/bluetooth/qlowenergyservice_osx.mm
deleted file mode 100644
index c294b693..00000000
--- a/src/bluetooth/qlowenergyservice_osx.mm
+++ /dev/null
@@ -1,277 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Javier S. Pedro <maemo@javispedro.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtBluetooth module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qlowenergycontroller_osx_p.h"
-#include "qlowenergyserviceprivate_p.h"
-#include "qlowenergycharacteristic.h"
-#include "qlowenergydescriptor.h"
-#include "qlowenergyservice.h"
-#include "qbluetoothuuid.h"
-
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qlist.h>
-
-#include <algorithm>
-
-QT_BEGIN_NAMESPACE
-
-namespace {
-
-QLowEnergyControllerPrivateOSX *qt_mac_le_controller(QSharedPointer<QLowEnergyServicePrivate> d_ptr)
-{
- if (d_ptr.isNull())
- return nullptr;
-
- return static_cast<QLowEnergyControllerPrivateOSX *>(d_ptr->controller.data());
-}
-
-}
-
-QLowEnergyService::QLowEnergyService(QSharedPointer<QLowEnergyServicePrivate> d, QObject *parent)
- : QObject(parent),
- d_ptr(d)
-{
- qRegisterMetaType<QLowEnergyService::ServiceState>();
- qRegisterMetaType<QLowEnergyService::ServiceError>();
-
- connect(d.data(), SIGNAL(error(QLowEnergyService::ServiceError)),
- this, SIGNAL(error(QLowEnergyService::ServiceError)));
- connect(d.data(), SIGNAL(stateChanged(QLowEnergyService::ServiceState)),
- this, SIGNAL(stateChanged(QLowEnergyService::ServiceState)));
- connect(d.data(), SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)),
- this, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)));
- connect(d.data(), SIGNAL(characteristicWritten(QLowEnergyCharacteristic, QByteArray)),
- this, SIGNAL(characteristicWritten(QLowEnergyCharacteristic, QByteArray)));
- connect(d.data(), SIGNAL(descriptorWritten(QLowEnergyDescriptor, QByteArray)),
- this, SIGNAL(descriptorWritten(QLowEnergyDescriptor, QByteArray)));
- connect(d.data(), SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)),
- this, SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)));
- connect(d.data(), SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray)),
- this, SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray)));
-
-}
-
-QLowEnergyService::~QLowEnergyService()
-{
-}
-
-QList<QBluetoothUuid> QLowEnergyService::includedServices() const
-{
- return d_ptr->includedServices;
-}
-
-QLowEnergyService::ServiceTypes QLowEnergyService::type() const
-{
- return d_ptr->type;
-}
-
-QLowEnergyService::ServiceState QLowEnergyService::state() const
-{
- return d_ptr->state;
-}
-
-QLowEnergyCharacteristic QLowEnergyService::characteristic(const QBluetoothUuid &uuid) const
-{
- CharacteristicDataMap::const_iterator charIt = d_ptr->characteristicList.constBegin();
- for ( ; charIt != d_ptr->characteristicList.constEnd(); ++charIt) {
- const QLowEnergyHandle charHandle = charIt.key();
- const QLowEnergyServicePrivate::CharData &charDetails = charIt.value();
-
- if (charDetails.uuid == uuid)
- return QLowEnergyCharacteristic(d_ptr, charHandle);
- }
-
- return QLowEnergyCharacteristic();
-}
-
-QList<QLowEnergyCharacteristic> QLowEnergyService::characteristics() const
-{
- QList<QLowEnergyCharacteristic> result;
- QList<QLowEnergyHandle> handles(d_ptr->characteristicList.keys());
-
- std::sort(handles.begin(), handles.end());
-
- for (const QLowEnergyHandle &handle : qAsConst(handles)) {
- QLowEnergyCharacteristic characteristic(d_ptr, handle);
- result.append(characteristic);
- }
-
- return result;
-}
-
-QBluetoothUuid QLowEnergyService::serviceUuid() const
-{
- return d_ptr->uuid;
-}
-
-QString QLowEnergyService::serviceName() const
-{
- bool ok = false;
- const quint16 clsId = d_ptr->uuid.toUInt16(&ok);
- if (ok) {
- QBluetoothUuid::ServiceClassUuid uuid
- = static_cast<QBluetoothUuid::ServiceClassUuid>(clsId);
- const QString name = QBluetoothUuid::serviceClassToString(uuid);
- if (!name.isEmpty())
- return name;
- }
-
- return qApp ? qApp->translate("QBluetoothServiceDiscoveryAgent", "Unknown Service") :
- QStringLiteral("Unknown Service");
-}
-
-void QLowEnergyService::discoverDetails()
-{
- QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
-
- if (!controller || d_ptr->state == InvalidService) {
- d_ptr->setError(OperationError);
- return;
- }
-
- if (d_ptr->state != DiscoveryRequired)
- return;
-
- d_ptr->setState(QLowEnergyService::DiscoveringServices);
- controller->discoverServiceDetails(d_ptr->uuid);
-}
-
-QLowEnergyService::ServiceError QLowEnergyService::error() const
-{
- return d_ptr->lastError;
-}
-
-bool QLowEnergyService::contains(const QLowEnergyCharacteristic &characteristic) const
-{
- if (characteristic.d_ptr.isNull() || !characteristic.data)
- return false;
-
- if (d_ptr == characteristic.d_ptr
- && d_ptr->characteristicList.contains(characteristic.attributeHandle())) {
- return true;
- }
-
- return false;
-}
-
-void QLowEnergyService::readCharacteristic(const QLowEnergyCharacteristic &characteristic)
-{
- QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
- if (controller == nullptr || state() != ServiceDiscovered || !contains(characteristic)) {
- d_ptr->setError(OperationError);
- return;
- }
-
- controller->readCharacteristic(characteristic.d_ptr, characteristic.attributeHandle());
-}
-
-
-void QLowEnergyService::writeCharacteristic(const QLowEnergyCharacteristic &ch, const QByteArray &newValue,
- WriteMode mode)
-{
- QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
- if (controller == nullptr ||
- (controller->role == QLowEnergyController::CentralRole && state() != ServiceDiscovered) ||
- !contains(ch)) {
- d_ptr->setError(QLowEnergyService::OperationError);
- return;
- }
-
- controller->writeCharacteristic(ch.d_ptr, ch.attributeHandle(), newValue, mode);
-}
-
-bool QLowEnergyService::contains(const QLowEnergyDescriptor &descriptor) const
-{
- if (descriptor.d_ptr.isNull() || !descriptor.data)
- return false;
-
- const QLowEnergyHandle charHandle = descriptor.characteristicHandle();
- if (!charHandle)
- return false;
-
- if (d_ptr == descriptor.d_ptr && d_ptr->characteristicList.contains(charHandle)
- && d_ptr->characteristicList[charHandle].descriptorList.contains(descriptor.handle()))
- {
- return true;
- }
-
- return false;
-}
-
-void QLowEnergyService::readDescriptor(const QLowEnergyDescriptor &descriptor)
-{
- QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
- if (controller == nullptr || state() != ServiceDiscovered || !contains(descriptor)) {
- d_ptr->setError(OperationError);
- return;
- }
-
- controller->readDescriptor(descriptor.d_ptr, descriptor.handle());
-}
-
-void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor,
- const QByteArray &newValue)
-{
- QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
- if (controller == nullptr || state() != ServiceDiscovered || !contains(descriptor)) {
- // This operation error also includes LE controller in the peripheral role:
- // on iOS/OS X - descriptors are immutable.
- d_ptr->setError(OperationError);
- return;
- }
-
- if (descriptor.uuid() == QBluetoothUuid::ClientCharacteristicConfiguration) {
- // We have to identify a special case - ClientCharacteristicConfiguration
- // since with Core Bluetooth:
- //
- // "You cannot use this method to write the value of a client configuration descriptor
- // (represented by the CBUUIDClientCharacteristicConfigurationString constant),
- // which describes how notification or indications are configured for a
- // characteristic’s value with respect to a client. If you want to manage
- // notifications or indications for a characteristic’s value, you must
- // use the setNotifyValue:forCharacteristic: method instead."
- controller->setNotifyValue(descriptor.d_ptr, descriptor.characteristicHandle(), newValue);
- } else {
- controller->writeDescriptor(descriptor.d_ptr, descriptor.handle(), newValue);
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/bluetooth/plugins.qmltypes b/src/imports/bluetooth/plugins.qmltypes
index 163d8413..9318fe93 100644
--- a/src/imports/bluetooth/plugins.qmltypes
+++ b/src/imports/bluetooth/plugins.qmltypes
@@ -4,10 +4,10 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable QtBluetooth 5.12'
+// 'qmlplugindump -nonrelocatable QtBluetooth 5.13'
Module {
- dependencies: ["QtQuick 2.12"]
+ dependencies: ["QtQuick 2.0"]
Component {
name: "QDeclarativeBluetoothDiscoveryModel"
prototype: "QAbstractListModel"
diff --git a/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp b/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp
index 6b2f32f3..6213355e 100644
--- a/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp
+++ b/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp
@@ -165,14 +165,6 @@ QDeclarativeBluetoothDiscoveryModel::QDeclarativeBluetoothDiscoveryModel(QObject
this,
&QDeclarativeBluetoothDiscoveryModel::errorDiscovery);
d->m_serviceAgent->setObjectName(QStringLiteral("ServiceDiscoveryAgent"));
-
- QHash<int, QByteArray> roleNames;
- roleNames = QAbstractItemModel::roleNames();
- roleNames.insert(Name, "name");
- roleNames.insert(ServiceRole, "service");
- roleNames.insert(RemoteAddress, "remoteAddress");
- roleNames.insert(DeviceName, "deviceName");
- setRoleNames(roleNames);
}
QDeclarativeBluetoothDiscoveryModel::~QDeclarativeBluetoothDiscoveryModel()
@@ -314,6 +306,14 @@ QVariant QDeclarativeBluetoothDiscoveryModel::data(const QModelIndex &index, int
return QVariant();
}
+QHash<int,QByteArray> QDeclarativeBluetoothDiscoveryModel::roleNames() const
+{
+ return {{Name, "name"},
+ {ServiceRole, "service"},
+ {RemoteAddress, "remoteAddress"},
+ {DeviceName, "deviceName"}};
+}
+
/*!
\qmlsignal BluetoothDiscoveryModel::serviceDiscovered(BluetoothService service)
diff --git a/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h b/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h
index 0aa134f5..6cbde088 100644
--- a/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h
+++ b/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h
@@ -106,13 +106,15 @@ public:
Error error() const;
- void componentComplete();
+ void componentComplete() override;
- void classBegin() { }
+ void classBegin() override { }
// From QAbstractListModel
- int rowCount(const QModelIndex &parent) const;
- QVariant data(const QModelIndex &index, int role) const;
+ int rowCount(const QModelIndex &parent) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+
+ QHash<int,QByteArray> roleNames() const override;
DiscoveryMode discoveryMode() const;
void setDiscoveryMode(DiscoveryMode discovery);
diff --git a/src/imports/nfc/plugins.qmltypes b/src/imports/nfc/plugins.qmltypes
index 81ce21d0..d99cac23 100644
--- a/src/imports/nfc/plugins.qmltypes
+++ b/src/imports/nfc/plugins.qmltypes
@@ -4,10 +4,10 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable QtNfc 5.12'
+// 'qmlplugindump -nonrelocatable QtNfc 5.13'
Module {
- dependencies: ["QtQuick 2.12"]
+ dependencies: ["QtQuick 2.0"]
Component {
name: "QDeclarativeNdefFilter"
prototype: "QObject"
diff --git a/src/nfc/doc/qtnfc.qdocconf b/src/nfc/doc/qtnfc.qdocconf
index 61ed15b6..e4f10f0e 100644
--- a/src/nfc/doc/qtnfc.qdocconf
+++ b/src/nfc/doc/qtnfc.qdocconf
@@ -1,4 +1,5 @@
include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
+include($QT_INSTALL_DOCS/config/exampleurl-qtconnectivity.qdocconf)
project = QtNfc
description = Qt NFC Reference Documentation
diff --git a/src/nfc/qnearfieldmanager.h b/src/nfc/qnearfieldmanager.h
index 500b9631..22506e7e 100644
--- a/src/nfc/qnearfieldmanager.h
+++ b/src/nfc/qnearfieldmanager.h
@@ -99,7 +99,7 @@ public:
bool unregisterNdefMessageHandler(int handlerId);
Q_SIGNALS:
- void adapterStateChanged(AdapterState state);
+ void adapterStateChanged(QNearFieldManager::AdapterState state);
void targetDetected(QNearFieldTarget *target);
void targetLost(QNearFieldTarget *target);
diff --git a/src/nfc/qnearfieldmanager_emulator.cpp b/src/nfc/qnearfieldmanager_emulator.cpp
index 8a61a3a9..4b5e5e0c 100644
--- a/src/nfc/qnearfieldmanager_emulator.cpp
+++ b/src/nfc/qnearfieldmanager_emulator.cpp
@@ -49,10 +49,11 @@ QT_BEGIN_NAMESPACE
QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl()
{
- globalTagActivator->initialize();
+ TagActivator *activator = TagActivator::instance();
+ activator->initialize();
- connect(globalTagActivator, &TagActivator::tagActivated, this, &QNearFieldManagerPrivateImpl::tagActivated);
- connect(globalTagActivator, &TagActivator::tagDeactivated, this, &QNearFieldManagerPrivateImpl::tagDeactivated);
+ connect(activator, &TagActivator::tagActivated, this, &QNearFieldManagerPrivateImpl::tagActivated);
+ connect(activator, &TagActivator::tagDeactivated, this, &QNearFieldManagerPrivateImpl::tagDeactivated);
}
QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl()
@@ -66,7 +67,7 @@ bool QNearFieldManagerPrivateImpl::isAvailable() const
void QNearFieldManagerPrivateImpl::reset()
{
- globalTagActivator->reset();
+ TagActivator::instance()->reset();
}
void QNearFieldManagerPrivateImpl::tagActivated(TagBase *tag)
diff --git a/src/nfc/qnearfieldtagtype2.cpp b/src/nfc/qnearfieldtagtype2.cpp
index 24ff8280..492dc5e3 100644
--- a/src/nfc/qnearfieldtagtype2.cpp
+++ b/src/nfc/qnearfieldtagtype2.cpp
@@ -307,9 +307,7 @@ void QNearFieldTagType2::timerEvent(QTimerEvent *event)
killTimer(event->timerId());
- QMutableMapIterator<QNearFieldTarget::RequestId, SectorSelectState> i(d->m_pendingSectorSelectCommands);
- while (i.hasNext()) {
- i.next();
+ for (auto i = d->m_pendingSectorSelectCommands.begin(), end = d->m_pendingSectorSelectCommands.end(); i != end; ++i) {
SectorSelectState &state = i.value();
@@ -318,8 +316,7 @@ void QNearFieldTagType2::timerEvent(QTimerEvent *event)
setResponseForRequest(i.key(), true);
- i.remove();
-
+ d->m_pendingSectorSelectCommands.erase(i);
break;
}
}
diff --git a/src/nfc/qnearfieldtarget.cpp b/src/nfc/qnearfieldtarget.cpp
index e9a6fa11..7d83db78 100644
--- a/src/nfc/qnearfieldtarget.cpp
+++ b/src/nfc/qnearfieldtarget.cpp
@@ -47,7 +47,7 @@
#include <QtCore/QDebug>
-#include <QTime>
+#include <QElapsedTimer>
#include <QCoreApplication>
QT_BEGIN_NAMESPACE
@@ -462,7 +462,7 @@ bool QNearFieldTarget::waitForRequestCompleted(const RequestId &id, int msecs)
{
Q_D(QNearFieldTarget);
- QTime timer;
+ QElapsedTimer timer;
timer.start();
do {
@@ -497,13 +497,12 @@ void QNearFieldTarget::setResponseForRequest(const QNearFieldTarget::RequestId &
{
Q_D(QNearFieldTarget);
- QMutableMapIterator<RequestId, QVariant> i(d->m_decodedResponses);
- while (i.hasNext()) {
- i.next();
-
+ for (auto i = d->m_decodedResponses.begin(), end = d->m_decodedResponses.end(); i != end; /* erasing */) {
// no more external references
if (i.key().refCount() == 1)
- i.remove();
+ i = d->m_decodedResponses.erase(i);
+ else
+ ++i;
}
d->m_decodedResponses.insert(id, response);
diff --git a/src/nfc/qnearfieldtarget_emulator.cpp b/src/nfc/qnearfieldtarget_emulator.cpp
index 0723b655..aecd743e 100644
--- a/src/nfc/qnearfieldtarget_emulator.cpp
+++ b/src/nfc/qnearfieldtarget_emulator.cpp
@@ -52,6 +52,8 @@ QT_BEGIN_NAMESPACE
static QMutex tagMutex;
static QMap<TagBase *, bool> tagMap;
+Q_GLOBAL_STATIC(TagActivator, globalTagActivator);
+
TagType1::TagType1(TagBase *tag, QObject *parent)
: QNearFieldTagType1(parent), m_tag(tag)
{
@@ -247,6 +249,11 @@ void TagActivator::reset()
tagMap.clear();
}
+TagActivator *TagActivator::instance()
+{
+ return globalTagActivator();
+}
+
void TagActivator::timerEvent(QTimerEvent *e)
{
Q_UNUSED(e);
diff --git a/src/nfc/qnearfieldtarget_emulator_p.h b/src/nfc/qnearfieldtarget_emulator_p.h
index 1b9f7bdb..70a67be8 100644
--- a/src/nfc/qnearfieldtarget_emulator_p.h
+++ b/src/nfc/qnearfieldtarget_emulator_p.h
@@ -122,8 +122,6 @@ private:
int timerId;
};
-Q_GLOBAL_STATIC(TagActivator, globalTagActivator);
-
QT_END_NAMESPACE
#endif // QNEARFIELDTARGET_EMULATOR_P_H
diff --git a/src/nfc/qqmlndefrecord.cpp b/src/nfc/qqmlndefrecord.cpp
index bc3667fe..5a96bec8 100644
--- a/src/nfc/qqmlndefrecord.cpp
+++ b/src/nfc/qqmlndefrecord.cpp
@@ -215,10 +215,9 @@ QQmlNdefRecord *qNewDeclarativeNdefRecordForNdefRecord(const QNdefRecord &record
{
const QString urn = urnForRecordType(record.typeNameFormat(), record.type());
- QMapIterator<QString, const QMetaObject *> i(*registeredNdefRecordTypes());
- while (i.hasNext()) {
- i.next();
+ const auto *rt = registeredNdefRecordTypes();
+ for (auto i = rt->cbegin(), end = rt->cend(); i != end; ++i) {
QRegularExpression rx(QRegularExpression::anchoredPattern(i.key()));
if (!rx.match(urn).hasMatch())
continue;
diff --git a/tests/auto/bic/data/QtBluetooth.5.13.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtBluetooth.5.13.0.linux-gcc-amd64.txt
new file mode 100644
index 00000000..ef61ed6f
--- /dev/null
+++ b/tests/auto/bic/data/QtBluetooth.5.13.0.linux-gcc-amd64.txt
@@ -0,0 +1,5423 @@
+Class std::__failure_type
+ size=1 align=1
+ base size=0 base align=1
+std::__failure_type (0x0x7f5ec289f600) 0 empty
+
+Class std::__do_is_destructible_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_destructible_impl (0x0x7f5ec28f7d80) 0 empty
+
+Class std::__do_is_nt_destructible_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_nt_destructible_impl (0x0x7f5ec2922000) 0 empty
+
+Class std::__do_is_default_constructible_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_default_constructible_impl (0x0x7f5ec2922240) 0 empty
+
+Class std::__do_is_static_castable_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_static_castable_impl (0x0x7f5ec2922480) 0 empty
+
+Class std::__do_is_direct_constructible_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_direct_constructible_impl (0x0x7f5ec2922600) 0 empty
+
+Class std::__do_is_nary_constructible_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_nary_constructible_impl (0x0x7f5ec29229c0) 0 empty
+
+Class std::__do_is_implicitly_default_constructible_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_implicitly_default_constructible_impl (0x0x7f5ec2960ae0) 0 empty
+
+Class std::__do_common_type_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_common_type_impl (0x0x7f5ec29e41e0) 0 empty
+
+Class std::__do_member_type_wrapper
+ size=1 align=1
+ base size=0 base align=1
+std::__do_member_type_wrapper (0x0x7f5ec29e42a0) 0 empty
+
+Class std::__invoke_memfun_ref
+ size=1 align=1
+ base size=0 base align=1
+std::__invoke_memfun_ref (0x0x7f5ec29e4660) 0 empty
+
+Class std::__invoke_memfun_deref
+ size=1 align=1
+ base size=0 base align=1
+std::__invoke_memfun_deref (0x0x7f5ec29e46c0) 0 empty
+
+Class std::__invoke_memobj_ref
+ size=1 align=1
+ base size=0 base align=1
+std::__invoke_memobj_ref (0x0x7f5ec29e4720) 0 empty
+
+Class std::__invoke_memobj_deref
+ size=1 align=1
+ base size=0 base align=1
+std::__invoke_memobj_deref (0x0x7f5ec29e4780) 0 empty
+
+Class std::__invoke_other
+ size=1 align=1
+ base size=0 base align=1
+std::__invoke_other (0x0x7f5ec29e47e0) 0 empty
+
+Class std::__result_of_memfun_ref_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__result_of_memfun_ref_impl (0x0x7f5ec29e48a0) 0 empty
+
+Class std::__result_of_memfun_deref_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__result_of_memfun_deref_impl (0x0x7f5ec29e4960) 0 empty
+
+Class std::__result_of_memobj_ref_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__result_of_memobj_ref_impl (0x0x7f5ec29e4a20) 0 empty
+
+Class std::__result_of_memobj_deref_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__result_of_memobj_deref_impl (0x0x7f5ec29e4ae0) 0 empty
+
+Class std::__result_of_other_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__result_of_other_impl (0x0x7f5ec29e4e40) 0 empty
+
+Class std::__swappable_details::__do_is_swappable_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__swappable_details::__do_is_swappable_impl (0x0x7f5ec26211e0) 0 empty
+
+Class std::__swappable_details::__do_is_nothrow_swappable_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__swappable_details::__do_is_nothrow_swappable_impl (0x0x7f5ec2621240) 0 empty
+
+Class std::__nonesuch
+ size=1 align=1
+ base size=0 base align=1
+std::__nonesuch (0x0x7f5ec26217e0) 0 empty
+
+Class std::piecewise_construct_t
+ size=1 align=1
+ base size=0 base align=1
+std::piecewise_construct_t (0x0x7f5ec2621e40) 0 empty
+
+Class std::__nonesuch_no_braces
+ size=1 align=1
+ base size=1 base align=1
+std::__nonesuch_no_braces (0x0x7f5ec261c680) 0 empty
+ std::__nonesuch (0x0x7f5ec2667360) 0 empty
+
+Class std::__true_type
+ size=1 align=1
+ base size=0 base align=1
+std::__true_type (0x0x7f5ec26b4cc0) 0 empty
+
+Class std::__false_type
+ size=1 align=1
+ base size=0 base align=1
+std::__false_type (0x0x7f5ec26b4d20) 0 empty
+
+Class std::input_iterator_tag
+ size=1 align=1
+ base size=0 base align=1
+std::input_iterator_tag (0x0x7f5ec2712a20) 0 empty
+
+Class std::output_iterator_tag
+ size=1 align=1
+ base size=0 base align=1
+std::output_iterator_tag (0x0x7f5ec2712a80) 0 empty
+
+Class std::forward_iterator_tag
+ size=1 align=1
+ base size=1 base align=1
+std::forward_iterator_tag (0x0x7f5ec261cb60) 0 empty
+ std::input_iterator_tag (0x0x7f5ec2712ae0) 0 empty
+
+Class std::bidirectional_iterator_tag
+ size=1 align=1
+ base size=1 base align=1
+std::bidirectional_iterator_tag (0x0x7f5ec261cbc8) 0 empty
+ std::forward_iterator_tag (0x0x7f5ec261cc30) 0 empty
+ std::input_iterator_tag (0x0x7f5ec2712b40) 0 empty
+
+Class std::random_access_iterator_tag
+ size=1 align=1
+ base size=1 base align=1
+std::random_access_iterator_tag (0x0x7f5ec261cc98) 0 empty
+ std::bidirectional_iterator_tag (0x0x7f5ec261cd00) 0 empty
+ std::forward_iterator_tag (0x0x7f5ec261cd68) 0 empty
+ std::input_iterator_tag (0x0x7f5ec2712ba0) 0 empty
+
+Class __gnu_cxx::__ops::_Iter_less_iter
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__ops::_Iter_less_iter (0x0x7f5ec27c56c0) 0 empty
+
+Class __gnu_cxx::__ops::_Iter_less_val
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__ops::_Iter_less_val (0x0x7f5ec27c57e0) 0 empty
+
+Class __gnu_cxx::__ops::_Val_less_iter
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__ops::_Val_less_iter (0x0x7f5ec27c5ae0) 0 empty
+
+Class __gnu_cxx::__ops::_Iter_equal_to_iter
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__ops::_Iter_equal_to_iter (0x0x7f5ec27c5de0) 0 empty
+
+Class __gnu_cxx::__ops::_Iter_equal_to_val
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__ops::_Iter_equal_to_val (0x0x7f5ec27c5f00) 0 empty
+
+Class __locale_struct
+ size=232 align=8
+ base size=232 base align=8
+__locale_struct (0x0x7f5ec247f240) 0
+
+Class timeval
+ size=16 align=8
+ base size=16 base align=8
+timeval (0x0x7f5ec247f540) 0
+
+Class timespec
+ size=16 align=8
+ base size=16 base align=8
+timespec (0x0x7f5ec247f5a0) 0
+
+Class __pthread_rwlock_arch_t
+ size=56 align=8
+ base size=56 base align=8
+__pthread_rwlock_arch_t (0x0x7f5ec247f660) 0
+
+Class __pthread_internal_list
+ size=16 align=8
+ base size=16 base align=8
+__pthread_internal_list (0x0x7f5ec247f6c0) 0
+
+Class __pthread_mutex_s
+ size=40 align=8
+ base size=40 base align=8
+__pthread_mutex_s (0x0x7f5ec247f720) 0
+
+Class __pthread_cond_s
+ size=48 align=8
+ base size=48 base align=8
+__pthread_cond_s (0x0x7f5ec247f780) 0
+
+Class pthread_attr_t
+ size=56 align=8
+ base size=56 base align=8
+pthread_attr_t (0x0x7f5ec247fa20) 0
+
+Class random_data
+ size=48 align=8
+ base size=48 base align=8
+random_data (0x0x7f5ec247fcc0) 0
+
+Class drand48_data
+ size=24 align=8
+ base size=24 base align=8
+drand48_data (0x0x7f5ec247fd20) 0
+
+Vtable for std::exception
+std::exception::_ZTVSt9exception: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt9exception)
+16 (int (*)(...))std::exception::~exception
+24 (int (*)(...))std::exception::~exception
+32 (int (*)(...))std::exception::what
+
+Class std::exception
+ size=8 align=8
+ base size=8 base align=8
+std::exception (0x0x7f5ec24e1ae0) 0 nearly-empty
+ vptr=((& std::exception::_ZTVSt9exception) + 16)
+
+Vtable for std::bad_exception
+std::bad_exception::_ZTVSt13bad_exception: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt13bad_exception)
+16 (int (*)(...))std::bad_exception::~bad_exception
+24 (int (*)(...))std::bad_exception::~bad_exception
+32 (int (*)(...))std::bad_exception::what
+
+Class std::bad_exception
+ size=8 align=8
+ base size=8 base align=8
+std::bad_exception (0x0x7f5ec27870d0) 0 nearly-empty
+ vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16)
+ std::exception (0x0x7f5ec24e1cc0) 0 nearly-empty
+ primary-for std::bad_exception (0x0x7f5ec27870d0)
+
+Vtable for std::type_info
+std::type_info::_ZTVSt9type_info: 8 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt9type_info)
+16 (int (*)(...))std::type_info::~type_info
+24 (int (*)(...))std::type_info::~type_info
+32 (int (*)(...))std::type_info::__is_pointer_p
+40 (int (*)(...))std::type_info::__is_function_p
+48 (int (*)(...))std::type_info::__do_catch
+56 (int (*)(...))std::type_info::__do_upcast
+
+Class std::type_info
+ size=16 align=8
+ base size=16 base align=8
+std::type_info (0x0x7f5ec24e1ea0) 0
+ vptr=((& std::type_info::_ZTVSt9type_info) + 16)
+
+Vtable for std::bad_cast
+std::bad_cast::_ZTVSt8bad_cast: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt8bad_cast)
+16 (int (*)(...))std::bad_cast::~bad_cast
+24 (int (*)(...))std::bad_cast::~bad_cast
+32 (int (*)(...))std::bad_cast::what
+
+Class std::bad_cast
+ size=8 align=8
+ base size=8 base align=8
+std::bad_cast (0x0x7f5ec2787138) 0 nearly-empty
+ vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16)
+ std::exception (0x0x7f5ec257e2a0) 0 nearly-empty
+ primary-for std::bad_cast (0x0x7f5ec2787138)
+
+Vtable for std::bad_typeid
+std::bad_typeid::_ZTVSt10bad_typeid: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt10bad_typeid)
+16 (int (*)(...))std::bad_typeid::~bad_typeid
+24 (int (*)(...))std::bad_typeid::~bad_typeid
+32 (int (*)(...))std::bad_typeid::what
+
+Class std::bad_typeid
+ size=8 align=8
+ base size=8 base align=8
+std::bad_typeid (0x0x7f5ec27871a0) 0 nearly-empty
+ vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16)
+ std::exception (0x0x7f5ec257e480) 0 nearly-empty
+ primary-for std::bad_typeid (0x0x7f5ec27871a0)
+
+Class std::__exception_ptr::exception_ptr
+ size=8 align=8
+ base size=8 base align=8
+std::__exception_ptr::exception_ptr (0x0x7f5ec257e660) 0
+
+Vtable for std::nested_exception
+std::nested_exception::_ZTVSt16nested_exception: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt16nested_exception)
+16 (int (*)(...))std::nested_exception::~nested_exception
+24 (int (*)(...))std::nested_exception::~nested_exception
+
+Class std::nested_exception
+ size=16 align=8
+ base size=16 base align=8
+std::nested_exception (0x0x7f5ec257ec00) 0
+ vptr=((& std::nested_exception::_ZTVSt16nested_exception) + 16)
+
+Vtable for std::bad_alloc
+std::bad_alloc::_ZTVSt9bad_alloc: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt9bad_alloc)
+16 (int (*)(...))std::bad_alloc::~bad_alloc
+24 (int (*)(...))std::bad_alloc::~bad_alloc
+32 (int (*)(...))std::bad_alloc::what
+
+Class std::bad_alloc
+ size=8 align=8
+ base size=8 base align=8
+std::bad_alloc (0x0x7f5ec2787208) 0 nearly-empty
+ vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16)
+ std::exception (0x0x7f5ec25b1300) 0 nearly-empty
+ primary-for std::bad_alloc (0x0x7f5ec2787208)
+
+Vtable for std::bad_array_new_length
+std::bad_array_new_length::_ZTVSt20bad_array_new_length: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt20bad_array_new_length)
+16 (int (*)(...))std::bad_array_new_length::~bad_array_new_length
+24 (int (*)(...))std::bad_array_new_length::~bad_array_new_length
+32 (int (*)(...))std::bad_array_new_length::what
+
+Class std::bad_array_new_length
+ size=8 align=8
+ base size=8 base align=8
+std::bad_array_new_length (0x0x7f5ec2787270) 0 nearly-empty
+ vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16)
+ std::bad_alloc (0x0x7f5ec27872d8) 0 nearly-empty
+ primary-for std::bad_array_new_length (0x0x7f5ec2787270)
+ std::exception (0x0x7f5ec25b14e0) 0 nearly-empty
+ primary-for std::bad_alloc (0x0x7f5ec27872d8)
+
+Class std::nothrow_t
+ size=1 align=1
+ base size=0 base align=1
+std::nothrow_t (0x0x7f5ec25b16c0) 0 empty
+
+Class std::__allocator_traits_base
+ size=1 align=1
+ base size=0 base align=1
+std::__allocator_traits_base (0x0x7f5ec25b18a0) 0 empty
+
+Class std::__numeric_limits_base
+ size=1 align=1
+ base size=0 base align=1
+std::__numeric_limits_base (0x0x7f5ec222fd80) 0 empty
+
+Class qIsNull(double)::U
+ size=8 align=8
+ base size=8 base align=8
+qIsNull(double)::U (0x0x7f5ec2408840) 0
+
+Class qIsNull(float)::U
+ size=4 align=4
+ base size=4 base align=4
+qIsNull(float)::U (0x0x7f5ec2408900) 0
+
+Class QSysInfo
+ size=1 align=1
+ base size=0 base align=1
+QSysInfo (0x0x7f5ec1ec92a0) 0 empty
+
+Class QMessageLogContext
+ size=32 align=8
+ base size=32 base align=8
+QMessageLogContext (0x0x7f5ec1ec93c0) 0
+
+Class QMessageLogger
+ size=32 align=8
+ base size=32 base align=8
+QMessageLogger (0x0x7f5ec1ec9720) 0
+
+Class QFlag
+ size=4 align=4
+ base size=4 base align=4
+QFlag (0x0x7f5ec1ec9c60) 0
+
+Class QIncompatibleFlag
+ size=4 align=4
+ base size=4 base align=4
+QIncompatibleFlag (0x0x7f5ec1f42420) 0
+
+Class std::__atomic_flag_base
+ size=1 align=1
+ base size=1 base align=1
+std::__atomic_flag_base (0x0x7f5ec1fd8840) 0
+
+Class std::atomic_flag
+ size=1 align=1
+ base size=1 base align=1
+std::atomic_flag (0x0x7f5ec1f86138) 0
+ std::__atomic_flag_base (0x0x7f5ec1fd88a0) 0
+
+Class QAtomicInt
+ size=4 align=4
+ base size=4 base align=4
+QAtomicInt (0x0x7f5ec1f86888) 0
+ QAtomicInteger<int> (0x0x7f5ec1f868f0) 0
+ QBasicAtomicInteger<int> (0x0x7f5ec1b0b840) 0
+
+Class QInternal
+ size=1 align=1
+ base size=0 base align=1
+QInternal (0x0x7f5ec1729b40) 0 empty
+
+Class QtPrivate::QSlotObjectBase
+ size=16 align=8
+ base size=16 base align=8
+QtPrivate::QSlotObjectBase (0x0x7f5ec1796120) 0
+
+Class QGenericArgument
+ size=16 align=8
+ base size=16 base align=8
+QGenericArgument (0x0x7f5ec1796840) 0
+
+Class QGenericReturnArgument
+ size=16 align=8
+ base size=16 base align=8
+QGenericReturnArgument (0x0x7f5ec177c478) 0
+ QGenericArgument (0x0x7f5ec1796ae0) 0
+
+Class QMetaObject
+ size=48 align=8
+ base size=48 base align=8
+QMetaObject (0x0x7f5ec1796f00) 0
+
+Class QMetaObject::Connection
+ size=8 align=8
+ base size=8 base align=8
+QMetaObject::Connection (0x0x7f5ec17f1360) 0
+
+Class QLatin1Char
+ size=1 align=1
+ base size=1 base align=1
+QLatin1Char (0x0x7f5ec145ae40) 0
+
+Class QChar
+ size=2 align=2
+ base size=2 base align=2
+QChar (0x0x7f5ec147c120) 0
+
+Class QtPrivate::RefCount
+ size=4 align=4
+ base size=4 base align=4
+QtPrivate::RefCount (0x0x7f5ec1528f00) 0
+
+Class QArrayData
+ size=24 align=8
+ base size=24 base align=8
+QArrayData (0x0x7f5ec154b2a0) 0
+
+Class QtPrivate::QContainerImplHelper
+ size=1 align=1
+ base size=0 base align=1
+QtPrivate::QContainerImplHelper (0x0x7f5ec15ac5a0) 0 empty
+
+Class lconv
+ size=96 align=8
+ base size=96 base align=8
+lconv (0x0x7f5ec125bde0) 0
+
+Vtable for __cxxabiv1::__forced_unwind
+__cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN10__cxxabiv115__forced_unwindE)
+16 0
+24 0
+32 (int (*)(...))__cxa_pure_virtual
+
+Class __cxxabiv1::__forced_unwind
+ size=8 align=8
+ base size=8 base align=8
+__cxxabiv1::__forced_unwind (0x0x7f5ec125bea0) 0 nearly-empty
+ vptr=((& __cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE) + 16)
+
+Class sched_param
+ size=4 align=4
+ base size=4 base align=4
+sched_param (0x0x7f5ec1353000) 0
+
+Class timex
+ size=208 align=8
+ base size=208 base align=8
+timex (0x0x7f5ec13530c0) 0
+
+Class tm
+ size=56 align=8
+ base size=56 base align=8
+tm (0x0x7f5ec1353120) 0
+
+Class itimerspec
+ size=32 align=8
+ base size=32 base align=8
+itimerspec (0x0x7f5ec1353180) 0
+
+Class _pthread_cleanup_buffer
+ size=32 align=8
+ base size=32 base align=8
+_pthread_cleanup_buffer (0x0x7f5ec13531e0) 0
+
+Class __pthread_cleanup_frame
+ size=24 align=8
+ base size=24 base align=8
+__pthread_cleanup_frame (0x0x7f5ec1353300) 0
+
+Class __pthread_cleanup_class
+ size=24 align=8
+ base size=24 base align=8
+__pthread_cleanup_class (0x0x7f5ec1353360) 0
+
+Class _IO_marker
+ size=24 align=8
+ base size=24 base align=8
+_IO_marker (0x0x7f5ec1097300) 0
+
+Class _IO_FILE
+ size=216 align=8
+ base size=216 base align=8
+_IO_FILE (0x0x7f5ec1097360) 0
+
+Class std::_Hash_impl
+ size=1 align=1
+ base size=0 base align=1
+std::_Hash_impl (0x0x7f5ec0e493c0) 0 empty
+
+Class std::_Fnv_hash_impl
+ size=1 align=1
+ base size=0 base align=1
+std::_Fnv_hash_impl (0x0x7f5ec0e49540) 0 empty
+
+Class std::locale
+ size=8 align=8
+ base size=8 base align=8
+std::locale (0x0x7f5ec0fc36c0) 0
+
+Vtable for std::locale::facet
+std::locale::facet::_ZTVNSt6locale5facetE: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt6locale5facetE)
+16 (int (*)(...))std::locale::facet::~facet
+24 (int (*)(...))std::locale::facet::~facet
+
+Class std::locale::facet
+ size=16 align=8
+ base size=12 base align=8
+std::locale::facet (0x0x7f5ec0fc3a80) 0
+ vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16)
+
+Class std::locale::id
+ size=8 align=8
+ base size=8 base align=8
+std::locale::id (0x0x7f5ec0fc3d20) 0
+
+Class std::locale::_Impl
+ size=40 align=8
+ base size=40 base align=8
+std::locale::_Impl (0x0x7f5ec0fc3f00) 0
+
+Class std::__cow_string
+ size=8 align=8
+ base size=8 base align=8
+std::__cow_string (0x0x7f5ec0c1ff00) 0
+
+Vtable for std::logic_error
+std::logic_error::_ZTVSt11logic_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt11logic_error)
+16 (int (*)(...))std::logic_error::~logic_error
+24 (int (*)(...))std::logic_error::~logic_error
+32 (int (*)(...))std::logic_error::what
+
+Class std::logic_error
+ size=16 align=8
+ base size=16 base align=8
+std::logic_error (0x0x7f5ec0c29410) 0
+ vptr=((& std::logic_error::_ZTVSt11logic_error) + 16)
+ std::exception (0x0x7f5ec0c67000) 0 nearly-empty
+ primary-for std::logic_error (0x0x7f5ec0c29410)
+
+Vtable for std::domain_error
+std::domain_error::_ZTVSt12domain_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt12domain_error)
+16 (int (*)(...))std::domain_error::~domain_error
+24 (int (*)(...))std::domain_error::~domain_error
+32 (int (*)(...))std::logic_error::what
+
+Class std::domain_error
+ size=16 align=8
+ base size=16 base align=8
+std::domain_error (0x0x7f5ec0c29478) 0
+ vptr=((& std::domain_error::_ZTVSt12domain_error) + 16)
+ std::logic_error (0x0x7f5ec0c294e0) 0
+ primary-for std::domain_error (0x0x7f5ec0c29478)
+ std::exception (0x0x7f5ec0c67060) 0 nearly-empty
+ primary-for std::logic_error (0x0x7f5ec0c294e0)
+
+Vtable for std::invalid_argument
+std::invalid_argument::_ZTVSt16invalid_argument: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt16invalid_argument)
+16 (int (*)(...))std::invalid_argument::~invalid_argument
+24 (int (*)(...))std::invalid_argument::~invalid_argument
+32 (int (*)(...))std::logic_error::what
+
+Class std::invalid_argument
+ size=16 align=8
+ base size=16 base align=8
+std::invalid_argument (0x0x7f5ec0c29548) 0
+ vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16)
+ std::logic_error (0x0x7f5ec0c295b0) 0
+ primary-for std::invalid_argument (0x0x7f5ec0c29548)
+ std::exception (0x0x7f5ec0c670c0) 0 nearly-empty
+ primary-for std::logic_error (0x0x7f5ec0c295b0)
+
+Vtable for std::length_error
+std::length_error::_ZTVSt12length_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt12length_error)
+16 (int (*)(...))std::length_error::~length_error
+24 (int (*)(...))std::length_error::~length_error
+32 (int (*)(...))std::logic_error::what
+
+Class std::length_error
+ size=16 align=8
+ base size=16 base align=8
+std::length_error (0x0x7f5ec0c29618) 0
+ vptr=((& std::length_error::_ZTVSt12length_error) + 16)
+ std::logic_error (0x0x7f5ec0c29680) 0
+ primary-for std::length_error (0x0x7f5ec0c29618)
+ std::exception (0x0x7f5ec0c67120) 0 nearly-empty
+ primary-for std::logic_error (0x0x7f5ec0c29680)
+
+Vtable for std::out_of_range
+std::out_of_range::_ZTVSt12out_of_range: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt12out_of_range)
+16 (int (*)(...))std::out_of_range::~out_of_range
+24 (int (*)(...))std::out_of_range::~out_of_range
+32 (int (*)(...))std::logic_error::what
+
+Class std::out_of_range
+ size=16 align=8
+ base size=16 base align=8
+std::out_of_range (0x0x7f5ec0c296e8) 0
+ vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16)
+ std::logic_error (0x0x7f5ec0c29750) 0
+ primary-for std::out_of_range (0x0x7f5ec0c296e8)
+ std::exception (0x0x7f5ec0c67180) 0 nearly-empty
+ primary-for std::logic_error (0x0x7f5ec0c29750)
+
+Vtable for std::runtime_error
+std::runtime_error::_ZTVSt13runtime_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt13runtime_error)
+16 (int (*)(...))std::runtime_error::~runtime_error
+24 (int (*)(...))std::runtime_error::~runtime_error
+32 (int (*)(...))std::runtime_error::what
+
+Class std::runtime_error
+ size=16 align=8
+ base size=16 base align=8
+std::runtime_error (0x0x7f5ec0c297b8) 0
+ vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16)
+ std::exception (0x0x7f5ec0c671e0) 0 nearly-empty
+ primary-for std::runtime_error (0x0x7f5ec0c297b8)
+
+Vtable for std::range_error
+std::range_error::_ZTVSt11range_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt11range_error)
+16 (int (*)(...))std::range_error::~range_error
+24 (int (*)(...))std::range_error::~range_error
+32 (int (*)(...))std::runtime_error::what
+
+Class std::range_error
+ size=16 align=8
+ base size=16 base align=8
+std::range_error (0x0x7f5ec0c29820) 0
+ vptr=((& std::range_error::_ZTVSt11range_error) + 16)
+ std::runtime_error (0x0x7f5ec0c29888) 0
+ primary-for std::range_error (0x0x7f5ec0c29820)
+ std::exception (0x0x7f5ec0c67240) 0 nearly-empty
+ primary-for std::runtime_error (0x0x7f5ec0c29888)
+
+Vtable for std::overflow_error
+std::overflow_error::_ZTVSt14overflow_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt14overflow_error)
+16 (int (*)(...))std::overflow_error::~overflow_error
+24 (int (*)(...))std::overflow_error::~overflow_error
+32 (int (*)(...))std::runtime_error::what
+
+Class std::overflow_error
+ size=16 align=8
+ base size=16 base align=8
+std::overflow_error (0x0x7f5ec0c298f0) 0
+ vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16)
+ std::runtime_error (0x0x7f5ec0c29958) 0
+ primary-for std::overflow_error (0x0x7f5ec0c298f0)
+ std::exception (0x0x7f5ec0c672a0) 0 nearly-empty
+ primary-for std::runtime_error (0x0x7f5ec0c29958)
+
+Vtable for std::underflow_error
+std::underflow_error::_ZTVSt15underflow_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt15underflow_error)
+16 (int (*)(...))std::underflow_error::~underflow_error
+24 (int (*)(...))std::underflow_error::~underflow_error
+32 (int (*)(...))std::runtime_error::what
+
+Class std::underflow_error
+ size=16 align=8
+ base size=16 base align=8
+std::underflow_error (0x0x7f5ec0c299c0) 0
+ vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16)
+ std::runtime_error (0x0x7f5ec0c29a28) 0
+ primary-for std::underflow_error (0x0x7f5ec0c299c0)
+ std::exception (0x0x7f5ec0c67300) 0 nearly-empty
+ primary-for std::runtime_error (0x0x7f5ec0c29a28)
+
+Vtable for std::_V2::error_category
+std::_V2::error_category::_ZTVNSt3_V214error_categoryE: 10 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt3_V214error_categoryE)
+16 0
+24 0
+32 (int (*)(...))__cxa_pure_virtual
+40 (int (*)(...))std::_V2::error_category::_M_message
+48 (int (*)(...))__cxa_pure_virtual
+56 (int (*)(...))std::_V2::error_category::default_error_condition
+64 (int (*)(...))std::_V2::error_category::equivalent
+72 (int (*)(...))std::_V2::error_category::equivalent
+
+Class std::_V2::error_category
+ size=8 align=8
+ base size=8 base align=8
+std::_V2::error_category (0x0x7f5ec0c67480) 0 nearly-empty
+ vptr=((& std::_V2::error_category::_ZTVNSt3_V214error_categoryE) + 16)
+
+Class std::error_code
+ size=16 align=8
+ base size=16 base align=8
+std::error_code (0x0x7f5ec0c677e0) 0
+
+Class std::error_condition
+ size=16 align=8
+ base size=16 base align=8
+std::error_condition (0x0x7f5ec0cb6060) 0
+
+Vtable for std::system_error
+std::system_error::_ZTVSt12system_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt12system_error)
+16 (int (*)(...))std::system_error::~system_error
+24 (int (*)(...))std::system_error::~system_error
+32 (int (*)(...))std::runtime_error::what
+
+Class std::system_error
+ size=32 align=8
+ base size=32 base align=8
+std::system_error (0x0x7f5ec0c29e38) 0
+ vptr=((& std::system_error::_ZTVSt12system_error) + 16)
+ std::runtime_error (0x0x7f5ec0c29ea0) 0
+ primary-for std::system_error (0x0x7f5ec0c29e38)
+ std::exception (0x0x7f5ec0cb6c00) 0 nearly-empty
+ primary-for std::runtime_error (0x0x7f5ec0c29ea0)
+
+Vtable for std::ios_base::failure
+std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt8ios_base7failureB5cxx11E)
+16 (int (*)(...))std::ios_base::failure::~failure
+24 (int (*)(...))std::ios_base::failure::~failure
+32 (int (*)(...))std::ios_base::failure::what
+
+Class std::ios_base::failure
+ size=32 align=8
+ base size=32 base align=8
+std::ios_base::failure (0x0x7f5ec0cf9138) 0
+ vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16)
+ std::system_error (0x0x7f5ec0cf91a0) 0
+ primary-for std::ios_base::failure (0x0x7f5ec0cf9138)
+ std::runtime_error (0x0x7f5ec0cf9208) 0
+ primary-for std::system_error (0x0x7f5ec0cf91a0)
+ std::exception (0x0x7f5ec0d121e0) 0 nearly-empty
+ primary-for std::runtime_error (0x0x7f5ec0cf9208)
+
+Class std::ios_base::_Callback_list
+ size=24 align=8
+ base size=24 base align=8
+std::ios_base::_Callback_list (0x0x7f5ec0d12240) 0
+
+Class std::ios_base::_Words
+ size=16 align=8
+ base size=16 base align=8
+std::ios_base::_Words (0x0x7f5ec0d122a0) 0
+
+Class std::ios_base::Init
+ size=1 align=1
+ base size=0 base align=1
+std::ios_base::Init (0x0x7f5ec0d12300) 0 empty
+
+Vtable for std::ios_base
+std::ios_base::_ZTVSt8ios_base: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt8ios_base)
+16 (int (*)(...))std::ios_base::~ios_base
+24 (int (*)(...))std::ios_base::~ios_base
+
+Class std::ios_base
+ size=216 align=8
+ base size=216 base align=8
+std::ios_base (0x0x7f5ec0d12180) 0
+ vptr=((& std::ios_base::_ZTVSt8ios_base) + 16)
+
+Class std::ctype_base
+ size=1 align=1
+ base size=0 base align=1
+std::ctype_base (0x0x7f5ec0ddfc00) 0 empty
+
+Class std::__num_base
+ size=1 align=1
+ base size=0 base align=1
+std::__num_base (0x0x7f5ec0a88de0) 0 empty
+
+VTT for std::basic_ostream<char>
+std::basic_ostream<char>::_ZTTSo: 2 entries
+0 ((& std::basic_ostream<char>::_ZTVSo) + 24)
+8 ((& std::basic_ostream<char>::_ZTVSo) + 64)
+
+VTT for std::basic_ostream<wchar_t>
+std::basic_ostream<wchar_t>::_ZTTSt13basic_ostreamIwSt11char_traitsIwEE: 2 entries
+0 ((& std::basic_ostream<wchar_t>::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 24)
+8 ((& std::basic_ostream<wchar_t>::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 64)
+
+VTT for std::basic_istream<char>
+std::basic_istream<char>::_ZTTSi: 2 entries
+0 ((& std::basic_istream<char>::_ZTVSi) + 24)
+8 ((& std::basic_istream<char>::_ZTVSi) + 64)
+
+VTT for std::basic_istream<wchar_t>
+std::basic_istream<wchar_t>::_ZTTSt13basic_istreamIwSt11char_traitsIwEE: 2 entries
+0 ((& std::basic_istream<wchar_t>::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 24)
+8 ((& std::basic_istream<wchar_t>::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 64)
+
+Construction vtable for std::basic_istream<char> (0x0x7f5ec06178f0 instance) in std::basic_iostream<char>
+std::basic_iostream<char>::_ZTCSd0_Si: 10 entries
+0 24
+8 (int (*)(...))0
+16 (int (*)(...))(& _ZTISi)
+24 0
+32 0
+40 18446744073709551592
+48 (int (*)(...))-24
+56 (int (*)(...))(& _ZTISi)
+64 0
+72 0
+
+Construction vtable for std::basic_ostream<char> (0x0x7f5ec06179c0 instance) in std::basic_iostream<char>
+std::basic_iostream<char>::_ZTCSd16_So: 10 entries
+0 8
+8 (int (*)(...))0
+16 (int (*)(...))(& _ZTISo)
+24 0
+32 0
+40 18446744073709551608
+48 (int (*)(...))-8
+56 (int (*)(...))(& _ZTISo)
+64 0
+72 0
+
+VTT for std::basic_iostream<char>
+std::basic_iostream<char>::_ZTTSd: 7 entries
+0 ((& std::basic_iostream<char>::_ZTVSd) + 24)
+8 ((& std::basic_iostream<char>::_ZTCSd0_Si) + 24)
+16 ((& std::basic_iostream<char>::_ZTCSd0_Si) + 64)
+24 ((& std::basic_iostream<char>::_ZTCSd16_So) + 24)
+32 ((& std::basic_iostream<char>::_ZTCSd16_So) + 64)
+40 ((& std::basic_iostream<char>::_ZTVSd) + 104)
+48 ((& std::basic_iostream<char>::_ZTVSd) + 64)
+
+Construction vtable for std::basic_istream<wchar_t> (0x0x7f5ec0654680 instance) in std::basic_iostream<wchar_t>
+std::basic_iostream<wchar_t>::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E: 10 entries
+0 24
+8 (int (*)(...))0
+16 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE)
+24 0
+32 0
+40 18446744073709551592
+48 (int (*)(...))-24
+56 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE)
+64 0
+72 0
+
+Construction vtable for std::basic_ostream<wchar_t> (0x0x7f5ec0654750 instance) in std::basic_iostream<wchar_t>
+std::basic_iostream<wchar_t>::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E: 10 entries
+0 8
+8 (int (*)(...))0
+16 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE)
+24 0
+32 0
+40 18446744073709551608
+48 (int (*)(...))-8
+56 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE)
+64 0
+72 0
+
+VTT for std::basic_iostream<wchar_t>
+std::basic_iostream<wchar_t>::_ZTTSt14basic_iostreamIwSt11char_traitsIwEE: 7 entries
+0 ((& std::basic_iostream<wchar_t>::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 24)
+8 ((& std::basic_iostream<wchar_t>::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 24)
+16 ((& std::basic_iostream<wchar_t>::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 64)
+24 ((& std::basic_iostream<wchar_t>::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 24)
+32 ((& std::basic_iostream<wchar_t>::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 64)
+40 ((& std::basic_iostream<wchar_t>::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 104)
+48 ((& std::basic_iostream<wchar_t>::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 64)
+
+Class QByteArrayDataPtr
+ size=8 align=8
+ base size=8 base align=8
+QByteArrayDataPtr (0x0x7f5ec067f780) 0
+
+Class QByteArray
+ size=8 align=8
+ base size=8 base align=8
+QByteArray (0x0x7f5ec067f7e0) 0
+
+Class QByteRef
+ size=16 align=8
+ base size=12 base align=8
+QByteRef (0x0x7f5ec07adba0) 0
+
+Class QStringDataPtr
+ size=8 align=8
+ base size=8 base align=8
+QStringDataPtr (0x0x7f5ec0451a20) 0
+
+Class QStringView
+ size=16 align=8
+ base size=16 base align=8
+QStringView (0x0x7f5ec0451ea0) 0
+
+Class QLatin1String
+ size=16 align=8
+ base size=16 base align=8
+QLatin1String (0x0x7f5ec0521c60) 0
+
+Class QString::Null
+ size=1 align=1
+ base size=0 base align=1
+QString::Null (0x0x7f5ec05c26c0) 0 empty
+
+Class QString
+ size=8 align=8
+ base size=8 base align=8
+QString (0x0x7f5ec05c2660) 0
+
+Class QCharRef
+ size=16 align=8
+ base size=12 base align=8
+QCharRef (0x0x7f5ec03a5840) 0
+
+Class QStringRef
+ size=16 align=8
+ base size=16 base align=8
+QStringRef (0x0x7f5ec01430c0) 0
+
+Class QtPrivate::QHashCombine
+ size=1 align=1
+ base size=0 base align=1
+QtPrivate::QHashCombine (0x0x7f5ebff5e3c0) 0 empty
+
+Class QtPrivate::QHashCombineCommutative
+ size=1 align=1
+ base size=0 base align=1
+QtPrivate::QHashCombineCommutative (0x0x7f5ebff5e480) 0 empty
+
+Class std::_Bit_reference
+ size=16 align=8
+ base size=16 base align=8
+std::_Bit_reference (0x0x7f5ebfc1e960) 0
+
+Class std::_Bit_iterator_base
+ size=16 align=8
+ base size=12 base align=8
+std::_Bit_iterator_base (0x0x7f5ebfdd1a90) 0
+ std::iterator<std::random_access_iterator_tag, bool> (0x0x7f5ebfc400c0) 0 empty
+
+Class std::_Bit_iterator
+ size=16 align=8
+ base size=12 base align=8
+std::_Bit_iterator (0x0x7f5ebfdd1bc8) 0
+ std::_Bit_iterator_base (0x0x7f5ebfdd1c30) 0
+ std::iterator<std::random_access_iterator_tag, bool> (0x0x7f5ebfc40720) 0 empty
+
+Class std::_Bit_const_iterator
+ size=16 align=8
+ base size=12 base align=8
+std::_Bit_const_iterator (0x0x7f5ebfdd1c98) 0
+ std::_Bit_iterator_base (0x0x7f5ebfdd1d00) 0
+ std::iterator<std::random_access_iterator_tag, bool> (0x0x7f5ebfc40f00) 0 empty
+
+Class std::__detail::_List_node_base
+ size=16 align=8
+ base size=16 base align=8
+std::__detail::_List_node_base (0x0x7f5ebfa595a0) 0
+
+Class QListData::NotArrayCompatibleLayout
+ size=1 align=1
+ base size=0 base align=1
+QListData::NotArrayCompatibleLayout (0x0x7f5ebfb21360) 0 empty
+
+Class QListData::NotIndirectLayout
+ size=1 align=1
+ base size=0 base align=1
+QListData::NotIndirectLayout (0x0x7f5ebfb213c0) 0 empty
+
+Class QListData::ArrayCompatibleLayout
+ size=1 align=1
+ base size=1 base align=1
+QListData::ArrayCompatibleLayout (0x0x7f5ebfce77b8) 0 empty
+ QListData::NotIndirectLayout (0x0x7f5ebfb21420) 0 empty
+
+Class QListData::InlineWithPaddingLayout
+ size=1 align=1
+ base size=1 base align=1
+QListData::InlineWithPaddingLayout (0x0x7f5ebfa9a380) 0 empty
+ QListData::NotArrayCompatibleLayout (0x0x7f5ebfb21480) 0 empty
+ QListData::NotIndirectLayout (0x0x7f5ebfb214e0) 0 empty
+
+Class QListData::IndirectLayout
+ size=1 align=1
+ base size=1 base align=1
+QListData::IndirectLayout (0x0x7f5ebfce7820) 0 empty
+ QListData::NotArrayCompatibleLayout (0x0x7f5ebfb21540) 0 empty
+
+Class QListData::Data
+ size=24 align=8
+ base size=24 base align=8
+QListData::Data (0x0x7f5ebfb215a0) 0
+
+Class QListData
+ size=8 align=8
+ base size=8 base align=8
+QListData (0x0x7f5ebfb21300) 0
+
+Class QRegExp
+ size=8 align=8
+ base size=8 base align=8
+QRegExp (0x0x7f5ebf814780) 0
+
+Class QStringMatcher::Data
+ size=272 align=8
+ base size=272 base align=8
+QStringMatcher::Data (0x0x7f5ebf8efde0) 0
+
+Class QStringMatcher
+ size=1048 align=8
+ base size=1048 base align=8
+QStringMatcher (0x0x7f5ebf8efd80) 0
+
+Class QStringList
+ size=8 align=8
+ base size=8 base align=8
+QStringList (0x0x7f5ebf9014e0) 0
+ QList<QString> (0x0x7f5ebf901548) 0
+ QListSpecialMethods<QString> (0x0x7f5ebf91b060) 0 empty
+
+Class QScopedPointerPodDeleter
+ size=1 align=1
+ base size=0 base align=1
+QScopedPointerPodDeleter (0x0x7f5ebf9acba0) 0 empty
+
+Class std::_Rb_tree_node_base
+ size=32 align=8
+ base size=32 base align=8
+std::_Rb_tree_node_base (0x0x7f5ebf642cc0) 0
+
+Class std::_Rb_tree_header
+ size=40 align=8
+ base size=40 base align=8
+std::_Rb_tree_header (0x0x7f5ebf665060) 0
+
+Class std::__erased_type
+ size=1 align=1
+ base size=0 base align=1
+std::__erased_type (0x0x7f5ebf43c600) 0 empty
+
+Class std::allocator_arg_t
+ size=1 align=1
+ base size=0 base align=1
+std::allocator_arg_t (0x0x7f5ebf43c660) 0 empty
+
+Class std::__uses_alloc_base
+ size=1 align=1
+ base size=0 base align=1
+std::__uses_alloc_base (0x0x7f5ebf43c7e0) 0 empty
+
+Class std::__uses_alloc0::_Sink
+ size=1 align=1
+ base size=0 base align=1
+std::__uses_alloc0::_Sink (0x0x7f5ebf43c8a0) 0 empty
+
+Class std::__uses_alloc0
+ size=1 align=1
+ base size=1 base align=1
+std::__uses_alloc0 (0x0x7f5ebf7c9888) 0
+ std::__uses_alloc_base (0x0x7f5ebf43c840) 0 empty
+
+Class std::_Swallow_assign
+ size=1 align=1
+ base size=0 base align=1
+std::_Swallow_assign (0x0x7f5ebf59dc00) 0 empty
+
+Class QtPrivate::AbstractDebugStreamFunction
+ size=16 align=8
+ base size=16 base align=8
+QtPrivate::AbstractDebugStreamFunction (0x0x7f5ebf1e50c0) 0
+
+Class QtPrivate::AbstractComparatorFunction
+ size=24 align=8
+ base size=24 base align=8
+QtPrivate::AbstractComparatorFunction (0x0x7f5ebf1e5420) 0
+
+Class QtPrivate::AbstractConverterFunction
+ size=8 align=8
+ base size=8 base align=8
+QtPrivate::AbstractConverterFunction (0x0x7f5ebf1e5960) 0
+
+Class QMetaType
+ size=80 align=8
+ base size=80 base align=8
+QMetaType (0x0x7f5ebf1e5ea0) 0
+
+Class QtMetaTypePrivate::VariantData
+ size=24 align=8
+ base size=20 base align=8
+QtMetaTypePrivate::VariantData (0x0x7f5ebf2710c0) 0
+
+Class QtMetaTypePrivate::VectorBoolElements
+ size=1 align=1
+ base size=0 base align=1
+QtMetaTypePrivate::VectorBoolElements (0x0x7f5ebf271780) 0 empty
+
+Class QtMetaTypePrivate::QSequentialIterableImpl
+ size=104 align=8
+ base size=104 base align=8
+QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f5ebf307600) 0
+
+Class QtMetaTypePrivate::QAssociativeIterableImpl
+ size=112 align=8
+ base size=112 base align=8
+QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f5ebef60cc0) 0
+
+Class QtMetaTypePrivate::QPairVariantInterfaceImpl
+ size=40 align=8
+ base size=40 base align=8
+QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f5ebefdd240) 0
+
+Class std::chrono::_V2::system_clock
+ size=1 align=1
+ base size=0 base align=1
+std::chrono::_V2::system_clock (0x0x7f5ebee2a060) 0 empty
+
+Class std::chrono::_V2::steady_clock
+ size=1 align=1
+ base size=0 base align=1
+std::chrono::_V2::steady_clock (0x0x7f5ebeb21ae0) 0 empty
+
+Vtable for QObjectData
+QObjectData::_ZTV11QObjectData: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QObjectData)
+16 (int (*)(...))__cxa_pure_virtual
+24 (int (*)(...))__cxa_pure_virtual
+
+Class QObjectData
+ size=48 align=8
+ base size=48 base align=8
+QObjectData (0x0x7f5ebeb21b40) 0
+ vptr=((& QObjectData::_ZTV11QObjectData) + 16)
+
+Class QObject::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QObject::QPrivateSignal (0x0x7f5ebeb21d20) 0 empty
+
+Vtable for QObject
+QObject::_ZTV7QObject: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI7QObject)
+16 (int (*)(...))QObject::metaObject
+24 (int (*)(...))QObject::qt_metacast
+32 (int (*)(...))QObject::qt_metacall
+40 (int (*)(...))QObject::~QObject
+48 (int (*)(...))QObject::~QObject
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QObject
+ size=16 align=8
+ base size=16 base align=8
+QObject (0x0x7f5ebeb21cc0) 0
+ vptr=((& QObject::_ZTV7QObject) + 16)
+
+Vtable for QObjectUserData
+QObjectUserData::_ZTV15QObjectUserData: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI15QObjectUserData)
+16 (int (*)(...))QObjectUserData::~QObjectUserData
+24 (int (*)(...))QObjectUserData::~QObjectUserData
+
+Class QObjectUserData
+ size=8 align=8
+ base size=8 base align=8
+QObjectUserData (0x0x7f5ebebfcb40) 0 nearly-empty
+ vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16)
+
+Class QSignalBlocker
+ size=16 align=8
+ base size=10 base align=8
+QSignalBlocker (0x0x7f5ebebfccc0) 0
+
+Class QAbstractAnimation::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractAnimation::QPrivateSignal (0x0x7f5ebec1d5a0) 0 empty
+
+Vtable for QAbstractAnimation
+QAbstractAnimation::_ZTV18QAbstractAnimation: 18 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QAbstractAnimation)
+16 (int (*)(...))QAbstractAnimation::metaObject
+24 (int (*)(...))QAbstractAnimation::qt_metacast
+32 (int (*)(...))QAbstractAnimation::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QAbstractAnimation::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+128 (int (*)(...))QAbstractAnimation::updateState
+136 (int (*)(...))QAbstractAnimation::updateDirection
+
+Class QAbstractAnimation
+ size=16 align=8
+ base size=16 base align=8
+QAbstractAnimation (0x0x7f5ebebdda90) 0
+ vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16)
+ QObject (0x0x7f5ebec1d540) 0
+ primary-for QAbstractAnimation (0x0x7f5ebebdda90)
+
+Class QAnimationDriver::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAnimationDriver::QPrivateSignal (0x0x7f5ebec1d960) 0 empty
+
+Vtable for QAnimationDriver
+QAnimationDriver::_ZTV16QAnimationDriver: 18 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI16QAnimationDriver)
+16 (int (*)(...))QAnimationDriver::metaObject
+24 (int (*)(...))QAnimationDriver::qt_metacast
+32 (int (*)(...))QAnimationDriver::qt_metacall
+40 (int (*)(...))QAnimationDriver::~QAnimationDriver
+48 (int (*)(...))QAnimationDriver::~QAnimationDriver
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QAnimationDriver::advance
+120 (int (*)(...))QAnimationDriver::elapsed
+128 (int (*)(...))QAnimationDriver::start
+136 (int (*)(...))QAnimationDriver::stop
+
+Class QAnimationDriver
+ size=16 align=8
+ base size=16 base align=8
+QAnimationDriver (0x0x7f5ebebddaf8) 0
+ vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16)
+ QObject (0x0x7f5ebec1d900) 0
+ primary-for QAnimationDriver (0x0x7f5ebebddaf8)
+
+Class QEventLoop::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QEventLoop::QPrivateSignal (0x0x7f5ebec1dba0) 0 empty
+
+Vtable for QEventLoop
+QEventLoop::_ZTV10QEventLoop: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI10QEventLoop)
+16 (int (*)(...))QEventLoop::metaObject
+24 (int (*)(...))QEventLoop::qt_metacast
+32 (int (*)(...))QEventLoop::qt_metacall
+40 (int (*)(...))QEventLoop::~QEventLoop
+48 (int (*)(...))QEventLoop::~QEventLoop
+56 (int (*)(...))QEventLoop::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QEventLoop
+ size=16 align=8
+ base size=16 base align=8
+QEventLoop (0x0x7f5ebebddb60) 0
+ vptr=((& QEventLoop::_ZTV10QEventLoop) + 16)
+ QObject (0x0x7f5ebec1db40) 0
+ primary-for QEventLoop (0x0x7f5ebebddb60)
+
+Class QEventLoopLocker
+ size=8 align=8
+ base size=8 base align=8
+QEventLoopLocker (0x0x7f5ebec73480) 0
+
+Class QAbstractEventDispatcher::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractEventDispatcher::QPrivateSignal (0x0x7f5ebec73540) 0 empty
+
+Class QAbstractEventDispatcher::TimerInfo
+ size=12 align=4
+ base size=12 base align=4
+QAbstractEventDispatcher::TimerInfo (0x0x7f5ebec735a0) 0
+
+Vtable for QAbstractEventDispatcher
+QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher: 28 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI24QAbstractEventDispatcher)
+16 (int (*)(...))QAbstractEventDispatcher::metaObject
+24 (int (*)(...))QAbstractEventDispatcher::qt_metacast
+32 (int (*)(...))QAbstractEventDispatcher::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+128 (int (*)(...))__cxa_pure_virtual
+136 (int (*)(...))__cxa_pure_virtual
+144 (int (*)(...))__cxa_pure_virtual
+152 (int (*)(...))__cxa_pure_virtual
+160 (int (*)(...))__cxa_pure_virtual
+168 (int (*)(...))__cxa_pure_virtual
+176 (int (*)(...))__cxa_pure_virtual
+184 (int (*)(...))__cxa_pure_virtual
+192 (int (*)(...))__cxa_pure_virtual
+200 (int (*)(...))__cxa_pure_virtual
+208 (int (*)(...))QAbstractEventDispatcher::startingUp
+216 (int (*)(...))QAbstractEventDispatcher::closingDown
+
+Class QAbstractEventDispatcher
+ size=16 align=8
+ base size=16 base align=8
+QAbstractEventDispatcher (0x0x7f5ebebddc98) 0
+ vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16)
+ QObject (0x0x7f5ebec734e0) 0
+ primary-for QAbstractEventDispatcher (0x0x7f5ebebddc98)
+
+Vtable for std::bad_function_call
+std::bad_function_call::_ZTVSt17bad_function_call: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt17bad_function_call)
+16 (int (*)(...))std::bad_function_call::~bad_function_call
+24 (int (*)(...))std::bad_function_call::~bad_function_call
+32 (int (*)(...))std::bad_function_call::what
+
+Class std::bad_function_call
+ size=8 align=8
+ base size=8 base align=8
+std::bad_function_call (0x0x7f5ebe90d618) 0 nearly-empty
+ vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16)
+ std::exception (0x0x7f5ebe905c00) 0 nearly-empty
+ primary-for std::bad_function_call (0x0x7f5ebe90d618)
+
+Class std::_Nocopy_types
+ size=16 align=8
+ base size=16 base align=8
+std::_Nocopy_types (0x0x7f5ebe905cc0) 0
+
+Class std::_Any_data
+ size=16 align=8
+ base size=16 base align=8
+std::_Any_data (0x0x7f5ebe905d20) 0
+
+Class std::_Function_base
+ size=24 align=8
+ base size=24 base align=8
+std::_Function_base (0x0x7f5ebe937060) 0
+
+Class QMapNodeBase
+ size=24 align=8
+ base size=24 base align=8
+QMapNodeBase (0x0x7f5ebe732000) 0
+
+Class QMapDataBase
+ size=40 align=8
+ base size=40 base align=8
+QMapDataBase (0x0x7f5ebe732c60) 0
+
+Class QHashData::Node
+ size=16 align=8
+ base size=16 base align=8
+QHashData::Node (0x0x7f5ebe830600) 0
+
+Class QHashData
+ size=48 align=8
+ base size=44 base align=8
+QHashData (0x0x7f5ebe8305a0) 0
+
+Class QHashDummyValue
+ size=1 align=1
+ base size=0 base align=1
+QHashDummyValue (0x0x7f5ebe8308a0) 0 empty
+
+Class QVariant::PrivateShared
+ size=16 align=8
+ base size=12 base align=8
+QVariant::PrivateShared (0x0x7f5ebe532e40) 0
+
+Class QVariant::Private::Data
+ size=8 align=8
+ base size=8 base align=8
+QVariant::Private::Data (0x0x7f5ebe532f00) 0
+
+Class QVariant::Private
+ size=16 align=8
+ base size=12 base align=8
+QVariant::Private (0x0x7f5ebe532ea0) 0
+
+Class QVariant::Handler
+ size=72 align=8
+ base size=72 base align=8
+QVariant::Handler (0x0x7f5ebe532f60) 0
+
+Class QVariant
+ size=16 align=8
+ base size=16 base align=8
+QVariant (0x0x7f5ebe532de0) 0
+
+Class QVariantComparisonHelper
+ size=8 align=8
+ base size=8 base align=8
+QVariantComparisonHelper (0x0x7f5ebe6ab240) 0
+
+Class QSequentialIterable::const_iterator
+ size=112 align=8
+ base size=112 base align=8
+QSequentialIterable::const_iterator (0x0x7f5ebe2f48a0) 0
+
+Class QSequentialIterable
+ size=104 align=8
+ base size=104 base align=8
+QSequentialIterable (0x0x7f5ebe2f4840) 0
+
+Class QAssociativeIterable::const_iterator
+ size=120 align=8
+ base size=120 base align=8
+QAssociativeIterable::const_iterator (0x0x7f5ebe2f49c0) 0
+
+Class QAssociativeIterable
+ size=112 align=8
+ base size=112 base align=8
+QAssociativeIterable (0x0x7f5ebe2f4960) 0
+
+Class QModelIndex
+ size=24 align=8
+ base size=24 base align=8
+QModelIndex (0x0x7f5ebe3bdb40) 0
+
+Class QPersistentModelIndex
+ size=8 align=8
+ base size=8 base align=8
+QPersistentModelIndex (0x0x7f5ebe42e780) 0
+
+Class QAbstractItemModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractItemModel::QPrivateSignal (0x0x7f5ebe0ff5a0) 0 empty
+
+Vtable for QAbstractItemModel
+QAbstractItemModel::_ZTV18QAbstractItemModel: 48 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QAbstractItemModel)
+16 (int (*)(...))QAbstractItemModel::metaObject
+24 (int (*)(...))QAbstractItemModel::qt_metacast
+32 (int (*)(...))QAbstractItemModel::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+128 (int (*)(...))QAbstractItemModel::sibling
+136 (int (*)(...))__cxa_pure_virtual
+144 (int (*)(...))__cxa_pure_virtual
+152 (int (*)(...))QAbstractItemModel::hasChildren
+160 (int (*)(...))__cxa_pure_virtual
+168 (int (*)(...))QAbstractItemModel::setData
+176 (int (*)(...))QAbstractItemModel::headerData
+184 (int (*)(...))QAbstractItemModel::setHeaderData
+192 (int (*)(...))QAbstractItemModel::itemData
+200 (int (*)(...))QAbstractItemModel::setItemData
+208 (int (*)(...))QAbstractItemModel::mimeTypes
+216 (int (*)(...))QAbstractItemModel::mimeData
+224 (int (*)(...))QAbstractItemModel::canDropMimeData
+232 (int (*)(...))QAbstractItemModel::dropMimeData
+240 (int (*)(...))QAbstractItemModel::supportedDropActions
+248 (int (*)(...))QAbstractItemModel::supportedDragActions
+256 (int (*)(...))QAbstractItemModel::insertRows
+264 (int (*)(...))QAbstractItemModel::insertColumns
+272 (int (*)(...))QAbstractItemModel::removeRows
+280 (int (*)(...))QAbstractItemModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractItemModel::fetchMore
+312 (int (*)(...))QAbstractItemModel::canFetchMore
+320 (int (*)(...))QAbstractItemModel::flags
+328 (int (*)(...))QAbstractItemModel::sort
+336 (int (*)(...))QAbstractItemModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QAbstractItemModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractItemModel::submit
+376 (int (*)(...))QAbstractItemModel::revert
+
+Class QAbstractItemModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractItemModel (0x0x7f5ebe103208) 0
+ vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16)
+ QObject (0x0x7f5ebe0ff540) 0
+ primary-for QAbstractItemModel (0x0x7f5ebe103208)
+
+Class QAbstractTableModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractTableModel::QPrivateSignal (0x0x7f5ebe1b6960) 0 empty
+
+Vtable for QAbstractTableModel
+QAbstractTableModel::_ZTV19QAbstractTableModel: 48 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QAbstractTableModel)
+16 (int (*)(...))QAbstractTableModel::metaObject
+24 (int (*)(...))QAbstractTableModel::qt_metacast
+32 (int (*)(...))QAbstractTableModel::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QAbstractTableModel::index
+120 (int (*)(...))QAbstractTableModel::parent
+128 (int (*)(...))QAbstractTableModel::sibling
+136 (int (*)(...))__cxa_pure_virtual
+144 (int (*)(...))__cxa_pure_virtual
+152 (int (*)(...))QAbstractTableModel::hasChildren
+160 (int (*)(...))__cxa_pure_virtual
+168 (int (*)(...))QAbstractItemModel::setData
+176 (int (*)(...))QAbstractItemModel::headerData
+184 (int (*)(...))QAbstractItemModel::setHeaderData
+192 (int (*)(...))QAbstractItemModel::itemData
+200 (int (*)(...))QAbstractItemModel::setItemData
+208 (int (*)(...))QAbstractItemModel::mimeTypes
+216 (int (*)(...))QAbstractItemModel::mimeData
+224 (int (*)(...))QAbstractItemModel::canDropMimeData
+232 (int (*)(...))QAbstractTableModel::dropMimeData
+240 (int (*)(...))QAbstractItemModel::supportedDropActions
+248 (int (*)(...))QAbstractItemModel::supportedDragActions
+256 (int (*)(...))QAbstractItemModel::insertRows
+264 (int (*)(...))QAbstractItemModel::insertColumns
+272 (int (*)(...))QAbstractItemModel::removeRows
+280 (int (*)(...))QAbstractItemModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractItemModel::fetchMore
+312 (int (*)(...))QAbstractItemModel::canFetchMore
+320 (int (*)(...))QAbstractTableModel::flags
+328 (int (*)(...))QAbstractItemModel::sort
+336 (int (*)(...))QAbstractItemModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QAbstractItemModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractItemModel::submit
+376 (int (*)(...))QAbstractItemModel::revert
+
+Class QAbstractTableModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractTableModel (0x0x7f5ebe103820) 0
+ vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16)
+ QAbstractItemModel (0x0x7f5ebe103888) 0
+ primary-for QAbstractTableModel (0x0x7f5ebe103820)
+ QObject (0x0x7f5ebe1b6900) 0
+ primary-for QAbstractItemModel (0x0x7f5ebe103888)
+
+Class QAbstractListModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractListModel::QPrivateSignal (0x0x7f5ebe1b6ae0) 0 empty
+
+Vtable for QAbstractListModel
+QAbstractListModel::_ZTV18QAbstractListModel: 48 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QAbstractListModel)
+16 (int (*)(...))QAbstractListModel::metaObject
+24 (int (*)(...))QAbstractListModel::qt_metacast
+32 (int (*)(...))QAbstractListModel::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QAbstractListModel::index
+120 (int (*)(...))QAbstractListModel::parent
+128 (int (*)(...))QAbstractListModel::sibling
+136 (int (*)(...))__cxa_pure_virtual
+144 (int (*)(...))QAbstractListModel::columnCount
+152 (int (*)(...))QAbstractListModel::hasChildren
+160 (int (*)(...))__cxa_pure_virtual
+168 (int (*)(...))QAbstractItemModel::setData
+176 (int (*)(...))QAbstractItemModel::headerData
+184 (int (*)(...))QAbstractItemModel::setHeaderData
+192 (int (*)(...))QAbstractItemModel::itemData
+200 (int (*)(...))QAbstractItemModel::setItemData
+208 (int (*)(...))QAbstractItemModel::mimeTypes
+216 (int (*)(...))QAbstractItemModel::mimeData
+224 (int (*)(...))QAbstractItemModel::canDropMimeData
+232 (int (*)(...))QAbstractListModel::dropMimeData
+240 (int (*)(...))QAbstractItemModel::supportedDropActions
+248 (int (*)(...))QAbstractItemModel::supportedDragActions
+256 (int (*)(...))QAbstractItemModel::insertRows
+264 (int (*)(...))QAbstractItemModel::insertColumns
+272 (int (*)(...))QAbstractItemModel::removeRows
+280 (int (*)(...))QAbstractItemModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractItemModel::fetchMore
+312 (int (*)(...))QAbstractItemModel::canFetchMore
+320 (int (*)(...))QAbstractListModel::flags
+328 (int (*)(...))QAbstractItemModel::sort
+336 (int (*)(...))QAbstractItemModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QAbstractItemModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractItemModel::submit
+376 (int (*)(...))QAbstractItemModel::revert
+
+Class QAbstractListModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractListModel (0x0x7f5ebe1038f0) 0
+ vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16)
+ QAbstractItemModel (0x0x7f5ebe103958) 0
+ primary-for QAbstractListModel (0x0x7f5ebe1038f0)
+ QObject (0x0x7f5ebe1b6a80) 0
+ primary-for QAbstractItemModel (0x0x7f5ebe103958)
+
+Vtable for QAbstractNativeEventFilter
+QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI26QAbstractNativeEventFilter)
+16 0
+24 0
+32 (int (*)(...))__cxa_pure_virtual
+
+Class QAbstractNativeEventFilter
+ size=16 align=8
+ base size=16 base align=8
+QAbstractNativeEventFilter (0x0x7f5ebe1fc240) 0
+ vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16)
+
+Class QAbstractProxyModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractProxyModel::QPrivateSignal (0x0x7f5ebe1fc300) 0 empty
+
+Vtable for QAbstractProxyModel
+QAbstractProxyModel::_ZTV19QAbstractProxyModel: 53 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QAbstractProxyModel)
+16 (int (*)(...))QAbstractProxyModel::metaObject
+24 (int (*)(...))QAbstractProxyModel::qt_metacast
+32 (int (*)(...))QAbstractProxyModel::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+128 (int (*)(...))QAbstractProxyModel::sibling
+136 (int (*)(...))__cxa_pure_virtual
+144 (int (*)(...))__cxa_pure_virtual
+152 (int (*)(...))QAbstractProxyModel::hasChildren
+160 (int (*)(...))QAbstractProxyModel::data
+168 (int (*)(...))QAbstractProxyModel::setData
+176 (int (*)(...))QAbstractProxyModel::headerData
+184 (int (*)(...))QAbstractProxyModel::setHeaderData
+192 (int (*)(...))QAbstractProxyModel::itemData
+200 (int (*)(...))QAbstractProxyModel::setItemData
+208 (int (*)(...))QAbstractProxyModel::mimeTypes
+216 (int (*)(...))QAbstractProxyModel::mimeData
+224 (int (*)(...))QAbstractProxyModel::canDropMimeData
+232 (int (*)(...))QAbstractProxyModel::dropMimeData
+240 (int (*)(...))QAbstractProxyModel::supportedDropActions
+248 (int (*)(...))QAbstractProxyModel::supportedDragActions
+256 (int (*)(...))QAbstractItemModel::insertRows
+264 (int (*)(...))QAbstractItemModel::insertColumns
+272 (int (*)(...))QAbstractItemModel::removeRows
+280 (int (*)(...))QAbstractItemModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractProxyModel::fetchMore
+312 (int (*)(...))QAbstractProxyModel::canFetchMore
+320 (int (*)(...))QAbstractProxyModel::flags
+328 (int (*)(...))QAbstractProxyModel::sort
+336 (int (*)(...))QAbstractProxyModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QAbstractProxyModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractProxyModel::submit
+376 (int (*)(...))QAbstractProxyModel::revert
+384 (int (*)(...))QAbstractProxyModel::setSourceModel
+392 (int (*)(...))__cxa_pure_virtual
+400 (int (*)(...))__cxa_pure_virtual
+408 (int (*)(...))QAbstractProxyModel::mapSelectionToSource
+416 (int (*)(...))QAbstractProxyModel::mapSelectionFromSource
+
+Class QAbstractProxyModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractProxyModel (0x0x7f5ebe103a28) 0
+ vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16)
+ QAbstractItemModel (0x0x7f5ebe103a90) 0
+ primary-for QAbstractProxyModel (0x0x7f5ebe103a28)
+ QObject (0x0x7f5ebe1fc2a0) 0
+ primary-for QAbstractItemModel (0x0x7f5ebe103a90)
+
+Class QAbstractState::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractState::QPrivateSignal (0x0x7f5ebe1fc540) 0 empty
+
+Vtable for QAbstractState
+QAbstractState::_ZTV14QAbstractState: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI14QAbstractState)
+16 (int (*)(...))QAbstractState::metaObject
+24 (int (*)(...))QAbstractState::qt_metacast
+32 (int (*)(...))QAbstractState::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QAbstractState::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+
+Class QAbstractState
+ size=16 align=8
+ base size=16 base align=8
+QAbstractState (0x0x7f5ebe103af8) 0
+ vptr=((& QAbstractState::_ZTV14QAbstractState) + 16)
+ QObject (0x0x7f5ebe1fc4e0) 0
+ primary-for QAbstractState (0x0x7f5ebe103af8)
+
+Class QAbstractTransition::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractTransition::QPrivateSignal (0x0x7f5ebe1fc780) 0 empty
+
+Vtable for QAbstractTransition
+QAbstractTransition::_ZTV19QAbstractTransition: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QAbstractTransition)
+16 (int (*)(...))QAbstractTransition::metaObject
+24 (int (*)(...))QAbstractTransition::qt_metacast
+32 (int (*)(...))QAbstractTransition::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QAbstractTransition::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+
+Class QAbstractTransition
+ size=16 align=8
+ base size=16 base align=8
+QAbstractTransition (0x0x7f5ebe103b60) 0
+ vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16)
+ QObject (0x0x7f5ebe1fc720) 0
+ primary-for QAbstractTransition (0x0x7f5ebe103b60)
+
+Class QAnimationGroup::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAnimationGroup::QPrivateSignal (0x0x7f5ebe1fca80) 0 empty
+
+Vtable for QAnimationGroup
+QAnimationGroup::_ZTV15QAnimationGroup: 18 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI15QAnimationGroup)
+16 (int (*)(...))QAnimationGroup::metaObject
+24 (int (*)(...))QAnimationGroup::qt_metacast
+32 (int (*)(...))QAnimationGroup::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QAnimationGroup::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+128 (int (*)(...))QAbstractAnimation::updateState
+136 (int (*)(...))QAbstractAnimation::updateDirection
+
+Class QAnimationGroup
+ size=16 align=8
+ base size=16 base align=8
+QAnimationGroup (0x0x7f5ebe103bc8) 0
+ vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16)
+ QAbstractAnimation (0x0x7f5ebe103c30) 0
+ primary-for QAnimationGroup (0x0x7f5ebe103bc8)
+ QObject (0x0x7f5ebe1fca20) 0
+ primary-for QAbstractAnimation (0x0x7f5ebe103c30)
+
+Class QBasicTimer
+ size=4 align=4
+ base size=4 base align=4
+QBasicTimer (0x0x7f5ebe2a6de0) 0
+
+Class QBitArray
+ size=8 align=8
+ base size=8 base align=8
+QBitArray (0x0x7f5ebdf021e0) 0
+
+Class QBitRef
+ size=16 align=8
+ base size=12 base align=8
+QBitRef (0x0x7f5ebdf61660) 0
+
+Class QIODevice::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QIODevice::QPrivateSignal (0x0x7f5ebdfada20) 0 empty
+
+Vtable for QIODevice
+QIODevice::_ZTV9QIODevice: 30 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QIODevice)
+16 (int (*)(...))QIODevice::metaObject
+24 (int (*)(...))QIODevice::qt_metacast
+32 (int (*)(...))QIODevice::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QIODevice::isSequential
+120 (int (*)(...))QIODevice::open
+128 (int (*)(...))QIODevice::close
+136 (int (*)(...))QIODevice::pos
+144 (int (*)(...))QIODevice::size
+152 (int (*)(...))QIODevice::seek
+160 (int (*)(...))QIODevice::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QIODevice::bytesAvailable
+184 (int (*)(...))QIODevice::bytesToWrite
+192 (int (*)(...))QIODevice::canReadLine
+200 (int (*)(...))QIODevice::waitForReadyRead
+208 (int (*)(...))QIODevice::waitForBytesWritten
+216 (int (*)(...))__cxa_pure_virtual
+224 (int (*)(...))QIODevice::readLineData
+232 (int (*)(...))__cxa_pure_virtual
+
+Class QIODevice
+ size=16 align=8
+ base size=16 base align=8
+QIODevice (0x0x7f5ebdfba1a0) 0
+ vptr=((& QIODevice::_ZTV9QIODevice) + 16)
+ QObject (0x0x7f5ebdfad9c0) 0
+ primary-for QIODevice (0x0x7f5ebdfba1a0)
+
+Class QBuffer::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QBuffer::QPrivateSignal (0x0x7f5ebdffa3c0) 0 empty
+
+Vtable for QBuffer
+QBuffer::_ZTV7QBuffer: 30 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI7QBuffer)
+16 (int (*)(...))QBuffer::metaObject
+24 (int (*)(...))QBuffer::qt_metacast
+32 (int (*)(...))QBuffer::qt_metacall
+40 (int (*)(...))QBuffer::~QBuffer
+48 (int (*)(...))QBuffer::~QBuffer
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QBuffer::connectNotify
+104 (int (*)(...))QBuffer::disconnectNotify
+112 (int (*)(...))QIODevice::isSequential
+120 (int (*)(...))QBuffer::open
+128 (int (*)(...))QBuffer::close
+136 (int (*)(...))QBuffer::pos
+144 (int (*)(...))QBuffer::size
+152 (int (*)(...))QBuffer::seek
+160 (int (*)(...))QBuffer::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QIODevice::bytesAvailable
+184 (int (*)(...))QIODevice::bytesToWrite
+192 (int (*)(...))QBuffer::canReadLine
+200 (int (*)(...))QIODevice::waitForReadyRead
+208 (int (*)(...))QIODevice::waitForBytesWritten
+216 (int (*)(...))QBuffer::readData
+224 (int (*)(...))QIODevice::readLineData
+232 (int (*)(...))QBuffer::writeData
+
+Class QBuffer
+ size=16 align=8
+ base size=16 base align=8
+QBuffer (0x0x7f5ebdfba2d8) 0
+ vptr=((& QBuffer::_ZTV7QBuffer) + 16)
+ QIODevice (0x0x7f5ebdfba340) 0
+ primary-for QBuffer (0x0x7f5ebdfba2d8)
+ QObject (0x0x7f5ebdffa360) 0
+ primary-for QIODevice (0x0x7f5ebdfba340)
+
+Class QByteArrayMatcher::Data
+ size=272 align=8
+ base size=272 base align=8
+QByteArrayMatcher::Data (0x0x7f5ebdffa660) 0
+
+Class QByteArrayMatcher
+ size=1040 align=8
+ base size=1040 base align=8
+QByteArrayMatcher (0x0x7f5ebdffa600) 0
+
+Class QStaticByteArrayMatcherBase::Skiptable
+ size=256 align=1
+ base size=256 base align=1
+QStaticByteArrayMatcherBase::Skiptable (0x0x7f5ebdffa7e0) 0
+
+Class QStaticByteArrayMatcherBase
+ size=256 align=16
+ base size=256 base align=16
+QStaticByteArrayMatcherBase (0x0x7f5ebdffa780) 0
+
+Class QSharedData
+ size=4 align=4
+ base size=4 base align=4
+QSharedData (0x0x7f5ebe0466c0) 0
+
+Class QDate
+ size=8 align=8
+ base size=8 base align=8
+QDate (0x0x7f5ebe087660) 0
+
+Class QTime
+ size=4 align=4
+ base size=4 base align=4
+QTime (0x0x7f5ebdcdbf00) 0
+
+Class QDateTime::ShortData
+ size=8 align=8
+ base size=8 base align=8
+QDateTime::ShortData (0x0x7f5ebdd45ba0) 0
+
+Class QDateTime::Data
+ size=8 align=8
+ base size=8 base align=8
+QDateTime::Data (0x0x7f5ebdd45c00) 0
+
+Class QDateTime
+ size=8 align=8
+ base size=8 base align=8
+QDateTime (0x0x7f5ebdd45b40) 0
+
+Class QLocale
+ size=8 align=8
+ base size=8 base align=8
+QLocale (0x0x7f5ebde36300) 0
+
+Vtable for QTextStream
+QTextStream::_ZTV11QTextStream: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QTextStream)
+16 (int (*)(...))QTextStream::~QTextStream
+24 (int (*)(...))QTextStream::~QTextStream
+
+Class QTextStream
+ size=16 align=8
+ base size=16 base align=8
+QTextStream (0x0x7f5ebdb338a0) 0
+ vptr=((& QTextStream::_ZTV11QTextStream) + 16)
+
+Class QTextStreamManipulator
+ size=40 align=8
+ base size=38 base align=8
+QTextStreamManipulator (0x0x7f5ebdb99180) 0
+
+Class QContiguousCacheData
+ size=24 align=4
+ base size=24 base align=4
+QContiguousCacheData (0x0x7f5ebdc0bc60) 0
+
+Class QtSharedPointer::NormalDeleter
+ size=1 align=1
+ base size=0 base align=1
+QtSharedPointer::NormalDeleter (0x0x7f5ebdc54900) 0 empty
+
+Class QtSharedPointer::ExternalRefCountData
+ size=16 align=8
+ base size=16 base align=8
+QtSharedPointer::ExternalRefCountData (0x0x7f5ebdc54a80) 0
+
+Class QDebug::Stream
+ size=80 align=8
+ base size=76 base align=8
+QDebug::Stream (0x0x7f5ebd90d6c0) 0
+
+Class QDebug
+ size=8 align=8
+ base size=8 base align=8
+QDebug (0x0x7f5ebd90d660) 0
+
+Class QDebugStateSaver
+ size=8 align=8
+ base size=8 base align=8
+QDebugStateSaver (0x0x7f5ebdaaf720) 0
+
+Class QNoDebug
+ size=1 align=1
+ base size=0 base align=1
+QNoDebug (0x0x7f5ebdaaf7e0) 0 empty
+
+Class QCborError
+ size=4 align=4
+ base size=4 base align=4
+QCborError (0x0x7f5ebd72fae0) 0
+
+Class QRegularExpression
+ size=8 align=8
+ base size=8 base align=8
+QRegularExpression (0x0x7f5ebd7632a0) 0
+
+Class QRegularExpressionMatch
+ size=8 align=8
+ base size=8 base align=8
+QRegularExpressionMatch (0x0x7f5ebd816180) 0
+
+Class QRegularExpressionMatchIterator
+ size=8 align=8
+ base size=8 base align=8
+QRegularExpressionMatchIterator (0x0x7f5ebd853f00) 0
+
+Class QUrl
+ size=8 align=8
+ base size=8 base align=8
+QUrl (0x0x7f5ebd4d1960) 0
+
+Class QUuid
+ size=16 align=4
+ base size=16 base align=4
+QUuid (0x0x7f5ebd615900) 0
+
+Class QCborParserError
+ size=16 align=8
+ base size=12 base align=8
+QCborParserError (0x0x7f5ebd6a0480) 0
+
+Class QCborValue
+ size=24 align=8
+ base size=20 base align=8
+QCborValue (0x0x7f5ebd6a0540) 0
+
+Class QCborValueRef
+ size=16 align=8
+ base size=16 base align=8
+QCborValueRef (0x0x7f5ebd114540) 0
+
+Class QCborArray::Iterator
+ size=16 align=8
+ base size=16 base align=8
+QCborArray::Iterator (0x0x7f5ebd188f60) 0
+
+Class QCborArray::ConstIterator
+ size=16 align=8
+ base size=16 base align=8
+QCborArray::ConstIterator (0x0x7f5ebd1bc000) 0
+
+Class QCborArray
+ size=8 align=8
+ base size=8 base align=8
+QCborArray (0x0x7f5ebd188f00) 0
+
+Class QCborMap::Iterator
+ size=16 align=8
+ base size=16 base align=8
+QCborMap::Iterator (0x0x7f5ebd2a19c0) 0
+
+Class QCborMap::ConstIterator
+ size=16 align=8
+ base size=16 base align=8
+QCborMap::ConstIterator (0x0x7f5ebd2a1a20) 0
+
+Class QCborMap
+ size=8 align=8
+ base size=8 base align=8
+QCborMap (0x0x7f5ebd2a1960) 0
+
+Class qfloat16
+ size=2 align=2
+ base size=2 base align=2
+qfloat16 (0x0x7f5ebd0b4180) 0
+
+Class QCborStreamWriter
+ size=8 align=8
+ base size=8 base align=8
+QCborStreamWriter (0x0x7f5ebcd73120) 0
+
+Class QCborStreamReader
+ size=24 align=8
+ base size=20 base align=8
+QCborStreamReader (0x0x7f5ebcd73e40) 0
+
+Class QCollatorSortKey
+ size=8 align=8
+ base size=8 base align=8
+QCollatorSortKey (0x0x7f5ebce08f60) 0
+
+Class QCollator
+ size=8 align=8
+ base size=8 base align=8
+QCollator (0x0x7f5ebce29180) 0
+
+Class QCommandLineOption
+ size=8 align=8
+ base size=8 base align=8
+QCommandLineOption (0x0x7f5ebcb21720) 0
+
+Vtable for QEvent
+QEvent::_ZTV6QEvent: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI6QEvent)
+16 (int (*)(...))QEvent::~QEvent
+24 (int (*)(...))QEvent::~QEvent
+
+Class QEvent
+ size=24 align=8
+ base size=20 base align=8
+QEvent (0x0x7f5ebcb77e40) 0
+ vptr=((& QEvent::_ZTV6QEvent) + 16)
+
+Vtable for QTimerEvent
+QTimerEvent::_ZTV11QTimerEvent: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QTimerEvent)
+16 (int (*)(...))QTimerEvent::~QTimerEvent
+24 (int (*)(...))QTimerEvent::~QTimerEvent
+
+Class QTimerEvent
+ size=24 align=8
+ base size=24 base align=8
+QTimerEvent (0x0x7f5ebcb7b4e0) 0
+ vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16)
+ QEvent (0x0x7f5ebcbbb240) 0
+ primary-for QTimerEvent (0x0x7f5ebcb7b4e0)
+
+Vtable for QChildEvent
+QChildEvent::_ZTV11QChildEvent: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QChildEvent)
+16 (int (*)(...))QChildEvent::~QChildEvent
+24 (int (*)(...))QChildEvent::~QChildEvent
+
+Class QChildEvent
+ size=32 align=8
+ base size=32 base align=8
+QChildEvent (0x0x7f5ebcb7b548) 0
+ vptr=((& QChildEvent::_ZTV11QChildEvent) + 16)
+ QEvent (0x0x7f5ebcbbb300) 0
+ primary-for QChildEvent (0x0x7f5ebcb7b548)
+
+Vtable for QDynamicPropertyChangeEvent
+QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI27QDynamicPropertyChangeEvent)
+16 (int (*)(...))QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent
+24 (int (*)(...))QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent
+
+Class QDynamicPropertyChangeEvent
+ size=32 align=8
+ base size=32 base align=8
+QDynamicPropertyChangeEvent (0x0x7f5ebcb7ba90) 0
+ vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16)
+ QEvent (0x0x7f5ebcbbb960) 0
+ primary-for QDynamicPropertyChangeEvent (0x0x7f5ebcb7ba90)
+
+Vtable for QDeferredDeleteEvent
+QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI20QDeferredDeleteEvent)
+16 (int (*)(...))QDeferredDeleteEvent::~QDeferredDeleteEvent
+24 (int (*)(...))QDeferredDeleteEvent::~QDeferredDeleteEvent
+
+Class QDeferredDeleteEvent
+ size=24 align=8
+ base size=24 base align=8
+QDeferredDeleteEvent (0x0x7f5ebcb7baf8) 0
+ vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16)
+ QEvent (0x0x7f5ebcbbba20) 0
+ primary-for QDeferredDeleteEvent (0x0x7f5ebcb7baf8)
+
+Class QCoreApplication::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QCoreApplication::QPrivateSignal (0x0x7f5ebcbbbb40) 0 empty
+
+Vtable for QCoreApplication
+QCoreApplication::_ZTV16QCoreApplication: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI16QCoreApplication)
+16 (int (*)(...))QCoreApplication::metaObject
+24 (int (*)(...))QCoreApplication::qt_metacast
+32 (int (*)(...))QCoreApplication::qt_metacall
+40 (int (*)(...))QCoreApplication::~QCoreApplication
+48 (int (*)(...))QCoreApplication::~QCoreApplication
+56 (int (*)(...))QCoreApplication::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QCoreApplication::notify
+120 (int (*)(...))QCoreApplication::compressEvent
+
+Class QCoreApplication
+ size=16 align=8
+ base size=16 base align=8
+QCoreApplication (0x0x7f5ebcb7bb60) 0
+ vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16)
+ QObject (0x0x7f5ebcbbbae0) 0
+ primary-for QCoreApplication (0x0x7f5ebcb7bb60)
+
+Class QCommandLineParser
+ size=8 align=8
+ base size=8 base align=8
+QCommandLineParser (0x0x7f5ebcbbbd80) 0
+
+Class QConcatenateTablesProxyModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QConcatenateTablesProxyModel::QPrivateSignal (0x0x7f5ebcbbbf00) 0 empty
+
+Vtable for QConcatenateTablesProxyModel
+QConcatenateTablesProxyModel::_ZTV28QConcatenateTablesProxyModel: 48 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI28QConcatenateTablesProxyModel)
+16 (int (*)(...))QConcatenateTablesProxyModel::metaObject
+24 (int (*)(...))QConcatenateTablesProxyModel::qt_metacast
+32 (int (*)(...))QConcatenateTablesProxyModel::qt_metacall
+40 (int (*)(...))QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel
+48 (int (*)(...))QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QConcatenateTablesProxyModel::index
+120 (int (*)(...))QConcatenateTablesProxyModel::parent
+128 (int (*)(...))QAbstractItemModel::sibling
+136 (int (*)(...))QConcatenateTablesProxyModel::rowCount
+144 (int (*)(...))QConcatenateTablesProxyModel::columnCount
+152 (int (*)(...))QAbstractItemModel::hasChildren
+160 (int (*)(...))QConcatenateTablesProxyModel::data
+168 (int (*)(...))QConcatenateTablesProxyModel::setData
+176 (int (*)(...))QConcatenateTablesProxyModel::headerData
+184 (int (*)(...))QAbstractItemModel::setHeaderData
+192 (int (*)(...))QConcatenateTablesProxyModel::itemData
+200 (int (*)(...))QConcatenateTablesProxyModel::setItemData
+208 (int (*)(...))QConcatenateTablesProxyModel::mimeTypes
+216 (int (*)(...))QConcatenateTablesProxyModel::mimeData
+224 (int (*)(...))QConcatenateTablesProxyModel::canDropMimeData
+232 (int (*)(...))QConcatenateTablesProxyModel::dropMimeData
+240 (int (*)(...))QAbstractItemModel::supportedDropActions
+248 (int (*)(...))QAbstractItemModel::supportedDragActions
+256 (int (*)(...))QAbstractItemModel::insertRows
+264 (int (*)(...))QAbstractItemModel::insertColumns
+272 (int (*)(...))QAbstractItemModel::removeRows
+280 (int (*)(...))QAbstractItemModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractItemModel::fetchMore
+312 (int (*)(...))QAbstractItemModel::canFetchMore
+320 (int (*)(...))QConcatenateTablesProxyModel::flags
+328 (int (*)(...))QAbstractItemModel::sort
+336 (int (*)(...))QAbstractItemModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QConcatenateTablesProxyModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractItemModel::submit
+376 (int (*)(...))QAbstractItemModel::revert
+
+Class QConcatenateTablesProxyModel
+ size=16 align=8
+ base size=16 base align=8
+QConcatenateTablesProxyModel (0x0x7f5ebcb7bbc8) 0
+ vptr=((& QConcatenateTablesProxyModel::_ZTV28QConcatenateTablesProxyModel) + 16)
+ QAbstractItemModel (0x0x7f5ebcb7bc30) 0
+ primary-for QConcatenateTablesProxyModel (0x0x7f5ebcb7bbc8)
+ QObject (0x0x7f5ebcbbbea0) 0
+ primary-for QAbstractItemModel (0x0x7f5ebcb7bc30)
+
+Class QCryptographicHash
+ size=8 align=8
+ base size=8 base align=8
+QCryptographicHash (0x0x7f5ebcc1e120) 0
+
+Class QDataStream
+ size=32 align=8
+ base size=32 base align=8
+QDataStream (0x0x7f5ebcc1e240) 0
+
+Class QtPrivate::StreamStateSaver
+ size=16 align=8
+ base size=12 base align=8
+QtPrivate::StreamStateSaver (0x0x7f5ebcc1e3c0) 0
+
+Class QElapsedTimer
+ size=16 align=8
+ base size=16 base align=8
+QElapsedTimer (0x0x7f5ebcc7cae0) 0
+
+Class QDeadlineTimer
+ size=16 align=8
+ base size=16 base align=8
+QDeadlineTimer (0x0x7f5ebccad240) 0
+
+Class QFileDevice::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QFileDevice::QPrivateSignal (0x0x7f5ebc9ccf60) 0 empty
+
+Vtable for QFileDevice
+QFileDevice::_ZTV11QFileDevice: 34 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QFileDevice)
+16 (int (*)(...))QFileDevice::metaObject
+24 (int (*)(...))QFileDevice::qt_metacast
+32 (int (*)(...))QFileDevice::qt_metacall
+40 (int (*)(...))QFileDevice::~QFileDevice
+48 (int (*)(...))QFileDevice::~QFileDevice
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QFileDevice::isSequential
+120 (int (*)(...))QIODevice::open
+128 (int (*)(...))QFileDevice::close
+136 (int (*)(...))QFileDevice::pos
+144 (int (*)(...))QFileDevice::size
+152 (int (*)(...))QFileDevice::seek
+160 (int (*)(...))QFileDevice::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QIODevice::bytesAvailable
+184 (int (*)(...))QIODevice::bytesToWrite
+192 (int (*)(...))QIODevice::canReadLine
+200 (int (*)(...))QIODevice::waitForReadyRead
+208 (int (*)(...))QIODevice::waitForBytesWritten
+216 (int (*)(...))QFileDevice::readData
+224 (int (*)(...))QFileDevice::readLineData
+232 (int (*)(...))QFileDevice::writeData
+240 (int (*)(...))QFileDevice::fileName
+248 (int (*)(...))QFileDevice::resize
+256 (int (*)(...))QFileDevice::permissions
+264 (int (*)(...))QFileDevice::setPermissions
+
+Class QFileDevice
+ size=16 align=8
+ base size=16 base align=8
+QFileDevice (0x0x7f5ebc9cde38) 0
+ vptr=((& QFileDevice::_ZTV11QFileDevice) + 16)
+ QIODevice (0x0x7f5ebc9cdea0) 0
+ primary-for QFileDevice (0x0x7f5ebc9cde38)
+ QObject (0x0x7f5ebc9ccf00) 0
+ primary-for QIODevice (0x0x7f5ebc9cdea0)
+
+Class QFile::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QFile::QPrivateSignal (0x0x7f5ebca048a0) 0 empty
+
+Vtable for QFile
+QFile::_ZTV5QFile: 34 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI5QFile)
+16 (int (*)(...))QFile::metaObject
+24 (int (*)(...))QFile::qt_metacast
+32 (int (*)(...))QFile::qt_metacall
+40 (int (*)(...))QFile::~QFile
+48 (int (*)(...))QFile::~QFile
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QFileDevice::isSequential
+120 (int (*)(...))QFile::open
+128 (int (*)(...))QFileDevice::close
+136 (int (*)(...))QFileDevice::pos
+144 (int (*)(...))QFile::size
+152 (int (*)(...))QFileDevice::seek
+160 (int (*)(...))QFileDevice::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QIODevice::bytesAvailable
+184 (int (*)(...))QIODevice::bytesToWrite
+192 (int (*)(...))QIODevice::canReadLine
+200 (int (*)(...))QIODevice::waitForReadyRead
+208 (int (*)(...))QIODevice::waitForBytesWritten
+216 (int (*)(...))QFileDevice::readData
+224 (int (*)(...))QFileDevice::readLineData
+232 (int (*)(...))QFileDevice::writeData
+240 (int (*)(...))QFile::fileName
+248 (int (*)(...))QFile::resize
+256 (int (*)(...))QFile::permissions
+264 (int (*)(...))QFile::setPermissions
+
+Class QFile
+ size=16 align=8
+ base size=16 base align=8
+QFile (0x0x7f5ebca2d000) 0
+ vptr=((& QFile::_ZTV5QFile) + 16)
+ QFileDevice (0x0x7f5ebca2d068) 0
+ primary-for QFile (0x0x7f5ebca2d000)
+ QIODevice (0x0x7f5ebca2d0d0) 0
+ primary-for QFileDevice (0x0x7f5ebca2d068)
+ QObject (0x0x7f5ebca04840) 0
+ primary-for QIODevice (0x0x7f5ebca2d0d0)
+
+Class QFileInfo
+ size=8 align=8
+ base size=8 base align=8
+QFileInfo (0x0x7f5ebca04f00) 0
+
+Class QDir
+ size=8 align=8
+ base size=8 base align=8
+QDir (0x0x7f5ebcab5300) 0
+
+Class QDirIterator
+ size=8 align=8
+ base size=8 base align=8
+QDirIterator (0x0x7f5ebc724660) 0
+
+Class QEasingCurve
+ size=8 align=8
+ base size=8 base align=8
+QEasingCurve (0x0x7f5ebc724de0) 0
+
+Class QEventTransition::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QEventTransition::QPrivateSignal (0x0x7f5ebc85df00) 0 empty
+
+Vtable for QEventTransition
+QEventTransition::_ZTV16QEventTransition: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI16QEventTransition)
+16 (int (*)(...))QEventTransition::metaObject
+24 (int (*)(...))QEventTransition::qt_metacast
+32 (int (*)(...))QEventTransition::qt_metacall
+40 (int (*)(...))QEventTransition::~QEventTransition
+48 (int (*)(...))QEventTransition::~QEventTransition
+56 (int (*)(...))QEventTransition::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QEventTransition::eventTest
+120 (int (*)(...))QEventTransition::onTransition
+
+Class QEventTransition
+ size=16 align=8
+ base size=16 base align=8
+QEventTransition (0x0x7f5ebc83a340) 0
+ vptr=((& QEventTransition::_ZTV16QEventTransition) + 16)
+ QAbstractTransition (0x0x7f5ebc83a3a8) 0
+ primary-for QEventTransition (0x0x7f5ebc83a340)
+ QObject (0x0x7f5ebc85dea0) 0
+ primary-for QAbstractTransition (0x0x7f5ebc83a3a8)
+
+Vtable for QException
+QException::_ZTV10QException: 7 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI10QException)
+16 (int (*)(...))QException::~QException
+24 (int (*)(...))QException::~QException
+32 (int (*)(...))std::exception::what
+40 (int (*)(...))QException::raise
+48 (int (*)(...))QException::clone
+
+Class QException
+ size=8 align=8
+ base size=8 base align=8
+QException (0x0x7f5ebc83a410) 0 nearly-empty
+ vptr=((& QException::_ZTV10QException) + 16)
+ std::exception (0x0x7f5ebc493120) 0 nearly-empty
+ primary-for QException (0x0x7f5ebc83a410)
+
+Vtable for QUnhandledException
+QUnhandledException::_ZTV19QUnhandledException: 7 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QUnhandledException)
+16 (int (*)(...))QUnhandledException::~QUnhandledException
+24 (int (*)(...))QUnhandledException::~QUnhandledException
+32 (int (*)(...))std::exception::what
+40 (int (*)(...))QUnhandledException::raise
+48 (int (*)(...))QUnhandledException::clone
+
+Class QUnhandledException
+ size=8 align=8
+ base size=8 base align=8
+QUnhandledException (0x0x7f5ebc83a478) 0 nearly-empty
+ vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16)
+ QException (0x0x7f5ebc83a4e0) 0 nearly-empty
+ primary-for QUnhandledException (0x0x7f5ebc83a478)
+ std::exception (0x0x7f5ebc493180) 0 nearly-empty
+ primary-for QException (0x0x7f5ebc83a4e0)
+
+Class QtPrivate::ExceptionHolder
+ size=8 align=8
+ base size=8 base align=8
+QtPrivate::ExceptionHolder (0x0x7f5ebc4931e0) 0
+
+Class QtPrivate::ExceptionStore
+ size=8 align=8
+ base size=8 base align=8
+QtPrivate::ExceptionStore (0x0x7f5ebc4932a0) 0
+
+Vtable for QFactoryInterface
+QFactoryInterface::_ZTV17QFactoryInterface: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI17QFactoryInterface)
+16 0
+24 0
+32 (int (*)(...))__cxa_pure_virtual
+
+Class QFactoryInterface
+ size=8 align=8
+ base size=8 base align=8
+QFactoryInterface (0x0x7f5ebc493300) 0 nearly-empty
+ vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16)
+
+Class QFileSelector::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QFileSelector::QPrivateSignal (0x0x7f5ebc493540) 0 empty
+
+Vtable for QFileSelector
+QFileSelector::_ZTV13QFileSelector: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QFileSelector)
+16 (int (*)(...))QFileSelector::metaObject
+24 (int (*)(...))QFileSelector::qt_metacast
+32 (int (*)(...))QFileSelector::qt_metacall
+40 (int (*)(...))QFileSelector::~QFileSelector
+48 (int (*)(...))QFileSelector::~QFileSelector
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QFileSelector
+ size=16 align=8
+ base size=16 base align=8
+QFileSelector (0x0x7f5ebc83a548) 0
+ vptr=((& QFileSelector::_ZTV13QFileSelector) + 16)
+ QObject (0x0x7f5ebc4934e0) 0
+ primary-for QFileSelector (0x0x7f5ebc83a548)
+
+Class QFileSystemWatcher::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QFileSystemWatcher::QPrivateSignal (0x0x7f5ebc493780) 0 empty
+
+Vtable for QFileSystemWatcher
+QFileSystemWatcher::_ZTV18QFileSystemWatcher: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QFileSystemWatcher)
+16 (int (*)(...))QFileSystemWatcher::metaObject
+24 (int (*)(...))QFileSystemWatcher::qt_metacast
+32 (int (*)(...))QFileSystemWatcher::qt_metacall
+40 (int (*)(...))QFileSystemWatcher::~QFileSystemWatcher
+48 (int (*)(...))QFileSystemWatcher::~QFileSystemWatcher
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QFileSystemWatcher
+ size=16 align=8
+ base size=16 base align=8
+QFileSystemWatcher (0x0x7f5ebc83a5b0) 0
+ vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16)
+ QObject (0x0x7f5ebc493720) 0
+ primary-for QFileSystemWatcher (0x0x7f5ebc83a5b0)
+
+Class QFinalState::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QFinalState::QPrivateSignal (0x0x7f5ebc4939c0) 0 empty
+
+Vtable for QFinalState
+QFinalState::_ZTV11QFinalState: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QFinalState)
+16 (int (*)(...))QFinalState::metaObject
+24 (int (*)(...))QFinalState::qt_metacast
+32 (int (*)(...))QFinalState::qt_metacall
+40 (int (*)(...))QFinalState::~QFinalState
+48 (int (*)(...))QFinalState::~QFinalState
+56 (int (*)(...))QFinalState::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QFinalState::onEntry
+120 (int (*)(...))QFinalState::onExit
+
+Class QFinalState
+ size=16 align=8
+ base size=16 base align=8
+QFinalState (0x0x7f5ebc83a618) 0
+ vptr=((& QFinalState::_ZTV11QFinalState) + 16)
+ QAbstractState (0x0x7f5ebc83a680) 0
+ primary-for QFinalState (0x0x7f5ebc83a618)
+ QObject (0x0x7f5ebc493960) 0
+ primary-for QAbstractState (0x0x7f5ebc83a680)
+
+Vtable for QRunnable
+QRunnable::_ZTV9QRunnable: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QRunnable)
+16 (int (*)(...))__cxa_pure_virtual
+24 0
+32 0
+
+Class QRunnable
+ size=16 align=8
+ base size=12 base align=8
+QRunnable (0x0x7f5ebc493ba0) 0
+ vptr=((& QRunnable::_ZTV9QRunnable) + 16)
+
+Class QBasicMutex
+ size=8 align=8
+ base size=8 base align=8
+QBasicMutex (0x0x7f5ebc493e40) 0
+
+Class QMutex
+ size=8 align=8
+ base size=8 base align=8
+QMutex (0x0x7f5ebc83a750) 0
+ QBasicMutex (0x0x7f5ebc50bae0) 0
+
+Class QMutexLocker
+ size=8 align=8
+ base size=8 base align=8
+QMutexLocker (0x0x7f5ebc50bd20) 0
+
+Class QtPrivate::ResultItem
+ size=16 align=8
+ base size=16 base align=8
+QtPrivate::ResultItem (0x0x7f5ebc5661e0) 0
+
+Class QtPrivate::ResultIteratorBase
+ size=16 align=8
+ base size=12 base align=8
+QtPrivate::ResultIteratorBase (0x0x7f5ebc5667e0) 0
+
+Vtable for QtPrivate::ResultStoreBase
+QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN9QtPrivate15ResultStoreBaseE)
+16 (int (*)(...))QtPrivate::ResultStoreBase::~ResultStoreBase
+24 (int (*)(...))QtPrivate::ResultStoreBase::~ResultStoreBase
+
+Class QtPrivate::ResultStoreBase
+ size=48 align=8
+ base size=44 base align=8
+QtPrivate::ResultStoreBase (0x0x7f5ebc5669c0) 0
+ vptr=((& QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE) + 16)
+
+Vtable for QFutureInterfaceBase
+QFutureInterfaceBase::_ZTV20QFutureInterfaceBase: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI20QFutureInterfaceBase)
+16 (int (*)(...))QFutureInterfaceBase::~QFutureInterfaceBase
+24 (int (*)(...))QFutureInterfaceBase::~QFutureInterfaceBase
+
+Class QFutureInterfaceBase
+ size=16 align=8
+ base size=16 base align=8
+QFutureInterfaceBase (0x0x7f5ebc5f41e0) 0
+ vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16)
+
+Class QFutureWatcherBase::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QFutureWatcherBase::QPrivateSignal (0x0x7f5ebc2a14e0) 0 empty
+
+Vtable for QFutureWatcherBase
+QFutureWatcherBase::_ZTV18QFutureWatcherBase: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QFutureWatcherBase)
+16 (int (*)(...))QFutureWatcherBase::metaObject
+24 (int (*)(...))QFutureWatcherBase::qt_metacast
+32 (int (*)(...))QFutureWatcherBase::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QFutureWatcherBase::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QFutureWatcherBase::connectNotify
+104 (int (*)(...))QFutureWatcherBase::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+
+Class QFutureWatcherBase
+ size=16 align=8
+ base size=16 base align=8
+QFutureWatcherBase (0x0x7f5ebc5f7d68) 0
+ vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16)
+ QObject (0x0x7f5ebc2a1480) 0
+ primary-for QFutureWatcherBase (0x0x7f5ebc5f7d68)
+
+Class QHistoryState::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QHistoryState::QPrivateSignal (0x0x7f5ebc2c8840) 0 empty
+
+Vtable for QHistoryState
+QHistoryState::_ZTV13QHistoryState: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QHistoryState)
+16 (int (*)(...))QHistoryState::metaObject
+24 (int (*)(...))QHistoryState::qt_metacast
+32 (int (*)(...))QHistoryState::qt_metacall
+40 (int (*)(...))QHistoryState::~QHistoryState
+48 (int (*)(...))QHistoryState::~QHistoryState
+56 (int (*)(...))QHistoryState::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QHistoryState::onEntry
+120 (int (*)(...))QHistoryState::onExit
+
+Class QHistoryState
+ size=16 align=8
+ base size=16 base align=8
+QHistoryState (0x0x7f5ebc2b85b0) 0
+ vptr=((& QHistoryState::_ZTV13QHistoryState) + 16)
+ QAbstractState (0x0x7f5ebc2b8618) 0
+ primary-for QHistoryState (0x0x7f5ebc2b85b0)
+ QObject (0x0x7f5ebc2c87e0) 0
+ primary-for QAbstractState (0x0x7f5ebc2b8618)
+
+Class QIdentityProxyModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QIdentityProxyModel::QPrivateSignal (0x0x7f5ebc2c8b40) 0 empty
+
+Vtable for QIdentityProxyModel
+QIdentityProxyModel::_ZTV19QIdentityProxyModel: 53 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QIdentityProxyModel)
+16 (int (*)(...))QIdentityProxyModel::metaObject
+24 (int (*)(...))QIdentityProxyModel::qt_metacast
+32 (int (*)(...))QIdentityProxyModel::qt_metacall
+40 (int (*)(...))QIdentityProxyModel::~QIdentityProxyModel
+48 (int (*)(...))QIdentityProxyModel::~QIdentityProxyModel
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QIdentityProxyModel::index
+120 (int (*)(...))QIdentityProxyModel::parent
+128 (int (*)(...))QIdentityProxyModel::sibling
+136 (int (*)(...))QIdentityProxyModel::rowCount
+144 (int (*)(...))QIdentityProxyModel::columnCount
+152 (int (*)(...))QAbstractProxyModel::hasChildren
+160 (int (*)(...))QAbstractProxyModel::data
+168 (int (*)(...))QAbstractProxyModel::setData
+176 (int (*)(...))QIdentityProxyModel::headerData
+184 (int (*)(...))QAbstractProxyModel::setHeaderData
+192 (int (*)(...))QAbstractProxyModel::itemData
+200 (int (*)(...))QAbstractProxyModel::setItemData
+208 (int (*)(...))QAbstractProxyModel::mimeTypes
+216 (int (*)(...))QAbstractProxyModel::mimeData
+224 (int (*)(...))QAbstractProxyModel::canDropMimeData
+232 (int (*)(...))QIdentityProxyModel::dropMimeData
+240 (int (*)(...))QAbstractProxyModel::supportedDropActions
+248 (int (*)(...))QAbstractProxyModel::supportedDragActions
+256 (int (*)(...))QIdentityProxyModel::insertRows
+264 (int (*)(...))QIdentityProxyModel::insertColumns
+272 (int (*)(...))QIdentityProxyModel::removeRows
+280 (int (*)(...))QIdentityProxyModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractProxyModel::fetchMore
+312 (int (*)(...))QAbstractProxyModel::canFetchMore
+320 (int (*)(...))QAbstractProxyModel::flags
+328 (int (*)(...))QAbstractProxyModel::sort
+336 (int (*)(...))QAbstractProxyModel::buddy
+344 (int (*)(...))QIdentityProxyModel::match
+352 (int (*)(...))QAbstractProxyModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractProxyModel::submit
+376 (int (*)(...))QAbstractProxyModel::revert
+384 (int (*)(...))QIdentityProxyModel::setSourceModel
+392 (int (*)(...))QIdentityProxyModel::mapToSource
+400 (int (*)(...))QIdentityProxyModel::mapFromSource
+408 (int (*)(...))QIdentityProxyModel::mapSelectionToSource
+416 (int (*)(...))QIdentityProxyModel::mapSelectionFromSource
+
+Class QIdentityProxyModel
+ size=16 align=8
+ base size=16 base align=8
+QIdentityProxyModel (0x0x7f5ebc2b8680) 0
+ vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16)
+ QAbstractProxyModel (0x0x7f5ebc2b86e8) 0
+ primary-for QIdentityProxyModel (0x0x7f5ebc2b8680)
+ QAbstractItemModel (0x0x7f5ebc2b8750) 0
+ primary-for QAbstractProxyModel (0x0x7f5ebc2b86e8)
+ QObject (0x0x7f5ebc2c8ae0) 0
+ primary-for QAbstractItemModel (0x0x7f5ebc2b8750)
+
+Class QItemSelectionRange
+ size=16 align=8
+ base size=16 base align=8
+QItemSelectionRange (0x0x7f5ebc2c8d20) 0
+
+Class QItemSelectionModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QItemSelectionModel::QPrivateSignal (0x0x7f5ebc3ac660) 0 empty
+
+Vtable for QItemSelectionModel
+QItemSelectionModel::_ZTV19QItemSelectionModel: 20 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QItemSelectionModel)
+16 (int (*)(...))QItemSelectionModel::metaObject
+24 (int (*)(...))QItemSelectionModel::qt_metacast
+32 (int (*)(...))QItemSelectionModel::qt_metacall
+40 (int (*)(...))QItemSelectionModel::~QItemSelectionModel
+48 (int (*)(...))QItemSelectionModel::~QItemSelectionModel
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QItemSelectionModel::setCurrentIndex
+120 (int (*)(...))QItemSelectionModel::select
+128 (int (*)(...))QItemSelectionModel::select
+136 (int (*)(...))QItemSelectionModel::clear
+144 (int (*)(...))QItemSelectionModel::reset
+152 (int (*)(...))QItemSelectionModel::clearCurrentIndex
+
+Class QItemSelectionModel
+ size=16 align=8
+ base size=16 base align=8
+QItemSelectionModel (0x0x7f5ebc3b40d0) 0
+ vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16)
+ QObject (0x0x7f5ebc3ac600) 0
+ primary-for QItemSelectionModel (0x0x7f5ebc3b40d0)
+
+Class QItemSelection
+ size=8 align=8
+ base size=8 base align=8
+QItemSelection (0x0x7f5ebc3b4270) 0
+ QList<QItemSelectionRange> (0x0x7f5ebc3b42d8) 0
+ QListSpecialMethods<QItemSelectionRange> (0x0x7f5ebc3f5180) 0 empty
+
+Class QJsonValue
+ size=24 align=8
+ base size=20 base align=8
+QJsonValue (0x0x7f5ebc45aa80) 0
+
+Class QJsonValueRef
+ size=16 align=8
+ base size=12 base align=8
+QJsonValueRef (0x0x7f5ebc1aac60) 0
+
+Class QJsonValuePtr
+ size=24 align=8
+ base size=24 base align=8
+QJsonValuePtr (0x0x7f5ebc1e7c00) 0
+
+Class QJsonValueRefPtr
+ size=16 align=8
+ base size=16 base align=8
+QJsonValueRefPtr (0x0x7f5ebc1e7ea0) 0
+
+Class QJsonArray::iterator
+ size=16 align=8
+ base size=12 base align=8
+QJsonArray::iterator (0x0x7f5ebc261240) 0
+
+Class QJsonArray::const_iterator
+ size=16 align=8
+ base size=12 base align=8
+QJsonArray::const_iterator (0x0x7f5ebc2612a0) 0
+
+Class QJsonArray
+ size=16 align=8
+ base size=16 base align=8
+QJsonArray (0x0x7f5ebc2611e0) 0
+
+Class QJsonParseError
+ size=8 align=4
+ base size=8 base align=4
+QJsonParseError (0x0x7f5ebbf8e180) 0
+
+Class QJsonDocument
+ size=8 align=8
+ base size=8 base align=8
+QJsonDocument (0x0x7f5ebbf8e1e0) 0
+
+Class QJsonObject::iterator
+ size=16 align=8
+ base size=12 base align=8
+QJsonObject::iterator (0x0x7f5ebbfe19c0) 0
+
+Class QJsonObject::const_iterator
+ size=16 align=8
+ base size=12 base align=8
+QJsonObject::const_iterator (0x0x7f5ebbfe1a20) 0
+
+Class QJsonObject
+ size=16 align=8
+ base size=16 base align=8
+QJsonObject (0x0x7f5ebbfe1960) 0
+
+Class QLibrary::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QLibrary::QPrivateSignal (0x0x7f5ebbcefd80) 0 empty
+
+Vtable for QLibrary
+QLibrary::_ZTV8QLibrary: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI8QLibrary)
+16 (int (*)(...))QLibrary::metaObject
+24 (int (*)(...))QLibrary::qt_metacast
+32 (int (*)(...))QLibrary::qt_metacall
+40 (int (*)(...))QLibrary::~QLibrary
+48 (int (*)(...))QLibrary::~QLibrary
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QLibrary
+ size=32 align=8
+ base size=25 base align=8
+QLibrary (0x0x7f5ebbd02340) 0
+ vptr=((& QLibrary::_ZTV8QLibrary) + 16)
+ QObject (0x0x7f5ebbcefd20) 0
+ primary-for QLibrary (0x0x7f5ebbd02340)
+
+Class QVersionNumber::SegmentStorage
+ size=8 align=8
+ base size=8 base align=8
+QVersionNumber::SegmentStorage (0x0x7f5ebbd1ec00) 0
+
+Class QVersionNumber
+ size=8 align=8
+ base size=8 base align=8
+QVersionNumber (0x0x7f5ebbd1e720) 0
+
+Class QLibraryInfo
+ size=1 align=1
+ base size=0 base align=1
+QLibraryInfo (0x0x7f5ebbdef360) 0 empty
+
+Class QPoint
+ size=8 align=4
+ base size=8 base align=4
+QPoint (0x0x7f5ebbdef3c0) 0
+
+Class QPointF
+ size=16 align=8
+ base size=16 base align=8
+QPointF (0x0x7f5ebbe6a1e0) 0
+
+Class QLine
+ size=16 align=4
+ base size=16 base align=4
+QLine (0x0x7f5ebbad8360) 0
+
+Class QLineF
+ size=32 align=8
+ base size=32 base align=8
+QLineF (0x0x7f5ebbb41720) 0
+
+Class QLinkedListData
+ size=32 align=8
+ base size=25 base align=8
+QLinkedListData (0x0x7f5ebbbbc9c0) 0
+
+Class QLockFile
+ size=8 align=8
+ base size=8 base align=8
+QLockFile (0x0x7f5ebbc63b40) 0
+
+Class QLoggingCategory::AtomicBools
+ size=4 align=1
+ base size=4 base align=1
+QLoggingCategory::AtomicBools (0x0x7f5ebbc63d80) 0
+
+Class QLoggingCategory
+ size=24 align=8
+ base size=24 base align=8
+QLoggingCategory (0x0x7f5ebbc63d20) 0
+
+Class QMargins
+ size=16 align=4
+ base size=16 base align=4
+QMargins (0x0x7f5ebb8cf1e0) 0
+
+Class QMarginsF
+ size=32 align=8
+ base size=32 base align=8
+QMarginsF (0x0x7f5ebb94d120) 0
+
+Class QMessageAuthenticationCode
+ size=8 align=8
+ base size=8 base align=8
+QMessageAuthenticationCode (0x0x7f5ebb780900) 0
+
+Class QMetaMethod
+ size=16 align=8
+ base size=12 base align=8
+QMetaMethod (0x0x7f5ebb780960) 0
+
+Class QMetaEnum
+ size=16 align=8
+ base size=12 base align=8
+QMetaEnum (0x0x7f5ebb80c1e0) 0
+
+Class QMetaProperty
+ size=32 align=8
+ base size=32 base align=8
+QMetaProperty (0x0x7f5ebb84d420) 0
+
+Class QMetaClassInfo
+ size=16 align=8
+ base size=12 base align=8
+QMetaClassInfo (0x0x7f5ebb84d540) 0
+
+Class QMimeData::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QMimeData::QPrivateSignal (0x0x7f5ebb489ae0) 0 empty
+
+Vtable for QMimeData
+QMimeData::_ZTV9QMimeData: 17 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QMimeData)
+16 (int (*)(...))QMimeData::metaObject
+24 (int (*)(...))QMimeData::qt_metacast
+32 (int (*)(...))QMimeData::qt_metacall
+40 (int (*)(...))QMimeData::~QMimeData
+48 (int (*)(...))QMimeData::~QMimeData
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QMimeData::hasFormat
+120 (int (*)(...))QMimeData::formats
+128 (int (*)(...))QMimeData::retrieveData
+
+Class QMimeData
+ size=16 align=8
+ base size=16 base align=8
+QMimeData (0x0x7f5ebb886f70) 0
+ vptr=((& QMimeData::_ZTV9QMimeData) + 16)
+ QObject (0x0x7f5ebb489a80) 0
+ primary-for QMimeData (0x0x7f5ebb886f70)
+
+Class QMimeType
+ size=8 align=8
+ base size=8 base align=8
+QMimeType (0x0x7f5ebb489cc0) 0
+
+Class QMimeDatabase
+ size=8 align=8
+ base size=8 base align=8
+QMimeDatabase (0x0x7f5ebb4e5de0) 0
+
+Class QObjectCleanupHandler::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QObjectCleanupHandler::QPrivateSignal (0x0x7f5ebb4e5ea0) 0 empty
+
+Vtable for QObjectCleanupHandler
+QObjectCleanupHandler::_ZTV21QObjectCleanupHandler: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI21QObjectCleanupHandler)
+16 (int (*)(...))QObjectCleanupHandler::metaObject
+24 (int (*)(...))QObjectCleanupHandler::qt_metacast
+32 (int (*)(...))QObjectCleanupHandler::qt_metacall
+40 (int (*)(...))QObjectCleanupHandler::~QObjectCleanupHandler
+48 (int (*)(...))QObjectCleanupHandler::~QObjectCleanupHandler
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QObjectCleanupHandler
+ size=24 align=8
+ base size=24 base align=8
+QObjectCleanupHandler (0x0x7f5ebb4fe2d8) 0
+ vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16)
+ QObject (0x0x7f5ebb4e5e40) 0
+ primary-for QObjectCleanupHandler (0x0x7f5ebb4fe2d8)
+
+Class QOperatingSystemVersion
+ size=16 align=4
+ base size=16 base align=4
+QOperatingSystemVersion (0x0x7f5ebb517000) 0
+
+Class QParallelAnimationGroup::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QParallelAnimationGroup::QPrivateSignal (0x0x7f5ebb576780) 0 empty
+
+Vtable for QParallelAnimationGroup
+QParallelAnimationGroup::_ZTV23QParallelAnimationGroup: 18 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI23QParallelAnimationGroup)
+16 (int (*)(...))QParallelAnimationGroup::metaObject
+24 (int (*)(...))QParallelAnimationGroup::qt_metacast
+32 (int (*)(...))QParallelAnimationGroup::qt_metacall
+40 (int (*)(...))QParallelAnimationGroup::~QParallelAnimationGroup
+48 (int (*)(...))QParallelAnimationGroup::~QParallelAnimationGroup
+56 (int (*)(...))QParallelAnimationGroup::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QParallelAnimationGroup::duration
+120 (int (*)(...))QParallelAnimationGroup::updateCurrentTime
+128 (int (*)(...))QParallelAnimationGroup::updateState
+136 (int (*)(...))QParallelAnimationGroup::updateDirection
+
+Class QParallelAnimationGroup
+ size=16 align=8
+ base size=16 base align=8
+QParallelAnimationGroup (0x0x7f5ebb572b60) 0
+ vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16)
+ QAnimationGroup (0x0x7f5ebb572bc8) 0
+ primary-for QParallelAnimationGroup (0x0x7f5ebb572b60)
+ QAbstractAnimation (0x0x7f5ebb572c30) 0
+ primary-for QAnimationGroup (0x0x7f5ebb572bc8)
+ QObject (0x0x7f5ebb576720) 0
+ primary-for QAbstractAnimation (0x0x7f5ebb572c30)
+
+Class QPauseAnimation::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QPauseAnimation::QPrivateSignal (0x0x7f5ebb5769c0) 0 empty
+
+Vtable for QPauseAnimation
+QPauseAnimation::_ZTV15QPauseAnimation: 18 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI15QPauseAnimation)
+16 (int (*)(...))QPauseAnimation::metaObject
+24 (int (*)(...))QPauseAnimation::qt_metacast
+32 (int (*)(...))QPauseAnimation::qt_metacall
+40 (int (*)(...))QPauseAnimation::~QPauseAnimation
+48 (int (*)(...))QPauseAnimation::~QPauseAnimation
+56 (int (*)(...))QPauseAnimation::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QPauseAnimation::duration
+120 (int (*)(...))QPauseAnimation::updateCurrentTime
+128 (int (*)(...))QAbstractAnimation::updateState
+136 (int (*)(...))QAbstractAnimation::updateDirection
+
+Class QPauseAnimation
+ size=16 align=8
+ base size=16 base align=8
+QPauseAnimation (0x0x7f5ebb572c98) 0
+ vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16)
+ QAbstractAnimation (0x0x7f5ebb572d00) 0
+ primary-for QPauseAnimation (0x0x7f5ebb572c98)
+ QObject (0x0x7f5ebb576960) 0
+ primary-for QAbstractAnimation (0x0x7f5ebb572d00)
+
+Class QStaticPlugin
+ size=16 align=8
+ base size=16 base align=8
+QStaticPlugin (0x0x7f5ebb5a8600) 0
+
+Class QPluginLoader::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QPluginLoader::QPrivateSignal (0x0x7f5ebb5ee780) 0 empty
+
+Vtable for QPluginLoader
+QPluginLoader::_ZTV13QPluginLoader: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QPluginLoader)
+16 (int (*)(...))QPluginLoader::metaObject
+24 (int (*)(...))QPluginLoader::qt_metacast
+32 (int (*)(...))QPluginLoader::qt_metacall
+40 (int (*)(...))QPluginLoader::~QPluginLoader
+48 (int (*)(...))QPluginLoader::~QPluginLoader
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QPluginLoader
+ size=32 align=8
+ base size=25 base align=8
+QPluginLoader (0x0x7f5ebb5f9068) 0
+ vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16)
+ QObject (0x0x7f5ebb5ee720) 0
+ primary-for QPluginLoader (0x0x7f5ebb5f9068)
+
+Class QProcessEnvironment
+ size=8 align=8
+ base size=8 base align=8
+QProcessEnvironment (0x0x7f5ebb5ee8a0) 0
+
+Class QProcess::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QProcess::QPrivateSignal (0x0x7f5ebb648f00) 0 empty
+
+Vtable for QProcess
+QProcess::_ZTV8QProcess: 31 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI8QProcess)
+16 (int (*)(...))QProcess::metaObject
+24 (int (*)(...))QProcess::qt_metacast
+32 (int (*)(...))QProcess::qt_metacall
+40 (int (*)(...))QProcess::~QProcess
+48 (int (*)(...))QProcess::~QProcess
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QProcess::isSequential
+120 (int (*)(...))QProcess::open
+128 (int (*)(...))QProcess::close
+136 (int (*)(...))QIODevice::pos
+144 (int (*)(...))QIODevice::size
+152 (int (*)(...))QIODevice::seek
+160 (int (*)(...))QProcess::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QProcess::bytesAvailable
+184 (int (*)(...))QProcess::bytesToWrite
+192 (int (*)(...))QProcess::canReadLine
+200 (int (*)(...))QProcess::waitForReadyRead
+208 (int (*)(...))QProcess::waitForBytesWritten
+216 (int (*)(...))QProcess::readData
+224 (int (*)(...))QIODevice::readLineData
+232 (int (*)(...))QProcess::writeData
+240 (int (*)(...))QProcess::setupChildProcess
+
+Class QProcess
+ size=16 align=8
+ base size=16 base align=8
+QProcess (0x0x7f5ebb64bc98) 0
+ vptr=((& QProcess::_ZTV8QProcess) + 16)
+ QIODevice (0x0x7f5ebb64bd00) 0
+ primary-for QProcess (0x0x7f5ebb64bc98)
+ QObject (0x0x7f5ebb648ea0) 0
+ primary-for QIODevice (0x0x7f5ebb64bd00)
+
+Class QVariantAnimation::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QVariantAnimation::QPrivateSignal (0x0x7f5ebb289600) 0 empty
+
+Vtable for QVariantAnimation
+QVariantAnimation::_ZTV17QVariantAnimation: 20 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI17QVariantAnimation)
+16 (int (*)(...))QVariantAnimation::metaObject
+24 (int (*)(...))QVariantAnimation::qt_metacast
+32 (int (*)(...))QVariantAnimation::qt_metacall
+40 (int (*)(...))QVariantAnimation::~QVariantAnimation
+48 (int (*)(...))QVariantAnimation::~QVariantAnimation
+56 (int (*)(...))QVariantAnimation::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QVariantAnimation::duration
+120 (int (*)(...))QVariantAnimation::updateCurrentTime
+128 (int (*)(...))QVariantAnimation::updateState
+136 (int (*)(...))QAbstractAnimation::updateDirection
+144 (int (*)(...))QVariantAnimation::updateCurrentValue
+152 (int (*)(...))QVariantAnimation::interpolated
+
+Class QVariantAnimation
+ size=16 align=8
+ base size=16 base align=8
+QVariantAnimation (0x0x7f5ebb64bd68) 0
+ vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16)
+ QAbstractAnimation (0x0x7f5ebb64bdd0) 0
+ primary-for QVariantAnimation (0x0x7f5ebb64bd68)
+ QObject (0x0x7f5ebb2895a0) 0
+ primary-for QAbstractAnimation (0x0x7f5ebb64bdd0)
+
+Class QPropertyAnimation::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QPropertyAnimation::QPrivateSignal (0x0x7f5ebb2898a0) 0 empty
+
+Vtable for QPropertyAnimation
+QPropertyAnimation::_ZTV18QPropertyAnimation: 20 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QPropertyAnimation)
+16 (int (*)(...))QPropertyAnimation::metaObject
+24 (int (*)(...))QPropertyAnimation::qt_metacast
+32 (int (*)(...))QPropertyAnimation::qt_metacall
+40 (int (*)(...))QPropertyAnimation::~QPropertyAnimation
+48 (int (*)(...))QPropertyAnimation::~QPropertyAnimation
+56 (int (*)(...))QPropertyAnimation::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QVariantAnimation::duration
+120 (int (*)(...))QVariantAnimation::updateCurrentTime
+128 (int (*)(...))QPropertyAnimation::updateState
+136 (int (*)(...))QAbstractAnimation::updateDirection
+144 (int (*)(...))QPropertyAnimation::updateCurrentValue
+152 (int (*)(...))QVariantAnimation::interpolated
+
+Class QPropertyAnimation
+ size=16 align=8
+ base size=16 base align=8
+QPropertyAnimation (0x0x7f5ebb64bea0) 0
+ vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16)
+ QVariantAnimation (0x0x7f5ebb64bf08) 0
+ primary-for QPropertyAnimation (0x0x7f5ebb64bea0)
+ QAbstractAnimation (0x0x7f5ebb64bf70) 0
+ primary-for QVariantAnimation (0x0x7f5ebb64bf08)
+ QObject (0x0x7f5ebb289840) 0
+ primary-for QAbstractAnimation (0x0x7f5ebb64bf70)
+
+Class std::random_device
+ size=5000 align=8
+ base size=5000 base align=8
+std::random_device (0x0x7f5ebb335000) 0
+
+Class std::bernoulli_distribution::param_type
+ size=8 align=8
+ base size=8 base align=8
+std::bernoulli_distribution::param_type (0x0x7f5ebb40ed20) 0
+
+Class std::bernoulli_distribution
+ size=8 align=8
+ base size=8 base align=8
+std::bernoulli_distribution (0x0x7f5ebb40ecc0) 0
+
+Class std::seed_seq
+ size=24 align=8
+ base size=24 base align=8
+std::seed_seq (0x0x7f5ebb1f6a80) 0
+
+Class QRandomGenerator::Storage
+ size=2504 align=8
+ base size=2504 base align=8
+QRandomGenerator::Storage (0x0x7f5ebb035720) 0
+
+Class QRandomGenerator
+ size=2512 align=8
+ base size=2512 base align=8
+QRandomGenerator (0x0x7f5ebb0356c0) 0
+
+Class QRandomGenerator64
+ size=2512 align=8
+ base size=2512 base align=8
+QRandomGenerator64 (0x0x7f5ebac2cc30) 0
+ QRandomGenerator (0x0x7f5ebac59240) 0
+
+Class QReadWriteLock
+ size=8 align=8
+ base size=8 base align=8
+QReadWriteLock (0x0x7f5ebac59de0) 0
+
+Class QReadLocker
+ size=8 align=8
+ base size=8 base align=8
+QReadLocker (0x0x7f5ebacd90c0) 0
+
+Class QWriteLocker
+ size=8 align=8
+ base size=8 base align=8
+QWriteLocker (0x0x7f5ebacd95a0) 0
+
+Class QSize
+ size=8 align=4
+ base size=8 base align=4
+QSize (0x0x7f5ebacd9a80) 0
+
+Class QSizeF
+ size=16 align=8
+ base size=16 base align=8
+QSizeF (0x0x7f5ebad478a0) 0
+
+Class QRect
+ size=16 align=4
+ base size=16 base align=4
+QRect (0x0x7f5ebadc3840) 0
+
+Class QRectF
+ size=32 align=8
+ base size=32 base align=8
+QRectF (0x0x7f5ebaa778a0) 0
+
+Class QResource
+ size=8 align=8
+ base size=8 base align=8
+QResource (0x0x7f5ebab359c0) 0
+
+Class QSaveFile::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSaveFile::QPrivateSignal (0x0x7f5ebab35c60) 0 empty
+
+Vtable for QSaveFile
+QSaveFile::_ZTV9QSaveFile: 34 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QSaveFile)
+16 (int (*)(...))QSaveFile::metaObject
+24 (int (*)(...))QSaveFile::qt_metacast
+32 (int (*)(...))QSaveFile::qt_metacall
+40 (int (*)(...))QSaveFile::~QSaveFile
+48 (int (*)(...))QSaveFile::~QSaveFile
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QFileDevice::isSequential
+120 (int (*)(...))QSaveFile::open
+128 (int (*)(...))QSaveFile::close
+136 (int (*)(...))QFileDevice::pos
+144 (int (*)(...))QFileDevice::size
+152 (int (*)(...))QFileDevice::seek
+160 (int (*)(...))QFileDevice::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QIODevice::bytesAvailable
+184 (int (*)(...))QIODevice::bytesToWrite
+192 (int (*)(...))QIODevice::canReadLine
+200 (int (*)(...))QIODevice::waitForReadyRead
+208 (int (*)(...))QIODevice::waitForBytesWritten
+216 (int (*)(...))QFileDevice::readData
+224 (int (*)(...))QFileDevice::readLineData
+232 (int (*)(...))QSaveFile::writeData
+240 (int (*)(...))QSaveFile::fileName
+248 (int (*)(...))QFileDevice::resize
+256 (int (*)(...))QFileDevice::permissions
+264 (int (*)(...))QFileDevice::setPermissions
+
+Class QSaveFile
+ size=16 align=8
+ base size=16 base align=8
+QSaveFile (0x0x7f5ebaafa618) 0
+ vptr=((& QSaveFile::_ZTV9QSaveFile) + 16)
+ QFileDevice (0x0x7f5ebaafa680) 0
+ primary-for QSaveFile (0x0x7f5ebaafa618)
+ QIODevice (0x0x7f5ebaafa6e8) 0
+ primary-for QFileDevice (0x0x7f5ebaafa680)
+ QObject (0x0x7f5ebab35c00) 0
+ primary-for QIODevice (0x0x7f5ebaafa6e8)
+
+Class QSemaphore
+ size=8 align=8
+ base size=8 base align=8
+QSemaphore (0x0x7f5ebab8e2a0) 0
+
+Class QSemaphoreReleaser
+ size=16 align=8
+ base size=12 base align=8
+QSemaphoreReleaser (0x0x7f5ebab8e420) 0
+
+Class QSequentialAnimationGroup::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSequentialAnimationGroup::QPrivateSignal (0x0x7f5eba89c6c0) 0 empty
+
+Vtable for QSequentialAnimationGroup
+QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup: 18 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI25QSequentialAnimationGroup)
+16 (int (*)(...))QSequentialAnimationGroup::metaObject
+24 (int (*)(...))QSequentialAnimationGroup::qt_metacast
+32 (int (*)(...))QSequentialAnimationGroup::qt_metacall
+40 (int (*)(...))QSequentialAnimationGroup::~QSequentialAnimationGroup
+48 (int (*)(...))QSequentialAnimationGroup::~QSequentialAnimationGroup
+56 (int (*)(...))QSequentialAnimationGroup::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QSequentialAnimationGroup::duration
+120 (int (*)(...))QSequentialAnimationGroup::updateCurrentTime
+128 (int (*)(...))QSequentialAnimationGroup::updateState
+136 (int (*)(...))QSequentialAnimationGroup::updateDirection
+
+Class QSequentialAnimationGroup
+ size=16 align=8
+ base size=16 base align=8
+QSequentialAnimationGroup (0x0x7f5eba89e410) 0
+ vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16)
+ QAnimationGroup (0x0x7f5eba89e478) 0
+ primary-for QSequentialAnimationGroup (0x0x7f5eba89e410)
+ QAbstractAnimation (0x0x7f5eba89e4e0) 0
+ primary-for QAnimationGroup (0x0x7f5eba89e478)
+ QObject (0x0x7f5eba89c660) 0
+ primary-for QAbstractAnimation (0x0x7f5eba89e4e0)
+
+Class QSettings::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSettings::QPrivateSignal (0x0x7f5eba89c900) 0 empty
+
+Vtable for QSettings
+QSettings::_ZTV9QSettings: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QSettings)
+16 (int (*)(...))QSettings::metaObject
+24 (int (*)(...))QSettings::qt_metacast
+32 (int (*)(...))QSettings::qt_metacall
+40 (int (*)(...))QSettings::~QSettings
+48 (int (*)(...))QSettings::~QSettings
+56 (int (*)(...))QSettings::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QSettings
+ size=16 align=8
+ base size=16 base align=8
+QSettings (0x0x7f5eba89e548) 0
+ vptr=((& QSettings::_ZTV9QSettings) + 16)
+ QObject (0x0x7f5eba89c8a0) 0
+ primary-for QSettings (0x0x7f5eba89e548)
+
+Class QSharedMemory::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSharedMemory::QPrivateSignal (0x0x7f5eba89cd80) 0 empty
+
+Vtable for QSharedMemory
+QSharedMemory::_ZTV13QSharedMemory: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QSharedMemory)
+16 (int (*)(...))QSharedMemory::metaObject
+24 (int (*)(...))QSharedMemory::qt_metacast
+32 (int (*)(...))QSharedMemory::qt_metacall
+40 (int (*)(...))QSharedMemory::~QSharedMemory
+48 (int (*)(...))QSharedMemory::~QSharedMemory
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QSharedMemory
+ size=16 align=8
+ base size=16 base align=8
+QSharedMemory (0x0x7f5eba89e5b0) 0
+ vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16)
+ QObject (0x0x7f5eba89cd20) 0
+ primary-for QSharedMemory (0x0x7f5eba89e5b0)
+
+Class QSignalMapper::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSignalMapper::QPrivateSignal (0x0x7f5eba8e9000) 0 empty
+
+Vtable for QSignalMapper
+QSignalMapper::_ZTV13QSignalMapper: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QSignalMapper)
+16 (int (*)(...))QSignalMapper::metaObject
+24 (int (*)(...))QSignalMapper::qt_metacast
+32 (int (*)(...))QSignalMapper::qt_metacall
+40 (int (*)(...))QSignalMapper::~QSignalMapper
+48 (int (*)(...))QSignalMapper::~QSignalMapper
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QSignalMapper
+ size=16 align=8
+ base size=16 base align=8
+QSignalMapper (0x0x7f5eba89e618) 0
+ vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16)
+ QObject (0x0x7f5eba89cf60) 0
+ primary-for QSignalMapper (0x0x7f5eba89e618)
+
+Class QSignalTransition::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSignalTransition::QPrivateSignal (0x0x7f5eba8e9240) 0 empty
+
+Vtable for QSignalTransition
+QSignalTransition::_ZTV17QSignalTransition: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI17QSignalTransition)
+16 (int (*)(...))QSignalTransition::metaObject
+24 (int (*)(...))QSignalTransition::qt_metacast
+32 (int (*)(...))QSignalTransition::qt_metacall
+40 (int (*)(...))QSignalTransition::~QSignalTransition
+48 (int (*)(...))QSignalTransition::~QSignalTransition
+56 (int (*)(...))QSignalTransition::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QSignalTransition::eventTest
+120 (int (*)(...))QSignalTransition::onTransition
+
+Class QSignalTransition
+ size=16 align=8
+ base size=16 base align=8
+QSignalTransition (0x0x7f5eba89e680) 0
+ vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16)
+ QAbstractTransition (0x0x7f5eba89e6e8) 0
+ primary-for QSignalTransition (0x0x7f5eba89e680)
+ QObject (0x0x7f5eba8e91e0) 0
+ primary-for QAbstractTransition (0x0x7f5eba89e6e8)
+
+Class QSocketNotifier::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSocketNotifier::QPrivateSignal (0x0x7f5eba8e94e0) 0 empty
+
+Vtable for QSocketNotifier
+QSocketNotifier::_ZTV15QSocketNotifier: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI15QSocketNotifier)
+16 (int (*)(...))QSocketNotifier::metaObject
+24 (int (*)(...))QSocketNotifier::qt_metacast
+32 (int (*)(...))QSocketNotifier::qt_metacall
+40 (int (*)(...))QSocketNotifier::~QSocketNotifier
+48 (int (*)(...))QSocketNotifier::~QSocketNotifier
+56 (int (*)(...))QSocketNotifier::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QSocketNotifier
+ size=16 align=8
+ base size=16 base align=8
+QSocketNotifier (0x0x7f5eba89e750) 0
+ vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16)
+ QObject (0x0x7f5eba8e9480) 0
+ primary-for QSocketNotifier (0x0x7f5eba89e750)
+
+Class QSortFilterProxyModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSortFilterProxyModel::QPrivateSignal (0x0x7f5eba8e9720) 0 empty
+
+Vtable for QSortFilterProxyModel
+QSortFilterProxyModel::_ZTV21QSortFilterProxyModel: 56 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI21QSortFilterProxyModel)
+16 (int (*)(...))QSortFilterProxyModel::metaObject
+24 (int (*)(...))QSortFilterProxyModel::qt_metacast
+32 (int (*)(...))QSortFilterProxyModel::qt_metacall
+40 (int (*)(...))QSortFilterProxyModel::~QSortFilterProxyModel
+48 (int (*)(...))QSortFilterProxyModel::~QSortFilterProxyModel
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QSortFilterProxyModel::index
+120 (int (*)(...))QSortFilterProxyModel::parent
+128 (int (*)(...))QSortFilterProxyModel::sibling
+136 (int (*)(...))QSortFilterProxyModel::rowCount
+144 (int (*)(...))QSortFilterProxyModel::columnCount
+152 (int (*)(...))QSortFilterProxyModel::hasChildren
+160 (int (*)(...))QSortFilterProxyModel::data
+168 (int (*)(...))QSortFilterProxyModel::setData
+176 (int (*)(...))QSortFilterProxyModel::headerData
+184 (int (*)(...))QSortFilterProxyModel::setHeaderData
+192 (int (*)(...))QAbstractProxyModel::itemData
+200 (int (*)(...))QAbstractProxyModel::setItemData
+208 (int (*)(...))QSortFilterProxyModel::mimeTypes
+216 (int (*)(...))QSortFilterProxyModel::mimeData
+224 (int (*)(...))QAbstractProxyModel::canDropMimeData
+232 (int (*)(...))QSortFilterProxyModel::dropMimeData
+240 (int (*)(...))QSortFilterProxyModel::supportedDropActions
+248 (int (*)(...))QAbstractProxyModel::supportedDragActions
+256 (int (*)(...))QSortFilterProxyModel::insertRows
+264 (int (*)(...))QSortFilterProxyModel::insertColumns
+272 (int (*)(...))QSortFilterProxyModel::removeRows
+280 (int (*)(...))QSortFilterProxyModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QSortFilterProxyModel::fetchMore
+312 (int (*)(...))QSortFilterProxyModel::canFetchMore
+320 (int (*)(...))QSortFilterProxyModel::flags
+328 (int (*)(...))QSortFilterProxyModel::sort
+336 (int (*)(...))QSortFilterProxyModel::buddy
+344 (int (*)(...))QSortFilterProxyModel::match
+352 (int (*)(...))QSortFilterProxyModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractProxyModel::submit
+376 (int (*)(...))QAbstractProxyModel::revert
+384 (int (*)(...))QSortFilterProxyModel::setSourceModel
+392 (int (*)(...))QSortFilterProxyModel::mapToSource
+400 (int (*)(...))QSortFilterProxyModel::mapFromSource
+408 (int (*)(...))QSortFilterProxyModel::mapSelectionToSource
+416 (int (*)(...))QSortFilterProxyModel::mapSelectionFromSource
+424 (int (*)(...))QSortFilterProxyModel::filterAcceptsRow
+432 (int (*)(...))QSortFilterProxyModel::filterAcceptsColumn
+440 (int (*)(...))QSortFilterProxyModel::lessThan
+
+Class QSortFilterProxyModel
+ size=16 align=8
+ base size=16 base align=8
+QSortFilterProxyModel (0x0x7f5eba89e7b8) 0
+ vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16)
+ QAbstractProxyModel (0x0x7f5eba89e820) 0
+ primary-for QSortFilterProxyModel (0x0x7f5eba89e7b8)
+ QAbstractItemModel (0x0x7f5eba89e888) 0
+ primary-for QAbstractProxyModel (0x0x7f5eba89e820)
+ QObject (0x0x7f5eba8e96c0) 0
+ primary-for QAbstractItemModel (0x0x7f5eba89e888)
+
+Class QStandardPaths
+ size=1 align=1
+ base size=0 base align=1
+QStandardPaths (0x0x7f5eba8e9b40) 0 empty
+
+Class QState::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QState::QPrivateSignal (0x0x7f5eba962480) 0 empty
+
+Vtable for QState
+QState::_ZTV6QState: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI6QState)
+16 (int (*)(...))QState::metaObject
+24 (int (*)(...))QState::qt_metacast
+32 (int (*)(...))QState::qt_metacall
+40 (int (*)(...))QState::~QState
+48 (int (*)(...))QState::~QState
+56 (int (*)(...))QState::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QState::onEntry
+120 (int (*)(...))QState::onExit
+
+Class QState
+ size=16 align=8
+ base size=16 base align=8
+QState (0x0x7f5eba89ea28) 0
+ vptr=((& QState::_ZTV6QState) + 16)
+ QAbstractState (0x0x7f5eba89ea90) 0
+ primary-for QState (0x0x7f5eba89ea28)
+ QObject (0x0x7f5eba962420) 0
+ primary-for QAbstractState (0x0x7f5eba89ea90)
+
+Class QStateMachine::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QStateMachine::QPrivateSignal (0x0x7f5eba962900) 0 empty
+
+Vtable for QStateMachine::SignalEvent
+QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN13QStateMachine11SignalEventE)
+16 (int (*)(...))QStateMachine::SignalEvent::~SignalEvent
+24 (int (*)(...))QStateMachine::SignalEvent::~SignalEvent
+
+Class QStateMachine::SignalEvent
+ size=48 align=8
+ base size=48 base align=8
+QStateMachine::SignalEvent (0x0x7f5eba89ec30) 0
+ vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16)
+ QEvent (0x0x7f5eba962960) 0
+ primary-for QStateMachine::SignalEvent (0x0x7f5eba89ec30)
+
+Vtable for QStateMachine::WrappedEvent
+QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN13QStateMachine12WrappedEventE)
+16 (int (*)(...))QStateMachine::WrappedEvent::~WrappedEvent
+24 (int (*)(...))QStateMachine::WrappedEvent::~WrappedEvent
+
+Class QStateMachine::WrappedEvent
+ size=40 align=8
+ base size=40 base align=8
+QStateMachine::WrappedEvent (0x0x7f5eba89ec98) 0
+ vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16)
+ QEvent (0x0x7f5eba9629c0) 0
+ primary-for QStateMachine::WrappedEvent (0x0x7f5eba89ec98)
+
+Vtable for QStateMachine
+QStateMachine::_ZTV13QStateMachine: 20 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QStateMachine)
+16 (int (*)(...))QStateMachine::metaObject
+24 (int (*)(...))QStateMachine::qt_metacast
+32 (int (*)(...))QStateMachine::qt_metacall
+40 (int (*)(...))QStateMachine::~QStateMachine
+48 (int (*)(...))QStateMachine::~QStateMachine
+56 (int (*)(...))QStateMachine::event
+64 (int (*)(...))QStateMachine::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QStateMachine::onEntry
+120 (int (*)(...))QStateMachine::onExit
+128 (int (*)(...))QStateMachine::beginSelectTransitions
+136 (int (*)(...))QStateMachine::endSelectTransitions
+144 (int (*)(...))QStateMachine::beginMicrostep
+152 (int (*)(...))QStateMachine::endMicrostep
+
+Class QStateMachine
+ size=16 align=8
+ base size=16 base align=8
+QStateMachine (0x0x7f5eba89eaf8) 0
+ vptr=((& QStateMachine::_ZTV13QStateMachine) + 16)
+ QState (0x0x7f5eba89eb60) 0
+ primary-for QStateMachine (0x0x7f5eba89eaf8)
+ QAbstractState (0x0x7f5eba89ebc8) 0
+ primary-for QState (0x0x7f5eba89eb60)
+ QObject (0x0x7f5eba9628a0) 0
+ primary-for QAbstractState (0x0x7f5eba89ebc8)
+
+Class QStorageInfo
+ size=8 align=8
+ base size=8 base align=8
+QStorageInfo (0x0x7f5eba962d80) 0
+
+Class QAbstractConcatenable
+ size=1 align=1
+ base size=0 base align=1
+QAbstractConcatenable (0x0x7f5eba61cd80) 0 empty
+
+Class QStringListModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QStringListModel::QPrivateSignal (0x0x7f5eba6cb120) 0 empty
+
+Vtable for QStringListModel
+QStringListModel::_ZTV16QStringListModel: 48 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI16QStringListModel)
+16 (int (*)(...))QStringListModel::metaObject
+24 (int (*)(...))QStringListModel::qt_metacast
+32 (int (*)(...))QStringListModel::qt_metacall
+40 (int (*)(...))QStringListModel::~QStringListModel
+48 (int (*)(...))QStringListModel::~QStringListModel
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QAbstractListModel::index
+120 (int (*)(...))QAbstractListModel::parent
+128 (int (*)(...))QStringListModel::sibling
+136 (int (*)(...))QStringListModel::rowCount
+144 (int (*)(...))QAbstractListModel::columnCount
+152 (int (*)(...))QAbstractListModel::hasChildren
+160 (int (*)(...))QStringListModel::data
+168 (int (*)(...))QStringListModel::setData
+176 (int (*)(...))QAbstractItemModel::headerData
+184 (int (*)(...))QAbstractItemModel::setHeaderData
+192 (int (*)(...))QStringListModel::itemData
+200 (int (*)(...))QStringListModel::setItemData
+208 (int (*)(...))QAbstractItemModel::mimeTypes
+216 (int (*)(...))QAbstractItemModel::mimeData
+224 (int (*)(...))QAbstractItemModel::canDropMimeData
+232 (int (*)(...))QAbstractListModel::dropMimeData
+240 (int (*)(...))QStringListModel::supportedDropActions
+248 (int (*)(...))QAbstractItemModel::supportedDragActions
+256 (int (*)(...))QStringListModel::insertRows
+264 (int (*)(...))QAbstractItemModel::insertColumns
+272 (int (*)(...))QStringListModel::removeRows
+280 (int (*)(...))QAbstractItemModel::removeColumns
+288 (int (*)(...))QStringListModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractItemModel::fetchMore
+312 (int (*)(...))QAbstractItemModel::canFetchMore
+320 (int (*)(...))QStringListModel::flags
+328 (int (*)(...))QStringListModel::sort
+336 (int (*)(...))QAbstractItemModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QAbstractItemModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractItemModel::submit
+376 (int (*)(...))QAbstractItemModel::revert
+
+Class QStringListModel
+ size=24 align=8
+ base size=24 base align=8
+QStringListModel (0x0x7f5eba690dd0) 0
+ vptr=((& QStringListModel::_ZTV16QStringListModel) + 16)
+ QAbstractListModel (0x0x7f5eba690e38) 0
+ primary-for QStringListModel (0x0x7f5eba690dd0)
+ QAbstractItemModel (0x0x7f5eba690ea0) 0
+ primary-for QAbstractListModel (0x0x7f5eba690e38)
+ QObject (0x0x7f5eba6cb0c0) 0
+ primary-for QAbstractItemModel (0x0x7f5eba690ea0)
+
+Class QSystemSemaphore
+ size=8 align=8
+ base size=8 base align=8
+QSystemSemaphore (0x0x7f5eba6cb240) 0
+
+Class QTemporaryDir
+ size=8 align=8
+ base size=8 base align=8
+QTemporaryDir (0x0x7f5eba6cb300) 0
+
+Class QTemporaryFile::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QTemporaryFile::QPrivateSignal (0x0x7f5eba6cb420) 0 empty
+
+Vtable for QTemporaryFile
+QTemporaryFile::_ZTV14QTemporaryFile: 34 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI14QTemporaryFile)
+16 (int (*)(...))QTemporaryFile::metaObject
+24 (int (*)(...))QTemporaryFile::qt_metacast
+32 (int (*)(...))QTemporaryFile::qt_metacall
+40 (int (*)(...))QTemporaryFile::~QTemporaryFile
+48 (int (*)(...))QTemporaryFile::~QTemporaryFile
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QFileDevice::isSequential
+120 (int (*)(...))QTemporaryFile::open
+128 (int (*)(...))QFileDevice::close
+136 (int (*)(...))QFileDevice::pos
+144 (int (*)(...))QFile::size
+152 (int (*)(...))QFileDevice::seek
+160 (int (*)(...))QFileDevice::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QIODevice::bytesAvailable
+184 (int (*)(...))QIODevice::bytesToWrite
+192 (int (*)(...))QIODevice::canReadLine
+200 (int (*)(...))QIODevice::waitForReadyRead
+208 (int (*)(...))QIODevice::waitForBytesWritten
+216 (int (*)(...))QFileDevice::readData
+224 (int (*)(...))QFileDevice::readLineData
+232 (int (*)(...))QFileDevice::writeData
+240 (int (*)(...))QTemporaryFile::fileName
+248 (int (*)(...))QFile::resize
+256 (int (*)(...))QFile::permissions
+264 (int (*)(...))QFile::setPermissions
+
+Class QTemporaryFile
+ size=16 align=8
+ base size=16 base align=8
+QTemporaryFile (0x0x7f5eba690f08) 0
+ vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16)
+ QFile (0x0x7f5eba690f70) 0
+ primary-for QTemporaryFile (0x0x7f5eba690f08)
+ QFileDevice (0x0x7f5eba6fc000) 0
+ primary-for QFile (0x0x7f5eba690f70)
+ QIODevice (0x0x7f5eba6fc068) 0
+ primary-for QFileDevice (0x0x7f5eba6fc000)
+ QObject (0x0x7f5eba6cb3c0) 0
+ primary-for QIODevice (0x0x7f5eba6fc068)
+
+Class QTextBoundaryFinder
+ size=48 align=8
+ base size=48 base align=8
+QTextBoundaryFinder (0x0x7f5eba6cb780) 0
+
+Class QTextCodec::ConverterState
+ size=32 align=8
+ base size=32 base align=8
+QTextCodec::ConverterState (0x0x7f5eba74d000) 0
+
+Vtable for QTextCodec
+QTextCodec::_ZTV10QTextCodec: 9 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI10QTextCodec)
+16 (int (*)(...))__cxa_pure_virtual
+24 (int (*)(...))QTextCodec::aliases
+32 (int (*)(...))__cxa_pure_virtual
+40 (int (*)(...))__cxa_pure_virtual
+48 (int (*)(...))__cxa_pure_virtual
+56 0
+64 0
+
+Class QTextCodec
+ size=8 align=8
+ base size=8 base align=8
+QTextCodec (0x0x7f5eba6cbf60) 0 nearly-empty
+ vptr=((& QTextCodec::_ZTV10QTextCodec) + 16)
+
+Class QTextEncoder
+ size=40 align=8
+ base size=40 base align=8
+QTextEncoder (0x0x7f5eba74d9c0) 0
+
+Class QTextDecoder
+ size=40 align=8
+ base size=40 base align=8
+QTextDecoder (0x0x7f5eba74dba0) 0
+
+Class std::__mutex_base
+ size=40 align=8
+ base size=40 base align=8
+std::__mutex_base (0x0x7f5eba74dd80) 0
+
+Class std::mutex
+ size=40 align=8
+ base size=40 base align=8
+std::mutex (0x0x7f5eba6fc270) 0
+ std::__mutex_base (0x0x7f5eba74dde0) 0
+
+Class std::defer_lock_t
+ size=1 align=1
+ base size=0 base align=1
+std::defer_lock_t (0x0x7f5eba7a3000) 0 empty
+
+Class std::try_to_lock_t
+ size=1 align=1
+ base size=0 base align=1
+std::try_to_lock_t (0x0x7f5eba7a3060) 0 empty
+
+Class std::adopt_lock_t
+ size=1 align=1
+ base size=0 base align=1
+std::adopt_lock_t (0x0x7f5eba7a30c0) 0 empty
+
+Class std::__recursive_mutex_base
+ size=40 align=8
+ base size=40 base align=8
+std::__recursive_mutex_base (0x0x7f5eba7a3ae0) 0
+
+Class std::recursive_mutex
+ size=40 align=8
+ base size=40 base align=8
+std::recursive_mutex (0x0x7f5eba6fc2d8) 0
+ std::__recursive_mutex_base (0x0x7f5eba7a3b40) 0
+
+Class std::timed_mutex
+ size=40 align=8
+ base size=40 base align=8
+std::timed_mutex (0x0x7f5eba7c61c0) 0
+ std::__mutex_base (0x0x7f5eba7a3f00) 0
+ std::__timed_mutex_impl<std::timed_mutex> (0x0x7f5eba7a3f60) 0 empty
+
+Class std::recursive_timed_mutex
+ size=40 align=8
+ base size=40 base align=8
+std::recursive_timed_mutex (0x0x7f5eba7c6540) 0
+ std::__recursive_mutex_base (0x0x7f5eba7ee300) 0
+ std::__timed_mutex_impl<std::recursive_timed_mutex> (0x0x7f5eba7ee360) 0 empty
+
+Class std::once_flag
+ size=4 align=4
+ base size=4 base align=4
+std::once_flag (0x0x7f5eba7eea80) 0
+
+Vtable for __gnu_cxx::__concurrence_lock_error
+__gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_lock_errorE)
+16 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error
+24 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error
+32 (int (*)(...))__gnu_cxx::__concurrence_lock_error::what
+
+Class __gnu_cxx::__concurrence_lock_error
+ size=8 align=8
+ base size=8 base align=8
+__gnu_cxx::__concurrence_lock_error (0x0x7f5eba6fc410) 0 nearly-empty
+ vptr=((& __gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE) + 16)
+ std::exception (0x0x7f5eba425000) 0 nearly-empty
+ primary-for __gnu_cxx::__concurrence_lock_error (0x0x7f5eba6fc410)
+
+Vtable for __gnu_cxx::__concurrence_unlock_error
+__gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN9__gnu_cxx26__concurrence_unlock_errorE)
+16 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error
+24 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error
+32 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::what
+
+Class __gnu_cxx::__concurrence_unlock_error
+ size=8 align=8
+ base size=8 base align=8
+__gnu_cxx::__concurrence_unlock_error (0x0x7f5eba6fc478) 0 nearly-empty
+ vptr=((& __gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE) + 16)
+ std::exception (0x0x7f5eba425120) 0 nearly-empty
+ primary-for __gnu_cxx::__concurrence_unlock_error (0x0x7f5eba6fc478)
+
+Vtable for __gnu_cxx::__concurrence_broadcast_error
+__gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN9__gnu_cxx29__concurrence_broadcast_errorE)
+16 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error
+24 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error
+32 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::what
+
+Class __gnu_cxx::__concurrence_broadcast_error
+ size=8 align=8
+ base size=8 base align=8
+__gnu_cxx::__concurrence_broadcast_error (0x0x7f5eba6fc4e0) 0 nearly-empty
+ vptr=((& __gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE) + 16)
+ std::exception (0x0x7f5eba425240) 0 nearly-empty
+ primary-for __gnu_cxx::__concurrence_broadcast_error (0x0x7f5eba6fc4e0)
+
+Vtable for __gnu_cxx::__concurrence_wait_error
+__gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_wait_errorE)
+16 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error
+24 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error
+32 (int (*)(...))__gnu_cxx::__concurrence_wait_error::what
+
+Class __gnu_cxx::__concurrence_wait_error
+ size=8 align=8
+ base size=8 base align=8
+__gnu_cxx::__concurrence_wait_error (0x0x7f5eba6fc5b0) 0 nearly-empty
+ vptr=((& __gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE) + 16)
+ std::exception (0x0x7f5eba425360) 0 nearly-empty
+ primary-for __gnu_cxx::__concurrence_wait_error (0x0x7f5eba6fc5b0)
+
+Class __gnu_cxx::__mutex
+ size=40 align=8
+ base size=40 base align=8
+__gnu_cxx::__mutex (0x0x7f5eba4473c0) 0
+
+Class __gnu_cxx::__recursive_mutex
+ size=40 align=8
+ base size=40 base align=8
+__gnu_cxx::__recursive_mutex (0x0x7f5eba4476c0) 0
+
+Class __gnu_cxx::__scoped_lock
+ size=8 align=8
+ base size=8 base align=8
+__gnu_cxx::__scoped_lock (0x0x7f5eba4479c0) 0
+
+Class __gnu_cxx::__cond
+ size=48 align=8
+ base size=48 base align=8
+__gnu_cxx::__cond (0x0x7f5eba447d20) 0
+
+Vtable for std::bad_weak_ptr
+std::bad_weak_ptr::_ZTVSt12bad_weak_ptr: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt12bad_weak_ptr)
+16 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr
+24 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr
+32 (int (*)(...))std::bad_weak_ptr::what
+
+Class std::bad_weak_ptr
+ size=8 align=8
+ base size=8 base align=8
+std::bad_weak_ptr (0x0x7f5eba6fc618) 0 nearly-empty
+ vptr=((& std::bad_weak_ptr::_ZTVSt12bad_weak_ptr) + 16)
+ std::exception (0x0x7f5eba4c5f00) 0 nearly-empty
+ primary-for std::bad_weak_ptr (0x0x7f5eba6fc618)
+
+Class std::_Sp_make_shared_tag
+ size=1 align=1
+ base size=0 base align=1
+std::_Sp_make_shared_tag (0x0x7f5eba527ea0) 0 empty
+
+Class std::__sp_array_delete
+ size=1 align=1
+ base size=0 base align=1
+std::__sp_array_delete (0x0x7f5eba55a300) 0 empty
+
+Class std::_Sp_locker
+ size=2 align=1
+ base size=2 base align=1
+std::_Sp_locker (0x0x7f5eba29c180) 0
+
+Vtable for std::thread::_State
+std::thread::_State::_ZTVNSt6thread6_StateE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt6thread6_StateE)
+16 0
+24 0
+32 (int (*)(...))__cxa_pure_virtual
+
+Class std::thread::_State
+ size=8 align=8
+ base size=8 base align=8
+std::thread::_State (0x0x7f5eba2c9600) 0 nearly-empty
+ vptr=((& std::thread::_State::_ZTVNSt6thread6_StateE) + 16)
+
+Class std::thread::id
+ size=8 align=8
+ base size=8 base align=8
+std::thread::id (0x0x7f5eba2c9660) 0
+
+Class std::thread
+ size=8 align=8
+ base size=8 base align=8
+std::thread (0x0x7f5eba2c95a0) 0
+
+Class std::condition_variable
+ size=48 align=8
+ base size=48 base align=8
+std::condition_variable (0x0x7f5eba158a20) 0
+
+Class std::__at_thread_exit_elt
+ size=16 align=8
+ base size=16 base align=8
+std::__at_thread_exit_elt (0x0x7f5eba158de0) 0
+
+Class std::_V2::condition_variable_any
+ size=64 align=8
+ base size=64 base align=8
+std::_V2::condition_variable_any (0x0x7f5eba158e40) 0
+
+Class std::__atomic_futex_unsigned_base
+ size=1 align=1
+ base size=0 base align=1
+std::__atomic_futex_unsigned_base (0x0x7f5eb9f11180) 0 empty
+
+Vtable for std::future_error
+std::future_error::_ZTVSt12future_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt12future_error)
+16 (int (*)(...))std::future_error::~future_error
+24 (int (*)(...))std::future_error::~future_error
+32 (int (*)(...))std::future_error::what
+
+Class std::future_error
+ size=32 align=8
+ base size=32 base align=8
+std::future_error (0x0x7f5eb9ef7ea0) 0
+ vptr=((& std::future_error::_ZTVSt12future_error) + 16)
+ std::logic_error (0x0x7f5eb9ef7f08) 0
+ primary-for std::future_error (0x0x7f5eb9ef7ea0)
+ std::exception (0x0x7f5eb9f118a0) 0 nearly-empty
+ primary-for std::logic_error (0x0x7f5eb9ef7f08)
+
+Class std::__future_base::_Result_base::_Deleter
+ size=1 align=1
+ base size=0 base align=1
+std::__future_base::_Result_base::_Deleter (0x0x7f5eb9f45000) 0 empty
+
+Vtable for std::__future_base::_Result_base
+std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt13__future_base12_Result_baseE)
+16 (int (*)(...))__cxa_pure_virtual
+24 0
+32 0
+
+Class std::__future_base::_Result_base
+ size=16 align=8
+ base size=16 base align=8
+std::__future_base::_Result_base (0x0x7f5eb9f11f60) 0
+ vptr=((& std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE) + 16)
+
+Class std::__future_base::_State_baseV2::__exception_ptr_tag
+ size=1 align=1
+ base size=0 base align=1
+std::__future_base::_State_baseV2::__exception_ptr_tag (0x0x7f5eb9d1f720) 0 empty
+
+Class std::__future_base::_State_baseV2::_Make_ready
+ size=32 align=8
+ base size=32 base align=8
+std::__future_base::_State_baseV2::_Make_ready (0x0x7f5eb9d1c750) 0
+ std::__at_thread_exit_elt (0x0x7f5eb9d1f7e0) 0
+
+Vtable for std::__future_base::_State_baseV2
+std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E: 6 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt13__future_base13_State_baseV2E)
+16 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2
+24 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2
+32 (int (*)(...))std::__future_base::_State_baseV2::_M_complete_async
+40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future
+
+Class std::__future_base::_State_baseV2
+ size=32 align=8
+ base size=28 base align=8
+std::__future_base::_State_baseV2 (0x0x7f5eb9f45180) 0
+ vptr=((& std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E) + 16)
+
+Class std::__future_base
+ size=1 align=1
+ base size=0 base align=1
+std::__future_base (0x0x7f5eb9f11f00) 0 empty
+
+Vtable for std::__future_base::_Async_state_commonV2
+std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E: 6 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt13__future_base21_Async_state_commonV2E)
+16 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2
+24 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2
+32 (int (*)(...))std::__future_base::_Async_state_commonV2::_M_complete_async
+40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future
+
+Class std::__future_base::_Async_state_commonV2
+ size=48 align=8
+ base size=44 base align=8
+std::__future_base::_Async_state_commonV2 (0x0x7f5eb949f478) 0
+ vptr=((& std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E) + 16)
+ std::__future_base::_State_baseV2 (0x0x7f5eb94c87e0) 0
+ primary-for std::__future_base::_Async_state_commonV2 (0x0x7f5eb949f478)
+
+Class QThread::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QThread::QPrivateSignal (0x0x7f5eb94fe0c0) 0 empty
+
+Vtable for QThread
+QThread::_ZTV7QThread: 15 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI7QThread)
+16 (int (*)(...))QThread::metaObject
+24 (int (*)(...))QThread::qt_metacast
+32 (int (*)(...))QThread::qt_metacall
+40 (int (*)(...))QThread::~QThread
+48 (int (*)(...))QThread::~QThread
+56 (int (*)(...))QThread::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QThread::run
+
+Class QThread
+ size=16 align=8
+ base size=16 base align=8
+QThread (0x0x7f5eb949f7b8) 0
+ vptr=((& QThread::_ZTV7QThread) + 16)
+ QObject (0x0x7f5eb94fe060) 0
+ primary-for QThread (0x0x7f5eb949f7b8)
+
+Class QThreadPool::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QThreadPool::QPrivateSignal (0x0x7f5eb94fe480) 0 empty
+
+Vtable for QThreadPool
+QThreadPool::_ZTV11QThreadPool: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QThreadPool)
+16 (int (*)(...))QThreadPool::metaObject
+24 (int (*)(...))QThreadPool::qt_metacast
+32 (int (*)(...))QThreadPool::qt_metacall
+40 (int (*)(...))QThreadPool::~QThreadPool
+48 (int (*)(...))QThreadPool::~QThreadPool
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QThreadPool
+ size=16 align=8
+ base size=16 base align=8
+QThreadPool (0x0x7f5eb949f820) 0
+ vptr=((& QThreadPool::_ZTV11QThreadPool) + 16)
+ QObject (0x0x7f5eb94fe420) 0
+ primary-for QThreadPool (0x0x7f5eb949f820)
+
+Class QThreadStorageData
+ size=4 align=4
+ base size=4 base align=4
+QThreadStorageData (0x0x7f5eb94fe660) 0
+
+Class QTimeLine::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QTimeLine::QPrivateSignal (0x0x7f5eb94fed20) 0 empty
+
+Vtable for QTimeLine
+QTimeLine::_ZTV9QTimeLine: 15 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QTimeLine)
+16 (int (*)(...))QTimeLine::metaObject
+24 (int (*)(...))QTimeLine::qt_metacast
+32 (int (*)(...))QTimeLine::qt_metacall
+40 (int (*)(...))QTimeLine::~QTimeLine
+48 (int (*)(...))QTimeLine::~QTimeLine
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QTimeLine::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QTimeLine::valueForTime
+
+Class QTimeLine
+ size=16 align=8
+ base size=16 base align=8
+QTimeLine (0x0x7f5eb949f888) 0
+ vptr=((& QTimeLine::_ZTV9QTimeLine) + 16)
+ QObject (0x0x7f5eb94fecc0) 0
+ primary-for QTimeLine (0x0x7f5eb949f888)
+
+Class QTimer::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QTimer::QPrivateSignal (0x0x7f5eb94fef60) 0 empty
+
+Vtable for QTimer
+QTimer::_ZTV6QTimer: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI6QTimer)
+16 (int (*)(...))QTimer::metaObject
+24 (int (*)(...))QTimer::qt_metacast
+32 (int (*)(...))QTimer::qt_metacall
+40 (int (*)(...))QTimer::~QTimer
+48 (int (*)(...))QTimer::~QTimer
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QTimer::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QTimer
+ size=32 align=8
+ base size=29 base align=8
+QTimer (0x0x7f5eb949f8f0) 0
+ vptr=((& QTimer::_ZTV6QTimer) + 16)
+ QObject (0x0x7f5eb94fef00) 0
+ primary-for QTimer (0x0x7f5eb949f8f0)
+
+Class QTimeZone::OffsetData
+ size=32 align=8
+ base size=28 base align=8
+QTimeZone::OffsetData (0x0x7f5eb9584900) 0
+
+Class QTimeZone
+ size=8 align=8
+ base size=8 base align=8
+QTimeZone (0x0x7f5eb95848a0) 0
+
+Class QTranslator::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QTranslator::QPrivateSignal (0x0x7f5eb92279c0) 0 empty
+
+Vtable for QTranslator
+QTranslator::_ZTV11QTranslator: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QTranslator)
+16 (int (*)(...))QTranslator::metaObject
+24 (int (*)(...))QTranslator::qt_metacast
+32 (int (*)(...))QTranslator::qt_metacall
+40 (int (*)(...))QTranslator::~QTranslator
+48 (int (*)(...))QTranslator::~QTranslator
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QTranslator::translate
+120 (int (*)(...))QTranslator::isEmpty
+
+Class QTranslator
+ size=16 align=8
+ base size=16 base align=8
+QTranslator (0x0x7f5eb9238000) 0
+ vptr=((& QTranslator::_ZTV11QTranslator) + 16)
+ QObject (0x0x7f5eb9227960) 0
+ primary-for QTranslator (0x0x7f5eb9238000)
+
+Class QTransposeProxyModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QTransposeProxyModel::QPrivateSignal (0x0x7f5eb9227c00) 0 empty
+
+Vtable for QTransposeProxyModel
+QTransposeProxyModel::_ZTV20QTransposeProxyModel: 53 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI20QTransposeProxyModel)
+16 (int (*)(...))QTransposeProxyModel::metaObject
+24 (int (*)(...))QTransposeProxyModel::qt_metacast
+32 (int (*)(...))QTransposeProxyModel::qt_metacall
+40 (int (*)(...))QTransposeProxyModel::~QTransposeProxyModel
+48 (int (*)(...))QTransposeProxyModel::~QTransposeProxyModel
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QTransposeProxyModel::index
+120 (int (*)(...))QTransposeProxyModel::parent
+128 (int (*)(...))QAbstractProxyModel::sibling
+136 (int (*)(...))QTransposeProxyModel::rowCount
+144 (int (*)(...))QTransposeProxyModel::columnCount
+152 (int (*)(...))QAbstractProxyModel::hasChildren
+160 (int (*)(...))QAbstractProxyModel::data
+168 (int (*)(...))QAbstractProxyModel::setData
+176 (int (*)(...))QTransposeProxyModel::headerData
+184 (int (*)(...))QTransposeProxyModel::setHeaderData
+192 (int (*)(...))QTransposeProxyModel::itemData
+200 (int (*)(...))QTransposeProxyModel::setItemData
+208 (int (*)(...))QAbstractProxyModel::mimeTypes
+216 (int (*)(...))QAbstractProxyModel::mimeData
+224 (int (*)(...))QAbstractProxyModel::canDropMimeData
+232 (int (*)(...))QAbstractProxyModel::dropMimeData
+240 (int (*)(...))QAbstractProxyModel::supportedDropActions
+248 (int (*)(...))QAbstractProxyModel::supportedDragActions
+256 (int (*)(...))QTransposeProxyModel::insertRows
+264 (int (*)(...))QTransposeProxyModel::insertColumns
+272 (int (*)(...))QTransposeProxyModel::removeRows
+280 (int (*)(...))QTransposeProxyModel::removeColumns
+288 (int (*)(...))QTransposeProxyModel::moveRows
+296 (int (*)(...))QTransposeProxyModel::moveColumns
+304 (int (*)(...))QAbstractProxyModel::fetchMore
+312 (int (*)(...))QAbstractProxyModel::canFetchMore
+320 (int (*)(...))QAbstractProxyModel::flags
+328 (int (*)(...))QTransposeProxyModel::sort
+336 (int (*)(...))QAbstractProxyModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QTransposeProxyModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractProxyModel::submit
+376 (int (*)(...))QAbstractProxyModel::revert
+384 (int (*)(...))QTransposeProxyModel::setSourceModel
+392 (int (*)(...))QTransposeProxyModel::mapToSource
+400 (int (*)(...))QTransposeProxyModel::mapFromSource
+408 (int (*)(...))QAbstractProxyModel::mapSelectionToSource
+416 (int (*)(...))QAbstractProxyModel::mapSelectionFromSource
+
+Class QTransposeProxyModel
+ size=16 align=8
+ base size=16 base align=8
+QTransposeProxyModel (0x0x7f5eb9238068) 0
+ vptr=((& QTransposeProxyModel::_ZTV20QTransposeProxyModel) + 16)
+ QAbstractProxyModel (0x0x7f5eb92380d0) 0
+ primary-for QTransposeProxyModel (0x0x7f5eb9238068)
+ QAbstractItemModel (0x0x7f5eb9238138) 0
+ primary-for QAbstractProxyModel (0x0x7f5eb92380d0)
+ QObject (0x0x7f5eb9227ba0) 0
+ primary-for QAbstractItemModel (0x0x7f5eb9238138)
+
+Class QUrlQuery
+ size=8 align=8
+ base size=8 base align=8
+QUrlQuery (0x0x7f5eb9227de0) 0
+
+Class QWaitCondition
+ size=8 align=8
+ base size=8 base align=8
+QWaitCondition (0x0x7f5eb92cb7e0) 0
+
+Class QXmlStreamStringRef
+ size=16 align=8
+ base size=16 base align=8
+QXmlStreamStringRef (0x0x7f5eb92cb900) 0
+
+Class QXmlStreamAttribute
+ size=80 align=8
+ base size=73 base align=8
+QXmlStreamAttribute (0x0x7f5eb9359cc0) 0
+
+Class QXmlStreamAttributes
+ size=8 align=8
+ base size=8 base align=8
+QXmlStreamAttributes (0x0x7f5eb93d47b8) 0
+ QVector<QXmlStreamAttribute> (0x0x7f5eb93d7420) 0
+
+Class QXmlStreamNamespaceDeclaration
+ size=40 align=8
+ base size=40 base align=8
+QXmlStreamNamespaceDeclaration (0x0x7f5eb93d7720) 0
+
+Class QXmlStreamNotationDeclaration
+ size=56 align=8
+ base size=56 base align=8
+QXmlStreamNotationDeclaration (0x0x7f5eb8fdd6c0) 0
+
+Class QXmlStreamEntityDeclaration
+ size=88 align=8
+ base size=88 base align=8
+QXmlStreamEntityDeclaration (0x0x7f5eb903a6c0) 0
+
+Vtable for QXmlStreamEntityResolver
+QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver: 6 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI24QXmlStreamEntityResolver)
+16 (int (*)(...))QXmlStreamEntityResolver::~QXmlStreamEntityResolver
+24 (int (*)(...))QXmlStreamEntityResolver::~QXmlStreamEntityResolver
+32 (int (*)(...))QXmlStreamEntityResolver::resolveEntity
+40 (int (*)(...))QXmlStreamEntityResolver::resolveUndeclaredEntity
+
+Class QXmlStreamEntityResolver
+ size=8 align=8
+ base size=8 base align=8
+QXmlStreamEntityResolver (0x0x7f5eb90a3780) 0 nearly-empty
+ vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16)
+
+Class QXmlStreamReader
+ size=8 align=8
+ base size=8 base align=8
+QXmlStreamReader (0x0x7f5eb90a37e0) 0
+
+Class QXmlStreamWriter
+ size=8 align=8
+ base size=8 base align=8
+QXmlStreamWriter (0x0x7f5eb90fa6c0) 0
+
+Class QBluetoothAddress
+ size=8 align=8
+ base size=8 base align=8
+QBluetoothAddress (0x0x7f5eb914e660) 0
+
+Class QBluetoothDeviceInfo
+ size=8 align=8
+ base size=8 base align=8
+QBluetoothDeviceInfo (0x0x7f5eb914e9c0) 0
+
+Class QBluetoothDeviceDiscoveryAgent::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QBluetoothDeviceDiscoveryAgent::QPrivateSignal (0x0x7f5eb8dccae0) 0 empty
+
+Vtable for QBluetoothDeviceDiscoveryAgent
+QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI30QBluetoothDeviceDiscoveryAgent)
+16 (int (*)(...))QBluetoothDeviceDiscoveryAgent::metaObject
+24 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacast
+32 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacall
+40 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent
+48 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QBluetoothDeviceDiscoveryAgent
+ size=24 align=8
+ base size=24 base align=8
+QBluetoothDeviceDiscoveryAgent (0x0x7f5eb91037b8) 0
+ vptr=((& QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent) + 16)
+ QObject (0x0x7f5eb8dcca80) 0
+ primary-for QBluetoothDeviceDiscoveryAgent (0x0x7f5eb91037b8)
+
+Class QBluetoothHostInfo
+ size=8 align=8
+ base size=8 base align=8
+QBluetoothHostInfo (0x0x7f5eb8e2b600) 0
+
+Class QBluetoothLocalDevice::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QBluetoothLocalDevice::QPrivateSignal (0x0x7f5eb8e2b960) 0 empty
+
+Vtable for QBluetoothLocalDevice
+QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI21QBluetoothLocalDevice)
+16 (int (*)(...))QBluetoothLocalDevice::metaObject
+24 (int (*)(...))QBluetoothLocalDevice::qt_metacast
+32 (int (*)(...))QBluetoothLocalDevice::qt_metacall
+40 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice
+48 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QBluetoothLocalDevice
+ size=24 align=8
+ base size=24 base align=8
+QBluetoothLocalDevice (0x0x7f5eb91038f0) 0
+ vptr=((& QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice) + 16)
+ QObject (0x0x7f5eb8e2b900) 0
+ primary-for QBluetoothLocalDevice (0x0x7f5eb91038f0)
+
+Class quint128
+ size=16 align=1
+ base size=16 base align=1
+quint128 (0x0x7f5eb8e73360) 0
+
+Class QBluetoothUuid
+ size=16 align=4
+ base size=16 base align=4
+QBluetoothUuid (0x0x7f5eb9103958) 0
+ QUuid (0x0x7f5eb8e733c0) 0
+
+Class QBluetoothServiceInfo::Sequence
+ size=8 align=8
+ base size=8 base align=8
+QBluetoothServiceInfo::Sequence (0x0x7f5eb91039c0) 0
+ QList<QVariant> (0x0x7f5eb9103a28) 0
+ QListSpecialMethods<QVariant> (0x0x7f5eb8e738a0) 0 empty
+
+Class QBluetoothServiceInfo::Alternative
+ size=8 align=8
+ base size=8 base align=8
+QBluetoothServiceInfo::Alternative (0x0x7f5eb9103a90) 0
+ QList<QVariant> (0x0x7f5eb9103af8) 0
+ QListSpecialMethods<QVariant> (0x0x7f5eb8e73900) 0 empty
+
+Class QBluetoothServiceInfo
+ size=16 align=8
+ base size=16 base align=8
+QBluetoothServiceInfo (0x0x7f5eb8e73840) 0
+
+Class QAbstractSocket::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractSocket::QPrivateSignal (0x0x7f5eb8ef0ae0) 0 empty
+
+Vtable for QAbstractSocket
+QAbstractSocket::_ZTV15QAbstractSocket: 41 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI15QAbstractSocket)
+16 (int (*)(...))QAbstractSocket::metaObject
+24 (int (*)(...))QAbstractSocket::qt_metacast
+32 (int (*)(...))QAbstractSocket::qt_metacall
+40 (int (*)(...))QAbstractSocket::~QAbstractSocket
+48 (int (*)(...))QAbstractSocket::~QAbstractSocket
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QAbstractSocket::isSequential
+120 (int (*)(...))QIODevice::open
+128 (int (*)(...))QAbstractSocket::close
+136 (int (*)(...))QIODevice::pos
+144 (int (*)(...))QIODevice::size
+152 (int (*)(...))QIODevice::seek
+160 (int (*)(...))QAbstractSocket::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QAbstractSocket::bytesAvailable
+184 (int (*)(...))QAbstractSocket::bytesToWrite
+192 (int (*)(...))QAbstractSocket::canReadLine
+200 (int (*)(...))QAbstractSocket::waitForReadyRead
+208 (int (*)(...))QAbstractSocket::waitForBytesWritten
+216 (int (*)(...))QAbstractSocket::readData
+224 (int (*)(...))QAbstractSocket::readLineData
+232 (int (*)(...))QAbstractSocket::writeData
+240 (int (*)(...))QAbstractSocket::resume
+248 (int (*)(...))QAbstractSocket::connectToHost
+256 (int (*)(...))QAbstractSocket::connectToHost
+264 (int (*)(...))QAbstractSocket::disconnectFromHost
+272 (int (*)(...))QAbstractSocket::setReadBufferSize
+280 (int (*)(...))QAbstractSocket::socketDescriptor
+288 (int (*)(...))QAbstractSocket::setSocketDescriptor
+296 (int (*)(...))QAbstractSocket::setSocketOption
+304 (int (*)(...))QAbstractSocket::socketOption
+312 (int (*)(...))QAbstractSocket::waitForConnected
+320 (int (*)(...))QAbstractSocket::waitForDisconnected
+
+Class QAbstractSocket
+ size=16 align=8
+ base size=16 base align=8
+QAbstractSocket (0x0x7f5eb9103b60) 0
+ vptr=((& QAbstractSocket::_ZTV15QAbstractSocket) + 16)
+ QIODevice (0x0x7f5eb9103bc8) 0
+ primary-for QAbstractSocket (0x0x7f5eb9103b60)
+ QObject (0x0x7f5eb8ef0a80) 0
+ primary-for QIODevice (0x0x7f5eb9103bc8)
+
+Class QBluetoothSocket::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QBluetoothSocket::QPrivateSignal (0x0x7f5eb8aaa2a0) 0 empty
+
+Vtable for QBluetoothSocket
+QBluetoothSocket::_ZTV16QBluetoothSocket: 30 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI16QBluetoothSocket)
+16 (int (*)(...))QBluetoothSocket::metaObject
+24 (int (*)(...))QBluetoothSocket::qt_metacast
+32 (int (*)(...))QBluetoothSocket::qt_metacall
+40 (int (*)(...))QBluetoothSocket::~QBluetoothSocket
+48 (int (*)(...))QBluetoothSocket::~QBluetoothSocket
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QBluetoothSocket::isSequential
+120 (int (*)(...))QIODevice::open
+128 (int (*)(...))QBluetoothSocket::close
+136 (int (*)(...))QIODevice::pos
+144 (int (*)(...))QIODevice::size
+152 (int (*)(...))QIODevice::seek
+160 (int (*)(...))QIODevice::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QBluetoothSocket::bytesAvailable
+184 (int (*)(...))QBluetoothSocket::bytesToWrite
+192 (int (*)(...))QBluetoothSocket::canReadLine
+200 (int (*)(...))QIODevice::waitForReadyRead
+208 (int (*)(...))QIODevice::waitForBytesWritten
+216 (int (*)(...))QBluetoothSocket::readData
+224 (int (*)(...))QIODevice::readLineData
+232 (int (*)(...))QBluetoothSocket::writeData
+
+Class QBluetoothSocket
+ size=24 align=8
+ base size=24 base align=8
+QBluetoothSocket (0x0x7f5eb9103dd0) 0
+ vptr=((& QBluetoothSocket::_ZTV16QBluetoothSocket) + 16)
+ QIODevice (0x0x7f5eb9103e38) 0
+ primary-for QBluetoothSocket (0x0x7f5eb9103dd0)
+ QObject (0x0x7f5eb8aaa240) 0
+ primary-for QIODevice (0x0x7f5eb9103e38)
+
+Class QBluetoothServer::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QBluetoothServer::QPrivateSignal (0x0x7f5eb8aaa6c0) 0 empty
+
+Vtable for QBluetoothServer
+QBluetoothServer::_ZTV16QBluetoothServer: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI16QBluetoothServer)
+16 (int (*)(...))QBluetoothServer::metaObject
+24 (int (*)(...))QBluetoothServer::qt_metacast
+32 (int (*)(...))QBluetoothServer::qt_metacall
+40 (int (*)(...))QBluetoothServer::~QBluetoothServer
+48 (int (*)(...))QBluetoothServer::~QBluetoothServer
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QBluetoothServer
+ size=24 align=8
+ base size=24 base align=8
+QBluetoothServer (0x0x7f5eb9103ea0) 0
+ vptr=((& QBluetoothServer::_ZTV16QBluetoothServer) + 16)
+ QObject (0x0x7f5eb8aaa660) 0
+ primary-for QBluetoothServer (0x0x7f5eb9103ea0)
+
+Class QBluetoothServiceDiscoveryAgent::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QBluetoothServiceDiscoveryAgent::QPrivateSignal (0x0x7f5eb8aaa9c0) 0 empty
+
+Vtable for QBluetoothServiceDiscoveryAgent
+QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI31QBluetoothServiceDiscoveryAgent)
+16 (int (*)(...))QBluetoothServiceDiscoveryAgent::metaObject
+24 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacast
+32 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacall
+40 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent
+48 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QBluetoothServiceDiscoveryAgent
+ size=24 align=8
+ base size=24 base align=8
+QBluetoothServiceDiscoveryAgent (0x0x7f5eb9103f08) 0
+ vptr=((& QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent) + 16)
+ QObject (0x0x7f5eb8aaa960) 0
+ primary-for QBluetoothServiceDiscoveryAgent (0x0x7f5eb9103f08)
+
+Class QBluetoothTransferManager::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QBluetoothTransferManager::QPrivateSignal (0x0x7f5eb8aaad80) 0 empty
+
+Vtable for QBluetoothTransferManager
+QBluetoothTransferManager::_ZTV25QBluetoothTransferManager: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI25QBluetoothTransferManager)
+16 (int (*)(...))QBluetoothTransferManager::metaObject
+24 (int (*)(...))QBluetoothTransferManager::qt_metacast
+32 (int (*)(...))QBluetoothTransferManager::qt_metacall
+40 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager
+48 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QBluetoothTransferManager
+ size=16 align=8
+ base size=16 base align=8
+QBluetoothTransferManager (0x0x7f5eb9103f70) 0
+ vptr=((& QBluetoothTransferManager::_ZTV25QBluetoothTransferManager) + 16)
+ QObject (0x0x7f5eb8aaad20) 0
+ primary-for QBluetoothTransferManager (0x0x7f5eb9103f70)
+
+Class QBluetoothTransferRequest
+ size=8 align=8
+ base size=8 base align=8
+QBluetoothTransferRequest (0x0x7f5eb8aaaea0) 0
+
+Class QBluetoothTransferReply::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QBluetoothTransferReply::QPrivateSignal (0x0x7f5eb8b16060) 0 empty
+
+Vtable for QBluetoothTransferReply
+QBluetoothTransferReply::_ZTV23QBluetoothTransferReply: 18 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI23QBluetoothTransferReply)
+16 (int (*)(...))QBluetoothTransferReply::metaObject
+24 (int (*)(...))QBluetoothTransferReply::qt_metacast
+32 (int (*)(...))QBluetoothTransferReply::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+128 (int (*)(...))__cxa_pure_virtual
+136 (int (*)(...))__cxa_pure_virtual
+
+Class QBluetoothTransferReply
+ size=24 align=8
+ base size=24 base align=8
+QBluetoothTransferReply (0x0x7f5eb8b15000) 0
+ vptr=((& QBluetoothTransferReply::_ZTV23QBluetoothTransferReply) + 16)
+ QObject (0x0x7f5eb8b16000) 0
+ primary-for QBluetoothTransferReply (0x0x7f5eb8b15000)
+
+Class QLowEnergyAdvertisingData
+ size=8 align=8
+ base size=8 base align=8
+QLowEnergyAdvertisingData (0x0x7f5eb8b164e0) 0
+
+Class QLowEnergyDescriptor
+ size=24 align=8
+ base size=24 base align=8
+QLowEnergyDescriptor (0x0x7f5eb8b79660) 0
+
+Class QLowEnergyCharacteristic
+ size=24 align=8
+ base size=24 base align=8
+QLowEnergyCharacteristic (0x0x7f5eb8b79900) 0
+
+Class QLowEnergyService::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QLowEnergyService::QPrivateSignal (0x0x7f5eb8bef2a0) 0 empty
+
+Vtable for QLowEnergyService
+QLowEnergyService::_ZTV17QLowEnergyService: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI17QLowEnergyService)
+16 (int (*)(...))QLowEnergyService::metaObject
+24 (int (*)(...))QLowEnergyService::qt_metacast
+32 (int (*)(...))QLowEnergyService::qt_metacall
+40 (int (*)(...))QLowEnergyService::~QLowEnergyService
+48 (int (*)(...))QLowEnergyService::~QLowEnergyService
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QLowEnergyService
+ size=32 align=8
+ base size=32 base align=8
+QLowEnergyService (0x0x7f5eb8b7a958) 0
+ vptr=((& QLowEnergyService::_ZTV17QLowEnergyService) + 16)
+ QObject (0x0x7f5eb8bef240) 0
+ primary-for QLowEnergyService (0x0x7f5eb8b7a958)
+
+Class QLowEnergyController::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QLowEnergyController::QPrivateSignal (0x0x7f5eb8c43660) 0 empty
+
+Vtable for QLowEnergyController
+QLowEnergyController::_ZTV20QLowEnergyController: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI20QLowEnergyController)
+16 (int (*)(...))QLowEnergyController::metaObject
+24 (int (*)(...))QLowEnergyController::qt_metacast
+32 (int (*)(...))QLowEnergyController::qt_metacall
+40 (int (*)(...))QLowEnergyController::~QLowEnergyController
+48 (int (*)(...))QLowEnergyController::~QLowEnergyController
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QLowEnergyController
+ size=24 align=8
+ base size=24 base align=8
+QLowEnergyController (0x0x7f5eb8b7aa90) 0
+ vptr=((& QLowEnergyController::_ZTV20QLowEnergyController) + 16)
+ QObject (0x0x7f5eb8c43600) 0
+ primary-for QLowEnergyController (0x0x7f5eb8b7aa90)
+
+Class QLowEnergyAdvertisingParameters::AddressInfo
+ size=16 align=8
+ base size=12 base align=8
+QLowEnergyAdvertisingParameters::AddressInfo (0x0x7f5eb888c360) 0
+
+Class QLowEnergyAdvertisingParameters
+ size=8 align=8
+ base size=8 base align=8
+QLowEnergyAdvertisingParameters (0x0x7f5eb888c300) 0
+
+Class QLowEnergyCharacteristicData
+ size=8 align=8
+ base size=8 base align=8
+QLowEnergyCharacteristicData (0x0x7f5eb8915120) 0
+
+Class QLowEnergyConnectionParameters
+ size=8 align=8
+ base size=8 base align=8
+QLowEnergyConnectionParameters (0x0x7f5eb8971240) 0
+
+Class QLowEnergyDescriptorData
+ size=8 align=8
+ base size=8 base align=8
+QLowEnergyDescriptorData (0x0x7f5eb89ca540) 0
+
+Class QLowEnergyServiceData
+ size=8 align=8
+ base size=8 base align=8
+QLowEnergyServiceData (0x0x7f5eb8a26840) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb86cd000) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb86cd360) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb86cd540) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb86cd8a0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb86cda80) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb86cdde0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8709000) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb8709360) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8709540) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87098a0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8709a80) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb8709de0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8742000) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb8742360) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8742540) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87428a0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8770d80) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87a2120) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb87a22a0) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87a2600) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb87a2780) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87a2ae0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb87a2c60) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87d3000) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb87d3180) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87d34e0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb87d3660) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87d39c0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb87d3b40) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87d3ea0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8801060) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb88013c0) 0 empty
+
diff --git a/tests/auto/bic/data/QtNfc.5.13.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtNfc.5.13.0.linux-gcc-amd64.txt
new file mode 100644
index 00000000..e35780a9
--- /dev/null
+++ b/tests/auto/bic/data/QtNfc.5.13.0.linux-gcc-amd64.txt
@@ -0,0 +1,5189 @@
+Class std::__failure_type
+ size=1 align=1
+ base size=0 base align=1
+std::__failure_type (0x0x7ff78ae54f60) 0 empty
+
+Class std::__do_is_destructible_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_destructible_impl (0x0x7ff789b2c720) 0 empty
+
+Class std::__do_is_nt_destructible_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_nt_destructible_impl (0x0x7ff789b2c960) 0 empty
+
+Class std::__do_is_default_constructible_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_default_constructible_impl (0x0x7ff789b2cba0) 0 empty
+
+Class std::__do_is_static_castable_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_static_castable_impl (0x0x7ff789b2cde0) 0 empty
+
+Class std::__do_is_direct_constructible_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_direct_constructible_impl (0x0x7ff789b2cf60) 0 empty
+
+Class std::__do_is_nary_constructible_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_nary_constructible_impl (0x0x7ff789b5b360) 0 empty
+
+Class std::__do_is_implicitly_default_constructible_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_is_implicitly_default_constructible_impl (0x0x7ff789b98480) 0 empty
+
+Class std::__do_common_type_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__do_common_type_impl (0x0x7ff789befb40) 0 empty
+
+Class std::__do_member_type_wrapper
+ size=1 align=1
+ base size=0 base align=1
+std::__do_member_type_wrapper (0x0x7ff789befc00) 0 empty
+
+Class std::__invoke_memfun_ref
+ size=1 align=1
+ base size=0 base align=1
+std::__invoke_memfun_ref (0x0x7ff789c1e000) 0 empty
+
+Class std::__invoke_memfun_deref
+ size=1 align=1
+ base size=0 base align=1
+std::__invoke_memfun_deref (0x0x7ff789c1e060) 0 empty
+
+Class std::__invoke_memobj_ref
+ size=1 align=1
+ base size=0 base align=1
+std::__invoke_memobj_ref (0x0x7ff789c1e0c0) 0 empty
+
+Class std::__invoke_memobj_deref
+ size=1 align=1
+ base size=0 base align=1
+std::__invoke_memobj_deref (0x0x7ff789c1e120) 0 empty
+
+Class std::__invoke_other
+ size=1 align=1
+ base size=0 base align=1
+std::__invoke_other (0x0x7ff789c1e180) 0 empty
+
+Class std::__result_of_memfun_ref_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__result_of_memfun_ref_impl (0x0x7ff789c1e240) 0 empty
+
+Class std::__result_of_memfun_deref_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__result_of_memfun_deref_impl (0x0x7ff789c1e300) 0 empty
+
+Class std::__result_of_memobj_ref_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__result_of_memobj_ref_impl (0x0x7ff789c1e3c0) 0 empty
+
+Class std::__result_of_memobj_deref_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__result_of_memobj_deref_impl (0x0x7ff789c1e480) 0 empty
+
+Class std::__result_of_other_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__result_of_other_impl (0x0x7ff789c1e7e0) 0 empty
+
+Class std::__swappable_details::__do_is_swappable_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__swappable_details::__do_is_swappable_impl (0x0x7ff789c1eb40) 0 empty
+
+Class std::__swappable_details::__do_is_nothrow_swappable_impl
+ size=1 align=1
+ base size=0 base align=1
+std::__swappable_details::__do_is_nothrow_swappable_impl (0x0x7ff789c1eba0) 0 empty
+
+Class std::__nonesuch
+ size=1 align=1
+ base size=0 base align=1
+std::__nonesuch (0x0x7ff789868180) 0 empty
+
+Class std::piecewise_construct_t
+ size=1 align=1
+ base size=0 base align=1
+std::piecewise_construct_t (0x0x7ff7898687e0) 0 empty
+
+Class std::__nonesuch_no_braces
+ size=1 align=1
+ base size=1 base align=1
+std::__nonesuch_no_braces (0x0x7ff789c58410) 0 empty
+ std::__nonesuch (0x0x7ff789868cc0) 0 empty
+
+Class std::__true_type
+ size=1 align=1
+ base size=0 base align=1
+std::__true_type (0x0x7ff7898e9660) 0 empty
+
+Class std::__false_type
+ size=1 align=1
+ base size=0 base align=1
+std::__false_type (0x0x7ff7898e96c0) 0 empty
+
+Class std::input_iterator_tag
+ size=1 align=1
+ base size=0 base align=1
+std::input_iterator_tag (0x0x7ff78993f3c0) 0 empty
+
+Class std::output_iterator_tag
+ size=1 align=1
+ base size=0 base align=1
+std::output_iterator_tag (0x0x7ff78993f420) 0 empty
+
+Class std::forward_iterator_tag
+ size=1 align=1
+ base size=1 base align=1
+std::forward_iterator_tag (0x0x7ff789c588f0) 0 empty
+ std::input_iterator_tag (0x0x7ff78993f480) 0 empty
+
+Class std::bidirectional_iterator_tag
+ size=1 align=1
+ base size=1 base align=1
+std::bidirectional_iterator_tag (0x0x7ff789c58958) 0 empty
+ std::forward_iterator_tag (0x0x7ff789c589c0) 0 empty
+ std::input_iterator_tag (0x0x7ff78993f4e0) 0 empty
+
+Class std::random_access_iterator_tag
+ size=1 align=1
+ base size=1 base align=1
+std::random_access_iterator_tag (0x0x7ff789c58a28) 0 empty
+ std::bidirectional_iterator_tag (0x0x7ff789c58a90) 0 empty
+ std::forward_iterator_tag (0x0x7ff789c58af8) 0 empty
+ std::input_iterator_tag (0x0x7ff78993f540) 0 empty
+
+Class __gnu_cxx::__ops::_Iter_less_iter
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__ops::_Iter_less_iter (0x0x7ff7899f8060) 0 empty
+
+Class __gnu_cxx::__ops::_Iter_less_val
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__ops::_Iter_less_val (0x0x7ff7899f8180) 0 empty
+
+Class __gnu_cxx::__ops::_Val_less_iter
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__ops::_Val_less_iter (0x0x7ff7899f8480) 0 empty
+
+Class __gnu_cxx::__ops::_Iter_equal_to_iter
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__ops::_Iter_equal_to_iter (0x0x7ff7899f8780) 0 empty
+
+Class __gnu_cxx::__ops::_Iter_equal_to_val
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__ops::_Iter_equal_to_val (0x0x7ff7899f88a0) 0 empty
+
+Class __locale_struct
+ size=232 align=8
+ base size=232 base align=8
+__locale_struct (0x0x7ff789683ba0) 0
+
+Class timeval
+ size=16 align=8
+ base size=16 base align=8
+timeval (0x0x7ff789683ea0) 0
+
+Class timespec
+ size=16 align=8
+ base size=16 base align=8
+timespec (0x0x7ff789683f00) 0
+
+Class __pthread_rwlock_arch_t
+ size=56 align=8
+ base size=56 base align=8
+__pthread_rwlock_arch_t (0x0x7ff7896ce000) 0
+
+Class __pthread_internal_list
+ size=16 align=8
+ base size=16 base align=8
+__pthread_internal_list (0x0x7ff7896ce060) 0
+
+Class __pthread_mutex_s
+ size=40 align=8
+ base size=40 base align=8
+__pthread_mutex_s (0x0x7ff7896ce0c0) 0
+
+Class __pthread_cond_s
+ size=48 align=8
+ base size=48 base align=8
+__pthread_cond_s (0x0x7ff7896ce120) 0
+
+Class pthread_attr_t
+ size=56 align=8
+ base size=56 base align=8
+pthread_attr_t (0x0x7ff7896ce3c0) 0
+
+Class random_data
+ size=48 align=8
+ base size=48 base align=8
+random_data (0x0x7ff7896ce660) 0
+
+Class drand48_data
+ size=24 align=8
+ base size=24 base align=8
+drand48_data (0x0x7ff7896ce6c0) 0
+
+Vtable for std::exception
+std::exception::_ZTVSt9exception: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt9exception)
+16 (int (*)(...))std::exception::~exception
+24 (int (*)(...))std::exception::~exception
+32 (int (*)(...))std::exception::what
+
+Class std::exception
+ size=8 align=8
+ base size=8 base align=8
+std::exception (0x0x7ff789782480) 0 nearly-empty
+ vptr=((& std::exception::_ZTVSt9exception) + 16)
+
+Vtable for std::bad_exception
+std::bad_exception::_ZTVSt13bad_exception: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt13bad_exception)
+16 (int (*)(...))std::bad_exception::~bad_exception
+24 (int (*)(...))std::bad_exception::~bad_exception
+32 (int (*)(...))std::bad_exception::what
+
+Class std::bad_exception
+ size=8 align=8
+ base size=8 base align=8
+std::bad_exception (0x0x7ff789c58e38) 0 nearly-empty
+ vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16)
+ std::exception (0x0x7ff789782660) 0 nearly-empty
+ primary-for std::bad_exception (0x0x7ff789c58e38)
+
+Vtable for std::type_info
+std::type_info::_ZTVSt9type_info: 8 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt9type_info)
+16 (int (*)(...))std::type_info::~type_info
+24 (int (*)(...))std::type_info::~type_info
+32 (int (*)(...))std::type_info::__is_pointer_p
+40 (int (*)(...))std::type_info::__is_function_p
+48 (int (*)(...))std::type_info::__do_catch
+56 (int (*)(...))std::type_info::__do_upcast
+
+Class std::type_info
+ size=16 align=8
+ base size=16 base align=8
+std::type_info (0x0x7ff789782840) 0
+ vptr=((& std::type_info::_ZTVSt9type_info) + 16)
+
+Vtable for std::bad_cast
+std::bad_cast::_ZTVSt8bad_cast: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt8bad_cast)
+16 (int (*)(...))std::bad_cast::~bad_cast
+24 (int (*)(...))std::bad_cast::~bad_cast
+32 (int (*)(...))std::bad_cast::what
+
+Class std::bad_cast
+ size=8 align=8
+ base size=8 base align=8
+std::bad_cast (0x0x7ff789c58ea0) 0 nearly-empty
+ vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16)
+ std::exception (0x0x7ff789782c00) 0 nearly-empty
+ primary-for std::bad_cast (0x0x7ff789c58ea0)
+
+Vtable for std::bad_typeid
+std::bad_typeid::_ZTVSt10bad_typeid: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt10bad_typeid)
+16 (int (*)(...))std::bad_typeid::~bad_typeid
+24 (int (*)(...))std::bad_typeid::~bad_typeid
+32 (int (*)(...))std::bad_typeid::what
+
+Class std::bad_typeid
+ size=8 align=8
+ base size=8 base align=8
+std::bad_typeid (0x0x7ff789c58f08) 0 nearly-empty
+ vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16)
+ std::exception (0x0x7ff789782de0) 0 nearly-empty
+ primary-for std::bad_typeid (0x0x7ff789c58f08)
+
+Class std::__exception_ptr::exception_ptr
+ size=8 align=8
+ base size=8 base align=8
+std::__exception_ptr::exception_ptr (0x0x7ff7897b4000) 0
+
+Vtable for std::nested_exception
+std::nested_exception::_ZTVSt16nested_exception: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt16nested_exception)
+16 (int (*)(...))std::nested_exception::~nested_exception
+24 (int (*)(...))std::nested_exception::~nested_exception
+
+Class std::nested_exception
+ size=16 align=8
+ base size=16 base align=8
+std::nested_exception (0x0x7ff7897b45a0) 0
+ vptr=((& std::nested_exception::_ZTVSt16nested_exception) + 16)
+
+Vtable for std::bad_alloc
+std::bad_alloc::_ZTVSt9bad_alloc: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt9bad_alloc)
+16 (int (*)(...))std::bad_alloc::~bad_alloc
+24 (int (*)(...))std::bad_alloc::~bad_alloc
+32 (int (*)(...))std::bad_alloc::what
+
+Class std::bad_alloc
+ size=8 align=8
+ base size=8 base align=8
+std::bad_alloc (0x0x7ff789c58f70) 0 nearly-empty
+ vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16)
+ std::exception (0x0x7ff7897b4c60) 0 nearly-empty
+ primary-for std::bad_alloc (0x0x7ff789c58f70)
+
+Vtable for std::bad_array_new_length
+std::bad_array_new_length::_ZTVSt20bad_array_new_length: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt20bad_array_new_length)
+16 (int (*)(...))std::bad_array_new_length::~bad_array_new_length
+24 (int (*)(...))std::bad_array_new_length::~bad_array_new_length
+32 (int (*)(...))std::bad_array_new_length::what
+
+Class std::bad_array_new_length
+ size=8 align=8
+ base size=8 base align=8
+std::bad_array_new_length (0x0x7ff7897e4000) 0 nearly-empty
+ vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16)
+ std::bad_alloc (0x0x7ff7897e4068) 0 nearly-empty
+ primary-for std::bad_array_new_length (0x0x7ff7897e4000)
+ std::exception (0x0x7ff7897b4e40) 0 nearly-empty
+ primary-for std::bad_alloc (0x0x7ff7897e4068)
+
+Class std::nothrow_t
+ size=1 align=1
+ base size=0 base align=1
+std::nothrow_t (0x0x7ff7897eb060) 0 empty
+
+Class std::__allocator_traits_base
+ size=1 align=1
+ base size=0 base align=1
+std::__allocator_traits_base (0x0x7ff7897eb240) 0 empty
+
+Class std::__numeric_limits_base
+ size=1 align=1
+ base size=0 base align=1
+std::__numeric_limits_base (0x0x7ff789461720) 0 empty
+
+Class qIsNull(double)::U
+ size=8 align=8
+ base size=8 base align=8
+qIsNull(double)::U (0x0x7ff7896431e0) 0
+
+Class qIsNull(float)::U
+ size=4 align=4
+ base size=4 base align=4
+qIsNull(float)::U (0x0x7ff7896432a0) 0
+
+Class QSysInfo
+ size=1 align=1
+ base size=0 base align=1
+QSysInfo (0x0x7ff7890dbc00) 0 empty
+
+Class QMessageLogContext
+ size=32 align=8
+ base size=32 base align=8
+QMessageLogContext (0x0x7ff7890dbd20) 0
+
+Class QMessageLogger
+ size=32 align=8
+ base size=32 base align=8
+QMessageLogger (0x0x7ff7891100c0) 0
+
+Class QFlag
+ size=4 align=4
+ base size=4 base align=4
+QFlag (0x0x7ff789110600) 0
+
+Class QIncompatibleFlag
+ size=4 align=4
+ base size=4 base align=4
+QIncompatibleFlag (0x0x7ff789153d80) 0
+
+Class std::__atomic_flag_base
+ size=1 align=1
+ base size=1 base align=1
+std::__atomic_flag_base (0x0x7ff78920a1e0) 0
+
+Class std::atomic_flag
+ size=1 align=1
+ base size=1 base align=1
+std::atomic_flag (0x0x7ff789197ea0) 0
+ std::__atomic_flag_base (0x0x7ff78920a240) 0
+
+Class QAtomicInt
+ size=4 align=4
+ base size=4 base align=4
+QAtomicInt (0x0x7ff788f2e618) 0
+ QAtomicInteger<int> (0x0x7ff788f2e680) 0
+ QBasicAtomicInteger<int> (0x0x7ff788d391e0) 0
+
+Class QInternal
+ size=1 align=1
+ base size=0 base align=1
+QInternal (0x0x7ff7889584e0) 0 empty
+
+Class QtPrivate::QSlotObjectBase
+ size=16 align=8
+ base size=16 base align=8
+QtPrivate::QSlotObjectBase (0x0x7ff78898fa80) 0
+
+Class QGenericArgument
+ size=16 align=8
+ base size=16 base align=8
+QGenericArgument (0x0x7ff7889d61e0) 0
+
+Class QGenericReturnArgument
+ size=16 align=8
+ base size=16 base align=8
+QGenericReturnArgument (0x0x7ff7889d4208) 0
+ QGenericArgument (0x0x7ff7889d6480) 0
+
+Class QMetaObject
+ size=48 align=8
+ base size=48 base align=8
+QMetaObject (0x0x7ff7889d68a0) 0
+
+Class QMetaObject::Connection
+ size=8 align=8
+ base size=8 base align=8
+QMetaObject::Connection (0x0x7ff7889d6cc0) 0
+
+Class QLatin1Char
+ size=1 align=1
+ base size=1 base align=1
+QLatin1Char (0x0x7ff78868a7e0) 0
+
+Class QChar
+ size=2 align=2
+ base size=2 base align=2
+QChar (0x0x7ff78868aa80) 0
+
+Class QtPrivate::RefCount
+ size=4 align=4
+ base size=4 base align=4
+QtPrivate::RefCount (0x0x7ff78875a8a0) 0
+
+Class QArrayData
+ size=24 align=8
+ base size=24 base align=8
+QArrayData (0x0x7ff78875ac00) 0
+
+Class QtPrivate::QContainerImplHelper
+ size=1 align=1
+ base size=0 base align=1
+QtPrivate::QContainerImplHelper (0x0x7ff7887b3f00) 0 empty
+
+Class lconv
+ size=96 align=8
+ base size=96 base align=8
+lconv (0x0x7ff788495780) 0
+
+Vtable for __cxxabiv1::__forced_unwind
+__cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN10__cxxabiv115__forced_unwindE)
+16 0
+24 0
+32 (int (*)(...))__cxa_pure_virtual
+
+Class __cxxabiv1::__forced_unwind
+ size=8 align=8
+ base size=8 base align=8
+__cxxabiv1::__forced_unwind (0x0x7ff788495840) 0 nearly-empty
+ vptr=((& __cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE) + 16)
+
+Class sched_param
+ size=4 align=4
+ base size=4 base align=4
+sched_param (0x0x7ff78855c960) 0
+
+Class timex
+ size=208 align=8
+ base size=208 base align=8
+timex (0x0x7ff78855ca20) 0
+
+Class tm
+ size=56 align=8
+ base size=56 base align=8
+tm (0x0x7ff78855ca80) 0
+
+Class itimerspec
+ size=32 align=8
+ base size=32 base align=8
+itimerspec (0x0x7ff78855cae0) 0
+
+Class _pthread_cleanup_buffer
+ size=32 align=8
+ base size=32 base align=8
+_pthread_cleanup_buffer (0x0x7ff78855cb40) 0
+
+Class __pthread_cleanup_frame
+ size=24 align=8
+ base size=24 base align=8
+__pthread_cleanup_frame (0x0x7ff78855cc60) 0
+
+Class __pthread_cleanup_class
+ size=24 align=8
+ base size=24 base align=8
+__pthread_cleanup_class (0x0x7ff78855ccc0) 0
+
+Class _IO_marker
+ size=24 align=8
+ base size=24 base align=8
+_IO_marker (0x0x7ff78829dc60) 0
+
+Class _IO_FILE
+ size=216 align=8
+ base size=216 base align=8
+_IO_FILE (0x0x7ff78829dcc0) 0
+
+Class std::_Hash_impl
+ size=1 align=1
+ base size=0 base align=1
+std::_Hash_impl (0x0x7ff788459d20) 0 empty
+
+Class std::_Fnv_hash_impl
+ size=1 align=1
+ base size=0 base align=1
+std::_Fnv_hash_impl (0x0x7ff788459ea0) 0 empty
+
+Class std::locale
+ size=8 align=8
+ base size=8 base align=8
+std::locale (0x0x7ff788204060) 0
+
+Vtable for std::locale::facet
+std::locale::facet::_ZTVNSt6locale5facetE: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt6locale5facetE)
+16 (int (*)(...))std::locale::facet::~facet
+24 (int (*)(...))std::locale::facet::~facet
+
+Class std::locale::facet
+ size=16 align=8
+ base size=12 base align=8
+std::locale::facet (0x0x7ff788204420) 0
+ vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16)
+
+Class std::locale::id
+ size=8 align=8
+ base size=8 base align=8
+std::locale::id (0x0x7ff7882046c0) 0
+
+Class std::locale::_Impl
+ size=40 align=8
+ base size=40 base align=8
+std::locale::_Impl (0x0x7ff7882048a0) 0
+
+Class std::__cow_string
+ size=8 align=8
+ base size=8 base align=8
+std::__cow_string (0x0x7ff787e668a0) 0
+
+Vtable for std::logic_error
+std::logic_error::_ZTVSt11logic_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt11logic_error)
+16 (int (*)(...))std::logic_error::~logic_error
+24 (int (*)(...))std::logic_error::~logic_error
+32 (int (*)(...))std::logic_error::what
+
+Class std::logic_error
+ size=16 align=8
+ base size=16 base align=8
+std::logic_error (0x0x7ff787e791a0) 0
+ vptr=((& std::logic_error::_ZTVSt11logic_error) + 16)
+ std::exception (0x0x7ff787e66960) 0 nearly-empty
+ primary-for std::logic_error (0x0x7ff787e791a0)
+
+Vtable for std::domain_error
+std::domain_error::_ZTVSt12domain_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt12domain_error)
+16 (int (*)(...))std::domain_error::~domain_error
+24 (int (*)(...))std::domain_error::~domain_error
+32 (int (*)(...))std::logic_error::what
+
+Class std::domain_error
+ size=16 align=8
+ base size=16 base align=8
+std::domain_error (0x0x7ff787e79208) 0
+ vptr=((& std::domain_error::_ZTVSt12domain_error) + 16)
+ std::logic_error (0x0x7ff787e79270) 0
+ primary-for std::domain_error (0x0x7ff787e79208)
+ std::exception (0x0x7ff787e669c0) 0 nearly-empty
+ primary-for std::logic_error (0x0x7ff787e79270)
+
+Vtable for std::invalid_argument
+std::invalid_argument::_ZTVSt16invalid_argument: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt16invalid_argument)
+16 (int (*)(...))std::invalid_argument::~invalid_argument
+24 (int (*)(...))std::invalid_argument::~invalid_argument
+32 (int (*)(...))std::logic_error::what
+
+Class std::invalid_argument
+ size=16 align=8
+ base size=16 base align=8
+std::invalid_argument (0x0x7ff787e792d8) 0
+ vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16)
+ std::logic_error (0x0x7ff787e79340) 0
+ primary-for std::invalid_argument (0x0x7ff787e792d8)
+ std::exception (0x0x7ff787e66a20) 0 nearly-empty
+ primary-for std::logic_error (0x0x7ff787e79340)
+
+Vtable for std::length_error
+std::length_error::_ZTVSt12length_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt12length_error)
+16 (int (*)(...))std::length_error::~length_error
+24 (int (*)(...))std::length_error::~length_error
+32 (int (*)(...))std::logic_error::what
+
+Class std::length_error
+ size=16 align=8
+ base size=16 base align=8
+std::length_error (0x0x7ff787e793a8) 0
+ vptr=((& std::length_error::_ZTVSt12length_error) + 16)
+ std::logic_error (0x0x7ff787e79410) 0
+ primary-for std::length_error (0x0x7ff787e793a8)
+ std::exception (0x0x7ff787e66a80) 0 nearly-empty
+ primary-for std::logic_error (0x0x7ff787e79410)
+
+Vtable for std::out_of_range
+std::out_of_range::_ZTVSt12out_of_range: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt12out_of_range)
+16 (int (*)(...))std::out_of_range::~out_of_range
+24 (int (*)(...))std::out_of_range::~out_of_range
+32 (int (*)(...))std::logic_error::what
+
+Class std::out_of_range
+ size=16 align=8
+ base size=16 base align=8
+std::out_of_range (0x0x7ff787e79478) 0
+ vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16)
+ std::logic_error (0x0x7ff787e794e0) 0
+ primary-for std::out_of_range (0x0x7ff787e79478)
+ std::exception (0x0x7ff787e66ae0) 0 nearly-empty
+ primary-for std::logic_error (0x0x7ff787e794e0)
+
+Vtable for std::runtime_error
+std::runtime_error::_ZTVSt13runtime_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt13runtime_error)
+16 (int (*)(...))std::runtime_error::~runtime_error
+24 (int (*)(...))std::runtime_error::~runtime_error
+32 (int (*)(...))std::runtime_error::what
+
+Class std::runtime_error
+ size=16 align=8
+ base size=16 base align=8
+std::runtime_error (0x0x7ff787e79548) 0
+ vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16)
+ std::exception (0x0x7ff787e66b40) 0 nearly-empty
+ primary-for std::runtime_error (0x0x7ff787e79548)
+
+Vtable for std::range_error
+std::range_error::_ZTVSt11range_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt11range_error)
+16 (int (*)(...))std::range_error::~range_error
+24 (int (*)(...))std::range_error::~range_error
+32 (int (*)(...))std::runtime_error::what
+
+Class std::range_error
+ size=16 align=8
+ base size=16 base align=8
+std::range_error (0x0x7ff787e795b0) 0
+ vptr=((& std::range_error::_ZTVSt11range_error) + 16)
+ std::runtime_error (0x0x7ff787e79618) 0
+ primary-for std::range_error (0x0x7ff787e795b0)
+ std::exception (0x0x7ff787e66ba0) 0 nearly-empty
+ primary-for std::runtime_error (0x0x7ff787e79618)
+
+Vtable for std::overflow_error
+std::overflow_error::_ZTVSt14overflow_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt14overflow_error)
+16 (int (*)(...))std::overflow_error::~overflow_error
+24 (int (*)(...))std::overflow_error::~overflow_error
+32 (int (*)(...))std::runtime_error::what
+
+Class std::overflow_error
+ size=16 align=8
+ base size=16 base align=8
+std::overflow_error (0x0x7ff787e79680) 0
+ vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16)
+ std::runtime_error (0x0x7ff787e796e8) 0
+ primary-for std::overflow_error (0x0x7ff787e79680)
+ std::exception (0x0x7ff787e66c00) 0 nearly-empty
+ primary-for std::runtime_error (0x0x7ff787e796e8)
+
+Vtable for std::underflow_error
+std::underflow_error::_ZTVSt15underflow_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt15underflow_error)
+16 (int (*)(...))std::underflow_error::~underflow_error
+24 (int (*)(...))std::underflow_error::~underflow_error
+32 (int (*)(...))std::runtime_error::what
+
+Class std::underflow_error
+ size=16 align=8
+ base size=16 base align=8
+std::underflow_error (0x0x7ff787e79750) 0
+ vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16)
+ std::runtime_error (0x0x7ff787e797b8) 0
+ primary-for std::underflow_error (0x0x7ff787e79750)
+ std::exception (0x0x7ff787e66c60) 0 nearly-empty
+ primary-for std::runtime_error (0x0x7ff787e797b8)
+
+Vtable for std::_V2::error_category
+std::_V2::error_category::_ZTVNSt3_V214error_categoryE: 10 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt3_V214error_categoryE)
+16 0
+24 0
+32 (int (*)(...))__cxa_pure_virtual
+40 (int (*)(...))std::_V2::error_category::_M_message
+48 (int (*)(...))__cxa_pure_virtual
+56 (int (*)(...))std::_V2::error_category::default_error_condition
+64 (int (*)(...))std::_V2::error_category::equivalent
+72 (int (*)(...))std::_V2::error_category::equivalent
+
+Class std::_V2::error_category
+ size=8 align=8
+ base size=8 base align=8
+std::_V2::error_category (0x0x7ff787e66de0) 0 nearly-empty
+ vptr=((& std::_V2::error_category::_ZTVNSt3_V214error_categoryE) + 16)
+
+Class std::error_code
+ size=16 align=8
+ base size=16 base align=8
+std::error_code (0x0x7ff787ebc180) 0
+
+Class std::error_condition
+ size=16 align=8
+ base size=16 base align=8
+std::error_condition (0x0x7ff787ebc9c0) 0
+
+Vtable for std::system_error
+std::system_error::_ZTVSt12system_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt12system_error)
+16 (int (*)(...))std::system_error::~system_error
+24 (int (*)(...))std::system_error::~system_error
+32 (int (*)(...))std::runtime_error::what
+
+Class std::system_error
+ size=32 align=8
+ base size=32 base align=8
+std::system_error (0x0x7ff787e79bc8) 0
+ vptr=((& std::system_error::_ZTVSt12system_error) + 16)
+ std::runtime_error (0x0x7ff787e79c30) 0
+ primary-for std::system_error (0x0x7ff787e79bc8)
+ std::exception (0x0x7ff787eea5a0) 0 nearly-empty
+ primary-for std::runtime_error (0x0x7ff787e79c30)
+
+Vtable for std::ios_base::failure
+std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt8ios_base7failureB5cxx11E)
+16 (int (*)(...))std::ios_base::failure::~failure
+24 (int (*)(...))std::ios_base::failure::~failure
+32 (int (*)(...))std::ios_base::failure::what
+
+Class std::ios_base::failure
+ size=32 align=8
+ base size=32 base align=8
+std::ios_base::failure (0x0x7ff787e79ea0) 0
+ vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16)
+ std::system_error (0x0x7ff787e79f08) 0
+ primary-for std::ios_base::failure (0x0x7ff787e79ea0)
+ std::runtime_error (0x0x7ff787e79f70) 0
+ primary-for std::system_error (0x0x7ff787e79f08)
+ std::exception (0x0x7ff787f20b40) 0 nearly-empty
+ primary-for std::runtime_error (0x0x7ff787e79f70)
+
+Class std::ios_base::_Callback_list
+ size=24 align=8
+ base size=24 base align=8
+std::ios_base::_Callback_list (0x0x7ff787f20ba0) 0
+
+Class std::ios_base::_Words
+ size=16 align=8
+ base size=16 base align=8
+std::ios_base::_Words (0x0x7ff787f20c00) 0
+
+Class std::ios_base::Init
+ size=1 align=1
+ base size=0 base align=1
+std::ios_base::Init (0x0x7ff787f20c60) 0 empty
+
+Vtable for std::ios_base
+std::ios_base::_ZTVSt8ios_base: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt8ios_base)
+16 (int (*)(...))std::ios_base::~ios_base
+24 (int (*)(...))std::ios_base::~ios_base
+
+Class std::ios_base
+ size=216 align=8
+ base size=216 base align=8
+std::ios_base (0x0x7ff787f20ae0) 0
+ vptr=((& std::ios_base::_ZTVSt8ios_base) + 16)
+
+Class std::ctype_base
+ size=1 align=1
+ base size=0 base align=1
+std::ctype_base (0x0x7ff7880175a0) 0 empty
+
+Class std::__num_base
+ size=1 align=1
+ base size=0 base align=1
+std::__num_base (0x0x7ff787cd2780) 0 empty
+
+VTT for std::basic_ostream<char>
+std::basic_ostream<char>::_ZTTSo: 2 entries
+0 ((& std::basic_ostream<char>::_ZTVSo) + 24)
+8 ((& std::basic_ostream<char>::_ZTVSo) + 64)
+
+VTT for std::basic_ostream<wchar_t>
+std::basic_ostream<wchar_t>::_ZTTSt13basic_ostreamIwSt11char_traitsIwEE: 2 entries
+0 ((& std::basic_ostream<wchar_t>::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 24)
+8 ((& std::basic_ostream<wchar_t>::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 64)
+
+VTT for std::basic_istream<char>
+std::basic_istream<char>::_ZTTSi: 2 entries
+0 ((& std::basic_istream<char>::_ZTVSi) + 24)
+8 ((& std::basic_istream<char>::_ZTVSi) + 64)
+
+VTT for std::basic_istream<wchar_t>
+std::basic_istream<wchar_t>::_ZTTSt13basic_istreamIwSt11char_traitsIwEE: 2 entries
+0 ((& std::basic_istream<wchar_t>::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 24)
+8 ((& std::basic_istream<wchar_t>::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 64)
+
+Construction vtable for std::basic_istream<char> (0x0x7ff78787e680 instance) in std::basic_iostream<char>
+std::basic_iostream<char>::_ZTCSd0_Si: 10 entries
+0 24
+8 (int (*)(...))0
+16 (int (*)(...))(& _ZTISi)
+24 0
+32 0
+40 18446744073709551592
+48 (int (*)(...))-24
+56 (int (*)(...))(& _ZTISi)
+64 0
+72 0
+
+Construction vtable for std::basic_ostream<char> (0x0x7ff78787e750 instance) in std::basic_iostream<char>
+std::basic_iostream<char>::_ZTCSd16_So: 10 entries
+0 8
+8 (int (*)(...))0
+16 (int (*)(...))(& _ZTISo)
+24 0
+32 0
+40 18446744073709551608
+48 (int (*)(...))-8
+56 (int (*)(...))(& _ZTISo)
+64 0
+72 0
+
+VTT for std::basic_iostream<char>
+std::basic_iostream<char>::_ZTTSd: 7 entries
+0 ((& std::basic_iostream<char>::_ZTVSd) + 24)
+8 ((& std::basic_iostream<char>::_ZTCSd0_Si) + 24)
+16 ((& std::basic_iostream<char>::_ZTCSd0_Si) + 64)
+24 ((& std::basic_iostream<char>::_ZTCSd16_So) + 24)
+32 ((& std::basic_iostream<char>::_ZTCSd16_So) + 64)
+40 ((& std::basic_iostream<char>::_ZTVSd) + 104)
+48 ((& std::basic_iostream<char>::_ZTVSd) + 64)
+
+Construction vtable for std::basic_istream<wchar_t> (0x0x7ff7878bd410 instance) in std::basic_iostream<wchar_t>
+std::basic_iostream<wchar_t>::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E: 10 entries
+0 24
+8 (int (*)(...))0
+16 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE)
+24 0
+32 0
+40 18446744073709551592
+48 (int (*)(...))-24
+56 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE)
+64 0
+72 0
+
+Construction vtable for std::basic_ostream<wchar_t> (0x0x7ff7878bd4e0 instance) in std::basic_iostream<wchar_t>
+std::basic_iostream<wchar_t>::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E: 10 entries
+0 8
+8 (int (*)(...))0
+16 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE)
+24 0
+32 0
+40 18446744073709551608
+48 (int (*)(...))-8
+56 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE)
+64 0
+72 0
+
+VTT for std::basic_iostream<wchar_t>
+std::basic_iostream<wchar_t>::_ZTTSt14basic_iostreamIwSt11char_traitsIwEE: 7 entries
+0 ((& std::basic_iostream<wchar_t>::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 24)
+8 ((& std::basic_iostream<wchar_t>::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 24)
+16 ((& std::basic_iostream<wchar_t>::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 64)
+24 ((& std::basic_iostream<wchar_t>::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 24)
+32 ((& std::basic_iostream<wchar_t>::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 64)
+40 ((& std::basic_iostream<wchar_t>::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 104)
+48 ((& std::basic_iostream<wchar_t>::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 64)
+
+Class QByteArrayDataPtr
+ size=8 align=8
+ base size=8 base align=8
+QByteArrayDataPtr (0x0x7ff7878f7120) 0
+
+Class QByteArray
+ size=8 align=8
+ base size=8 base align=8
+QByteArray (0x0x7ff7878f7180) 0
+
+Class QByteRef
+ size=16 align=8
+ base size=12 base align=8
+QByteRef (0x0x7ff787a21540) 0
+
+Class QStringDataPtr
+ size=8 align=8
+ base size=8 base align=8
+QStringDataPtr (0x0x7ff7876c13c0) 0
+
+Class QStringView
+ size=16 align=8
+ base size=16 base align=8
+QStringView (0x0x7ff7876c1840) 0
+
+Class QLatin1String
+ size=16 align=8
+ base size=16 base align=8
+QLatin1String (0x0x7ff787796600) 0
+
+Class QString::Null
+ size=1 align=1
+ base size=0 base align=1
+QString::Null (0x0x7ff787834060) 0 empty
+
+Class QString
+ size=8 align=8
+ base size=8 base align=8
+QString (0x0x7ff787834000) 0
+
+Class QCharRef
+ size=16 align=8
+ base size=12 base align=8
+QCharRef (0x0x7ff7876251e0) 0
+
+Class QStringRef
+ size=16 align=8
+ base size=16 base align=8
+QStringRef (0x0x7ff787396a20) 0
+
+Class QtPrivate::QHashCombine
+ size=1 align=1
+ base size=0 base align=1
+QtPrivate::QHashCombine (0x0x7ff7871a2d20) 0 empty
+
+Class QtPrivate::QHashCombineCommutative
+ size=1 align=1
+ base size=0 base align=1
+QtPrivate::QHashCombineCommutative (0x0x7ff7871a2de0) 0 empty
+
+Class std::_Bit_reference
+ size=16 align=8
+ base size=16 base align=8
+std::_Bit_reference (0x0x7ff786e8d300) 0
+
+Class std::_Bit_iterator_base
+ size=16 align=8
+ base size=12 base align=8
+std::_Bit_iterator_base (0x0x7ff78743b820) 0
+ std::iterator<std::random_access_iterator_tag, bool> (0x0x7ff786e8da20) 0 empty
+
+Class std::_Bit_iterator
+ size=16 align=8
+ base size=12 base align=8
+std::_Bit_iterator (0x0x7ff78743b958) 0
+ std::_Bit_iterator_base (0x0x7ff78743b9c0) 0
+ std::iterator<std::random_access_iterator_tag, bool> (0x0x7ff786eba0c0) 0 empty
+
+Class std::_Bit_const_iterator
+ size=16 align=8
+ base size=12 base align=8
+std::_Bit_const_iterator (0x0x7ff78743ba28) 0
+ std::_Bit_iterator_base (0x0x7ff78743ba90) 0
+ std::iterator<std::random_access_iterator_tag, bool> (0x0x7ff786eba8a0) 0 empty
+
+Class std::__detail::_List_node_base
+ size=16 align=8
+ base size=16 base align=8
+std::__detail::_List_node_base (0x0x7ff786c77f00) 0
+
+Class QListData::NotArrayCompatibleLayout
+ size=1 align=1
+ base size=0 base align=1
+QListData::NotArrayCompatibleLayout (0x0x7ff786d7ccc0) 0 empty
+
+Class QListData::NotIndirectLayout
+ size=1 align=1
+ base size=0 base align=1
+QListData::NotIndirectLayout (0x0x7ff786d7cd20) 0 empty
+
+Class QListData::ArrayCompatibleLayout
+ size=1 align=1
+ base size=1 base align=1
+QListData::ArrayCompatibleLayout (0x0x7ff786fec4e0) 0 empty
+ QListData::NotIndirectLayout (0x0x7ff786d7cd80) 0 empty
+
+Class QListData::InlineWithPaddingLayout
+ size=1 align=1
+ base size=1 base align=1
+QListData::InlineWithPaddingLayout (0x0x7ff786d730e0) 0 empty
+ QListData::NotArrayCompatibleLayout (0x0x7ff786d7cde0) 0 empty
+ QListData::NotIndirectLayout (0x0x7ff786d7ce40) 0 empty
+
+Class QListData::IndirectLayout
+ size=1 align=1
+ base size=1 base align=1
+QListData::IndirectLayout (0x0x7ff786fec548) 0 empty
+ QListData::NotArrayCompatibleLayout (0x0x7ff786d7cea0) 0 empty
+
+Class QListData::Data
+ size=24 align=8
+ base size=24 base align=8
+QListData::Data (0x0x7ff786d7cf00) 0
+
+Class QListData
+ size=8 align=8
+ base size=8 base align=8
+QListData (0x0x7ff786d7cc60) 0
+
+Class QRegExp
+ size=8 align=8
+ base size=8 base align=8
+QRegExp (0x0x7ff786a90120) 0
+
+Class QStringMatcher::Data
+ size=272 align=8
+ base size=272 base align=8
+QStringMatcher::Data (0x0x7ff786b63780) 0
+
+Class QStringMatcher
+ size=1048 align=8
+ base size=1048 base align=8
+QStringMatcher (0x0x7ff786b63720) 0
+
+Class QStringList
+ size=8 align=8
+ base size=8 base align=8
+QStringList (0x0x7ff786b69270) 0
+ QList<QString> (0x0x7ff786b692d8) 0
+ QListSpecialMethods<QString> (0x0x7ff786b639c0) 0 empty
+
+Class QScopedPointerPodDeleter
+ size=1 align=1
+ base size=0 base align=1
+QScopedPointerPodDeleter (0x0x7ff786c29540) 0 empty
+
+Class std::_Rb_tree_node_base
+ size=32 align=8
+ base size=32 base align=8
+std::_Rb_tree_node_base (0x0x7ff7868b3660) 0
+
+Class std::_Rb_tree_header
+ size=40 align=8
+ base size=40 base align=8
+std::_Rb_tree_header (0x0x7ff7868b39c0) 0
+
+Class std::__erased_type
+ size=1 align=1
+ base size=0 base align=1
+std::__erased_type (0x0x7ff78668bf60) 0 empty
+
+Class std::allocator_arg_t
+ size=1 align=1
+ base size=0 base align=1
+std::allocator_arg_t (0x0x7ff7866b1000) 0 empty
+
+Class std::__uses_alloc_base
+ size=1 align=1
+ base size=0 base align=1
+std::__uses_alloc_base (0x0x7ff7866b1180) 0 empty
+
+Class std::__uses_alloc0::_Sink
+ size=1 align=1
+ base size=0 base align=1
+std::__uses_alloc0::_Sink (0x0x7ff7866b1240) 0 empty
+
+Class std::__uses_alloc0
+ size=1 align=1
+ base size=1 base align=1
+std::__uses_alloc0 (0x0x7ff786a30618) 0
+ std::__uses_alloc_base (0x0x7ff7866b11e0) 0 empty
+
+Class std::_Swallow_assign
+ size=1 align=1
+ base size=0 base align=1
+std::_Swallow_assign (0x0x7ff7868195a0) 0 empty
+
+Class QtPrivate::AbstractDebugStreamFunction
+ size=16 align=8
+ base size=16 base align=8
+QtPrivate::AbstractDebugStreamFunction (0x0x7ff78643aa20) 0
+
+Class QtPrivate::AbstractComparatorFunction
+ size=24 align=8
+ base size=24 base align=8
+QtPrivate::AbstractComparatorFunction (0x0x7ff78643ad80) 0
+
+Class QtPrivate::AbstractConverterFunction
+ size=8 align=8
+ base size=8 base align=8
+QtPrivate::AbstractConverterFunction (0x0x7ff78645f300) 0
+
+Class QMetaType
+ size=80 align=8
+ base size=80 base align=8
+QMetaType (0x0x7ff78645f840) 0
+
+Class QtMetaTypePrivate::VariantData
+ size=24 align=8
+ base size=20 base align=8
+QtMetaTypePrivate::VariantData (0x0x7ff7864c3a20) 0
+
+Class QtMetaTypePrivate::VectorBoolElements
+ size=1 align=1
+ base size=0 base align=1
+QtMetaTypePrivate::VectorBoolElements (0x0x7ff7864e1120) 0 empty
+
+Class QtMetaTypePrivate::QSequentialIterableImpl
+ size=104 align=8
+ base size=104 base align=8
+QtMetaTypePrivate::QSequentialIterableImpl (0x0x7ff7864e1f60) 0
+
+Class QtMetaTypePrivate::QAssociativeIterableImpl
+ size=112 align=8
+ base size=112 base align=8
+QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7ff7865d3660) 0
+
+Class QtMetaTypePrivate::QPairVariantInterfaceImpl
+ size=40 align=8
+ base size=40 base align=8
+QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7ff786229ba0) 0
+
+Class std::chrono::_V2::system_clock
+ size=1 align=1
+ base size=0 base align=1
+std::chrono::_V2::system_clock (0x0x7ff7860679c0) 0 empty
+
+Class std::chrono::_V2::steady_clock
+ size=1 align=1
+ base size=0 base align=1
+std::chrono::_V2::steady_clock (0x0x7ff785d9a480) 0 empty
+
+Vtable for QObjectData
+QObjectData::_ZTV11QObjectData: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QObjectData)
+16 (int (*)(...))__cxa_pure_virtual
+24 (int (*)(...))__cxa_pure_virtual
+
+Class QObjectData
+ size=48 align=8
+ base size=48 base align=8
+QObjectData (0x0x7ff785d9a4e0) 0
+ vptr=((& QObjectData::_ZTV11QObjectData) + 16)
+
+Class QObject::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QObject::QPrivateSignal (0x0x7ff785d9a6c0) 0 empty
+
+Vtable for QObject
+QObject::_ZTV7QObject: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI7QObject)
+16 (int (*)(...))QObject::metaObject
+24 (int (*)(...))QObject::qt_metacast
+32 (int (*)(...))QObject::qt_metacall
+40 (int (*)(...))QObject::~QObject
+48 (int (*)(...))QObject::~QObject
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QObject
+ size=16 align=8
+ base size=16 base align=8
+QObject (0x0x7ff785d9a660) 0
+ vptr=((& QObject::_ZTV7QObject) + 16)
+
+Vtable for QObjectUserData
+QObjectUserData::_ZTV15QObjectUserData: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI15QObjectUserData)
+16 (int (*)(...))QObjectUserData::~QObjectUserData
+24 (int (*)(...))QObjectUserData::~QObjectUserData
+
+Class QObjectUserData
+ size=8 align=8
+ base size=8 base align=8
+QObjectUserData (0x0x7ff785e6c4e0) 0 nearly-empty
+ vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16)
+
+Class QSignalBlocker
+ size=16 align=8
+ base size=10 base align=8
+QSignalBlocker (0x0x7ff785e6c660) 0
+
+Class QAbstractAnimation::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractAnimation::QPrivateSignal (0x0x7ff785e6cf00) 0 empty
+
+Vtable for QAbstractAnimation
+QAbstractAnimation::_ZTV18QAbstractAnimation: 18 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QAbstractAnimation)
+16 (int (*)(...))QAbstractAnimation::metaObject
+24 (int (*)(...))QAbstractAnimation::qt_metacast
+32 (int (*)(...))QAbstractAnimation::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QAbstractAnimation::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+128 (int (*)(...))QAbstractAnimation::updateState
+136 (int (*)(...))QAbstractAnimation::updateDirection
+
+Class QAbstractAnimation
+ size=16 align=8
+ base size=16 base align=8
+QAbstractAnimation (0x0x7ff785e46820) 0
+ vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16)
+ QObject (0x0x7ff785e6cea0) 0
+ primary-for QAbstractAnimation (0x0x7ff785e46820)
+
+Class QAnimationDriver::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAnimationDriver::QPrivateSignal (0x0x7ff785ea0300) 0 empty
+
+Vtable for QAnimationDriver
+QAnimationDriver::_ZTV16QAnimationDriver: 18 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI16QAnimationDriver)
+16 (int (*)(...))QAnimationDriver::metaObject
+24 (int (*)(...))QAnimationDriver::qt_metacast
+32 (int (*)(...))QAnimationDriver::qt_metacall
+40 (int (*)(...))QAnimationDriver::~QAnimationDriver
+48 (int (*)(...))QAnimationDriver::~QAnimationDriver
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QAnimationDriver::advance
+120 (int (*)(...))QAnimationDriver::elapsed
+128 (int (*)(...))QAnimationDriver::start
+136 (int (*)(...))QAnimationDriver::stop
+
+Class QAnimationDriver
+ size=16 align=8
+ base size=16 base align=8
+QAnimationDriver (0x0x7ff785e46888) 0
+ vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16)
+ QObject (0x0x7ff785ea02a0) 0
+ primary-for QAnimationDriver (0x0x7ff785e46888)
+
+Class QEventLoop::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QEventLoop::QPrivateSignal (0x0x7ff785ea0540) 0 empty
+
+Vtable for QEventLoop
+QEventLoop::_ZTV10QEventLoop: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI10QEventLoop)
+16 (int (*)(...))QEventLoop::metaObject
+24 (int (*)(...))QEventLoop::qt_metacast
+32 (int (*)(...))QEventLoop::qt_metacall
+40 (int (*)(...))QEventLoop::~QEventLoop
+48 (int (*)(...))QEventLoop::~QEventLoop
+56 (int (*)(...))QEventLoop::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QEventLoop
+ size=16 align=8
+ base size=16 base align=8
+QEventLoop (0x0x7ff785e468f0) 0
+ vptr=((& QEventLoop::_ZTV10QEventLoop) + 16)
+ QObject (0x0x7ff785ea04e0) 0
+ primary-for QEventLoop (0x0x7ff785e468f0)
+
+Class QEventLoopLocker
+ size=8 align=8
+ base size=8 base align=8
+QEventLoopLocker (0x0x7ff785ea0de0) 0
+
+Class QAbstractEventDispatcher::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractEventDispatcher::QPrivateSignal (0x0x7ff785ea0ea0) 0 empty
+
+Class QAbstractEventDispatcher::TimerInfo
+ size=12 align=4
+ base size=12 base align=4
+QAbstractEventDispatcher::TimerInfo (0x0x7ff785ea0f00) 0
+
+Vtable for QAbstractEventDispatcher
+QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher: 28 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI24QAbstractEventDispatcher)
+16 (int (*)(...))QAbstractEventDispatcher::metaObject
+24 (int (*)(...))QAbstractEventDispatcher::qt_metacast
+32 (int (*)(...))QAbstractEventDispatcher::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+128 (int (*)(...))__cxa_pure_virtual
+136 (int (*)(...))__cxa_pure_virtual
+144 (int (*)(...))__cxa_pure_virtual
+152 (int (*)(...))__cxa_pure_virtual
+160 (int (*)(...))__cxa_pure_virtual
+168 (int (*)(...))__cxa_pure_virtual
+176 (int (*)(...))__cxa_pure_virtual
+184 (int (*)(...))__cxa_pure_virtual
+192 (int (*)(...))__cxa_pure_virtual
+200 (int (*)(...))__cxa_pure_virtual
+208 (int (*)(...))QAbstractEventDispatcher::startingUp
+216 (int (*)(...))QAbstractEventDispatcher::closingDown
+
+Class QAbstractEventDispatcher
+ size=16 align=8
+ base size=16 base align=8
+QAbstractEventDispatcher (0x0x7ff785e46a28) 0
+ vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16)
+ QObject (0x0x7ff785ea0e40) 0
+ primary-for QAbstractEventDispatcher (0x0x7ff785e46a28)
+
+Vtable for std::bad_function_call
+std::bad_function_call::_ZTVSt17bad_function_call: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt17bad_function_call)
+16 (int (*)(...))std::bad_function_call::~bad_function_call
+24 (int (*)(...))std::bad_function_call::~bad_function_call
+32 (int (*)(...))std::bad_function_call::what
+
+Class std::bad_function_call
+ size=8 align=8
+ base size=8 base align=8
+std::bad_function_call (0x0x7ff785b783a8) 0 nearly-empty
+ vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16)
+ std::exception (0x0x7ff785b7d5a0) 0 nearly-empty
+ primary-for std::bad_function_call (0x0x7ff785b783a8)
+
+Class std::_Nocopy_types
+ size=16 align=8
+ base size=16 base align=8
+std::_Nocopy_types (0x0x7ff785b7d660) 0
+
+Class std::_Any_data
+ size=16 align=8
+ base size=16 base align=8
+std::_Any_data (0x0x7ff785b7d6c0) 0
+
+Class std::_Function_base
+ size=24 align=8
+ base size=24 base align=8
+std::_Function_base (0x0x7ff785b7d9c0) 0
+
+Class QMapNodeBase
+ size=24 align=8
+ base size=24 base align=8
+QMapNodeBase (0x0x7ff785977960) 0
+
+Class QMapDataBase
+ size=40 align=8
+ base size=40 base align=8
+QMapDataBase (0x0x7ff7859af600) 0
+
+Class QHashData::Node
+ size=16 align=8
+ base size=16 base align=8
+QHashData::Node (0x0x7ff785a73f60) 0
+
+Class QHashData
+ size=48 align=8
+ base size=44 base align=8
+QHashData (0x0x7ff785a73f00) 0
+
+Class QHashDummyValue
+ size=1 align=1
+ base size=0 base align=1
+QHashDummyValue (0x0x7ff785a9e240) 0 empty
+
+Class QVariant::PrivateShared
+ size=16 align=8
+ base size=12 base align=8
+QVariant::PrivateShared (0x0x7ff7857a87e0) 0
+
+Class QVariant::Private::Data
+ size=8 align=8
+ base size=8 base align=8
+QVariant::Private::Data (0x0x7ff7857a88a0) 0
+
+Class QVariant::Private
+ size=16 align=8
+ base size=12 base align=8
+QVariant::Private (0x0x7ff7857a8840) 0
+
+Class QVariant::Handler
+ size=72 align=8
+ base size=72 base align=8
+QVariant::Handler (0x0x7ff7857a8900) 0
+
+Class QVariant
+ size=16 align=8
+ base size=16 base align=8
+QVariant (0x0x7ff7857a8780) 0
+
+Class QVariantComparisonHelper
+ size=8 align=8
+ base size=8 base align=8
+QVariantComparisonHelper (0x0x7ff7858e2ba0) 0
+
+Class QSequentialIterable::const_iterator
+ size=112 align=8
+ base size=112 base align=8
+QSequentialIterable::const_iterator (0x0x7ff78555f240) 0
+
+Class QSequentialIterable
+ size=104 align=8
+ base size=104 base align=8
+QSequentialIterable (0x0x7ff78555f1e0) 0
+
+Class QAssociativeIterable::const_iterator
+ size=120 align=8
+ base size=120 base align=8
+QAssociativeIterable::const_iterator (0x0x7ff78555f360) 0
+
+Class QAssociativeIterable
+ size=112 align=8
+ base size=112 base align=8
+QAssociativeIterable (0x0x7ff78555f300) 0
+
+Class QModelIndex
+ size=24 align=8
+ base size=24 base align=8
+QModelIndex (0x0x7ff78562b4e0) 0
+
+Class QPersistentModelIndex
+ size=8 align=8
+ base size=8 base align=8
+QPersistentModelIndex (0x0x7ff78569d120) 0
+
+Class QAbstractItemModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractItemModel::QPrivateSignal (0x0x7ff785753f00) 0 empty
+
+Vtable for QAbstractItemModel
+QAbstractItemModel::_ZTV18QAbstractItemModel: 48 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QAbstractItemModel)
+16 (int (*)(...))QAbstractItemModel::metaObject
+24 (int (*)(...))QAbstractItemModel::qt_metacast
+32 (int (*)(...))QAbstractItemModel::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+128 (int (*)(...))QAbstractItemModel::sibling
+136 (int (*)(...))__cxa_pure_virtual
+144 (int (*)(...))__cxa_pure_virtual
+152 (int (*)(...))QAbstractItemModel::hasChildren
+160 (int (*)(...))__cxa_pure_virtual
+168 (int (*)(...))QAbstractItemModel::setData
+176 (int (*)(...))QAbstractItemModel::headerData
+184 (int (*)(...))QAbstractItemModel::setHeaderData
+192 (int (*)(...))QAbstractItemModel::itemData
+200 (int (*)(...))QAbstractItemModel::setItemData
+208 (int (*)(...))QAbstractItemModel::mimeTypes
+216 (int (*)(...))QAbstractItemModel::mimeData
+224 (int (*)(...))QAbstractItemModel::canDropMimeData
+232 (int (*)(...))QAbstractItemModel::dropMimeData
+240 (int (*)(...))QAbstractItemModel::supportedDropActions
+248 (int (*)(...))QAbstractItemModel::supportedDragActions
+256 (int (*)(...))QAbstractItemModel::insertRows
+264 (int (*)(...))QAbstractItemModel::insertColumns
+272 (int (*)(...))QAbstractItemModel::removeRows
+280 (int (*)(...))QAbstractItemModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractItemModel::fetchMore
+312 (int (*)(...))QAbstractItemModel::canFetchMore
+320 (int (*)(...))QAbstractItemModel::flags
+328 (int (*)(...))QAbstractItemModel::sort
+336 (int (*)(...))QAbstractItemModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QAbstractItemModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractItemModel::submit
+376 (int (*)(...))QAbstractItemModel::revert
+
+Class QAbstractItemModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractItemModel (0x0x7ff785751f70) 0
+ vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16)
+ QObject (0x0x7ff785753ea0) 0
+ primary-for QAbstractItemModel (0x0x7ff785751f70)
+
+Class QAbstractTableModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractTableModel::QPrivateSignal (0x0x7ff785431300) 0 empty
+
+Vtable for QAbstractTableModel
+QAbstractTableModel::_ZTV19QAbstractTableModel: 48 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QAbstractTableModel)
+16 (int (*)(...))QAbstractTableModel::metaObject
+24 (int (*)(...))QAbstractTableModel::qt_metacast
+32 (int (*)(...))QAbstractTableModel::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QAbstractTableModel::index
+120 (int (*)(...))QAbstractTableModel::parent
+128 (int (*)(...))QAbstractTableModel::sibling
+136 (int (*)(...))__cxa_pure_virtual
+144 (int (*)(...))__cxa_pure_virtual
+152 (int (*)(...))QAbstractTableModel::hasChildren
+160 (int (*)(...))__cxa_pure_virtual
+168 (int (*)(...))QAbstractItemModel::setData
+176 (int (*)(...))QAbstractItemModel::headerData
+184 (int (*)(...))QAbstractItemModel::setHeaderData
+192 (int (*)(...))QAbstractItemModel::itemData
+200 (int (*)(...))QAbstractItemModel::setItemData
+208 (int (*)(...))QAbstractItemModel::mimeTypes
+216 (int (*)(...))QAbstractItemModel::mimeData
+224 (int (*)(...))QAbstractItemModel::canDropMimeData
+232 (int (*)(...))QAbstractTableModel::dropMimeData
+240 (int (*)(...))QAbstractItemModel::supportedDropActions
+248 (int (*)(...))QAbstractItemModel::supportedDragActions
+256 (int (*)(...))QAbstractItemModel::insertRows
+264 (int (*)(...))QAbstractItemModel::insertColumns
+272 (int (*)(...))QAbstractItemModel::removeRows
+280 (int (*)(...))QAbstractItemModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractItemModel::fetchMore
+312 (int (*)(...))QAbstractItemModel::canFetchMore
+320 (int (*)(...))QAbstractTableModel::flags
+328 (int (*)(...))QAbstractItemModel::sort
+336 (int (*)(...))QAbstractItemModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QAbstractItemModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractItemModel::submit
+376 (int (*)(...))QAbstractItemModel::revert
+
+Class QAbstractTableModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractTableModel (0x0x7ff7853985b0) 0
+ vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16)
+ QAbstractItemModel (0x0x7ff785398618) 0
+ primary-for QAbstractTableModel (0x0x7ff7853985b0)
+ QObject (0x0x7ff7854312a0) 0
+ primary-for QAbstractItemModel (0x0x7ff785398618)
+
+Class QAbstractListModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractListModel::QPrivateSignal (0x0x7ff785431480) 0 empty
+
+Vtable for QAbstractListModel
+QAbstractListModel::_ZTV18QAbstractListModel: 48 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QAbstractListModel)
+16 (int (*)(...))QAbstractListModel::metaObject
+24 (int (*)(...))QAbstractListModel::qt_metacast
+32 (int (*)(...))QAbstractListModel::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QAbstractListModel::index
+120 (int (*)(...))QAbstractListModel::parent
+128 (int (*)(...))QAbstractListModel::sibling
+136 (int (*)(...))__cxa_pure_virtual
+144 (int (*)(...))QAbstractListModel::columnCount
+152 (int (*)(...))QAbstractListModel::hasChildren
+160 (int (*)(...))__cxa_pure_virtual
+168 (int (*)(...))QAbstractItemModel::setData
+176 (int (*)(...))QAbstractItemModel::headerData
+184 (int (*)(...))QAbstractItemModel::setHeaderData
+192 (int (*)(...))QAbstractItemModel::itemData
+200 (int (*)(...))QAbstractItemModel::setItemData
+208 (int (*)(...))QAbstractItemModel::mimeTypes
+216 (int (*)(...))QAbstractItemModel::mimeData
+224 (int (*)(...))QAbstractItemModel::canDropMimeData
+232 (int (*)(...))QAbstractListModel::dropMimeData
+240 (int (*)(...))QAbstractItemModel::supportedDropActions
+248 (int (*)(...))QAbstractItemModel::supportedDragActions
+256 (int (*)(...))QAbstractItemModel::insertRows
+264 (int (*)(...))QAbstractItemModel::insertColumns
+272 (int (*)(...))QAbstractItemModel::removeRows
+280 (int (*)(...))QAbstractItemModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractItemModel::fetchMore
+312 (int (*)(...))QAbstractItemModel::canFetchMore
+320 (int (*)(...))QAbstractListModel::flags
+328 (int (*)(...))QAbstractItemModel::sort
+336 (int (*)(...))QAbstractItemModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QAbstractItemModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractItemModel::submit
+376 (int (*)(...))QAbstractItemModel::revert
+
+Class QAbstractListModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractListModel (0x0x7ff785398680) 0
+ vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16)
+ QAbstractItemModel (0x0x7ff7853986e8) 0
+ primary-for QAbstractListModel (0x0x7ff785398680)
+ QObject (0x0x7ff785431420) 0
+ primary-for QAbstractItemModel (0x0x7ff7853986e8)
+
+Vtable for QAbstractNativeEventFilter
+QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI26QAbstractNativeEventFilter)
+16 0
+24 0
+32 (int (*)(...))__cxa_pure_virtual
+
+Class QAbstractNativeEventFilter
+ size=16 align=8
+ base size=16 base align=8
+QAbstractNativeEventFilter (0x0x7ff785431ba0) 0
+ vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16)
+
+Class QAbstractProxyModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractProxyModel::QPrivateSignal (0x0x7ff785431c60) 0 empty
+
+Vtable for QAbstractProxyModel
+QAbstractProxyModel::_ZTV19QAbstractProxyModel: 53 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QAbstractProxyModel)
+16 (int (*)(...))QAbstractProxyModel::metaObject
+24 (int (*)(...))QAbstractProxyModel::qt_metacast
+32 (int (*)(...))QAbstractProxyModel::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+128 (int (*)(...))QAbstractProxyModel::sibling
+136 (int (*)(...))__cxa_pure_virtual
+144 (int (*)(...))__cxa_pure_virtual
+152 (int (*)(...))QAbstractProxyModel::hasChildren
+160 (int (*)(...))QAbstractProxyModel::data
+168 (int (*)(...))QAbstractProxyModel::setData
+176 (int (*)(...))QAbstractProxyModel::headerData
+184 (int (*)(...))QAbstractProxyModel::setHeaderData
+192 (int (*)(...))QAbstractProxyModel::itemData
+200 (int (*)(...))QAbstractProxyModel::setItemData
+208 (int (*)(...))QAbstractProxyModel::mimeTypes
+216 (int (*)(...))QAbstractProxyModel::mimeData
+224 (int (*)(...))QAbstractProxyModel::canDropMimeData
+232 (int (*)(...))QAbstractProxyModel::dropMimeData
+240 (int (*)(...))QAbstractProxyModel::supportedDropActions
+248 (int (*)(...))QAbstractProxyModel::supportedDragActions
+256 (int (*)(...))QAbstractItemModel::insertRows
+264 (int (*)(...))QAbstractItemModel::insertColumns
+272 (int (*)(...))QAbstractItemModel::removeRows
+280 (int (*)(...))QAbstractItemModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractProxyModel::fetchMore
+312 (int (*)(...))QAbstractProxyModel::canFetchMore
+320 (int (*)(...))QAbstractProxyModel::flags
+328 (int (*)(...))QAbstractProxyModel::sort
+336 (int (*)(...))QAbstractProxyModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QAbstractProxyModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractProxyModel::submit
+376 (int (*)(...))QAbstractProxyModel::revert
+384 (int (*)(...))QAbstractProxyModel::setSourceModel
+392 (int (*)(...))__cxa_pure_virtual
+400 (int (*)(...))__cxa_pure_virtual
+408 (int (*)(...))QAbstractProxyModel::mapSelectionToSource
+416 (int (*)(...))QAbstractProxyModel::mapSelectionFromSource
+
+Class QAbstractProxyModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractProxyModel (0x0x7ff7853987b8) 0
+ vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16)
+ QAbstractItemModel (0x0x7ff785398820) 0
+ primary-for QAbstractProxyModel (0x0x7ff7853987b8)
+ QObject (0x0x7ff785431c00) 0
+ primary-for QAbstractItemModel (0x0x7ff785398820)
+
+Class QAbstractState::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractState::QPrivateSignal (0x0x7ff785431ea0) 0 empty
+
+Vtable for QAbstractState
+QAbstractState::_ZTV14QAbstractState: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI14QAbstractState)
+16 (int (*)(...))QAbstractState::metaObject
+24 (int (*)(...))QAbstractState::qt_metacast
+32 (int (*)(...))QAbstractState::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QAbstractState::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+
+Class QAbstractState
+ size=16 align=8
+ base size=16 base align=8
+QAbstractState (0x0x7ff785398888) 0
+ vptr=((& QAbstractState::_ZTV14QAbstractState) + 16)
+ QObject (0x0x7ff785431e40) 0
+ primary-for QAbstractState (0x0x7ff785398888)
+
+Class QAbstractTransition::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAbstractTransition::QPrivateSignal (0x0x7ff7854bc120) 0 empty
+
+Vtable for QAbstractTransition
+QAbstractTransition::_ZTV19QAbstractTransition: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QAbstractTransition)
+16 (int (*)(...))QAbstractTransition::metaObject
+24 (int (*)(...))QAbstractTransition::qt_metacast
+32 (int (*)(...))QAbstractTransition::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QAbstractTransition::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+
+Class QAbstractTransition
+ size=16 align=8
+ base size=16 base align=8
+QAbstractTransition (0x0x7ff7853988f0) 0
+ vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16)
+ QObject (0x0x7ff7854bc0c0) 0
+ primary-for QAbstractTransition (0x0x7ff7853988f0)
+
+Class QAnimationGroup::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QAnimationGroup::QPrivateSignal (0x0x7ff7854bc420) 0 empty
+
+Vtable for QAnimationGroup
+QAnimationGroup::_ZTV15QAnimationGroup: 18 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI15QAnimationGroup)
+16 (int (*)(...))QAnimationGroup::metaObject
+24 (int (*)(...))QAnimationGroup::qt_metacast
+32 (int (*)(...))QAnimationGroup::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QAnimationGroup::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+128 (int (*)(...))QAbstractAnimation::updateState
+136 (int (*)(...))QAbstractAnimation::updateDirection
+
+Class QAnimationGroup
+ size=16 align=8
+ base size=16 base align=8
+QAnimationGroup (0x0x7ff785398958) 0
+ vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16)
+ QAbstractAnimation (0x0x7ff7853989c0) 0
+ primary-for QAnimationGroup (0x0x7ff785398958)
+ QObject (0x0x7ff7854bc3c0) 0
+ primary-for QAbstractAnimation (0x0x7ff7853989c0)
+
+Class QBasicTimer
+ size=4 align=4
+ base size=4 base align=4
+QBasicTimer (0x0x7ff78551b780) 0
+
+Class QBitArray
+ size=8 align=8
+ base size=8 base align=8
+QBitArray (0x0x7ff785555b40) 0
+
+Class QBitRef
+ size=16 align=8
+ base size=12 base align=8
+QBitRef (0x0x7ff7851dc000) 0
+
+Class QIODevice::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QIODevice::QPrivateSignal (0x0x7ff7852203c0) 0 empty
+
+Vtable for QIODevice
+QIODevice::_ZTV9QIODevice: 30 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QIODevice)
+16 (int (*)(...))QIODevice::metaObject
+24 (int (*)(...))QIODevice::qt_metacast
+32 (int (*)(...))QIODevice::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QIODevice::isSequential
+120 (int (*)(...))QIODevice::open
+128 (int (*)(...))QIODevice::close
+136 (int (*)(...))QIODevice::pos
+144 (int (*)(...))QIODevice::size
+152 (int (*)(...))QIODevice::seek
+160 (int (*)(...))QIODevice::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QIODevice::bytesAvailable
+184 (int (*)(...))QIODevice::bytesToWrite
+192 (int (*)(...))QIODevice::canReadLine
+200 (int (*)(...))QIODevice::waitForReadyRead
+208 (int (*)(...))QIODevice::waitForBytesWritten
+216 (int (*)(...))__cxa_pure_virtual
+224 (int (*)(...))QIODevice::readLineData
+232 (int (*)(...))__cxa_pure_virtual
+
+Class QIODevice
+ size=16 align=8
+ base size=16 base align=8
+QIODevice (0x0x7ff78520af08) 0
+ vptr=((& QIODevice::_ZTV9QIODevice) + 16)
+ QObject (0x0x7ff785220360) 0
+ primary-for QIODevice (0x0x7ff78520af08)
+
+Class QBuffer::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QBuffer::QPrivateSignal (0x0x7ff785220d20) 0 empty
+
+Vtable for QBuffer
+QBuffer::_ZTV7QBuffer: 30 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI7QBuffer)
+16 (int (*)(...))QBuffer::metaObject
+24 (int (*)(...))QBuffer::qt_metacast
+32 (int (*)(...))QBuffer::qt_metacall
+40 (int (*)(...))QBuffer::~QBuffer
+48 (int (*)(...))QBuffer::~QBuffer
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QBuffer::connectNotify
+104 (int (*)(...))QBuffer::disconnectNotify
+112 (int (*)(...))QIODevice::isSequential
+120 (int (*)(...))QBuffer::open
+128 (int (*)(...))QBuffer::close
+136 (int (*)(...))QBuffer::pos
+144 (int (*)(...))QBuffer::size
+152 (int (*)(...))QBuffer::seek
+160 (int (*)(...))QBuffer::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QIODevice::bytesAvailable
+184 (int (*)(...))QIODevice::bytesToWrite
+192 (int (*)(...))QBuffer::canReadLine
+200 (int (*)(...))QIODevice::waitForReadyRead
+208 (int (*)(...))QIODevice::waitForBytesWritten
+216 (int (*)(...))QBuffer::readData
+224 (int (*)(...))QIODevice::readLineData
+232 (int (*)(...))QBuffer::writeData
+
+Class QBuffer
+ size=16 align=8
+ base size=16 base align=8
+QBuffer (0x0x7ff785243068) 0
+ vptr=((& QBuffer::_ZTV7QBuffer) + 16)
+ QIODevice (0x0x7ff7852430d0) 0
+ primary-for QBuffer (0x0x7ff785243068)
+ QObject (0x0x7ff785220cc0) 0
+ primary-for QIODevice (0x0x7ff7852430d0)
+
+Class QByteArrayMatcher::Data
+ size=272 align=8
+ base size=272 base align=8
+QByteArrayMatcher::Data (0x0x7ff78527c000) 0
+
+Class QByteArrayMatcher
+ size=1040 align=8
+ base size=1040 base align=8
+QByteArrayMatcher (0x0x7ff785220f60) 0
+
+Class QStaticByteArrayMatcherBase::Skiptable
+ size=256 align=1
+ base size=256 base align=1
+QStaticByteArrayMatcherBase::Skiptable (0x0x7ff78527c180) 0
+
+Class QStaticByteArrayMatcherBase
+ size=256 align=16
+ base size=256 base align=16
+QStaticByteArrayMatcherBase (0x0x7ff78527c120) 0
+
+Class QSharedData
+ size=4 align=4
+ base size=4 base align=4
+QSharedData (0x0x7ff7852ba060) 0
+
+Class QDate
+ size=8 align=8
+ base size=8 base align=8
+QDate (0x0x7ff7852ff000) 0
+
+Class QTime
+ size=4 align=4
+ base size=4 base align=4
+QTime (0x0x7ff78534e8a0) 0
+
+Class QDateTime::ShortData
+ size=8 align=8
+ base size=8 base align=8
+QDateTime::ShortData (0x0x7ff784fb5540) 0
+
+Class QDateTime::Data
+ size=8 align=8
+ base size=8 base align=8
+QDateTime::Data (0x0x7ff784fb55a0) 0
+
+Class QDateTime
+ size=8 align=8
+ base size=8 base align=8
+QDateTime (0x0x7ff784fb54e0) 0
+
+Class QLocale
+ size=8 align=8
+ base size=8 base align=8
+QLocale (0x0x7ff785086c60) 0
+
+Vtable for QTextStream
+QTextStream::_ZTV11QTextStream: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QTextStream)
+16 (int (*)(...))QTextStream::~QTextStream
+24 (int (*)(...))QTextStream::~QTextStream
+
+Class QTextStream
+ size=16 align=8
+ base size=16 base align=8
+QTextStream (0x0x7ff784da9240) 0
+ vptr=((& QTextStream::_ZTV11QTextStream) + 16)
+
+Class QTextStreamManipulator
+ size=40 align=8
+ base size=38 base align=8
+QTextStreamManipulator (0x0x7ff784da9ae0) 0
+
+Class QContiguousCacheData
+ size=24 align=4
+ base size=24 base align=4
+QContiguousCacheData (0x0x7ff784e7e600) 0
+
+Class QtSharedPointer::NormalDeleter
+ size=1 align=1
+ base size=0 base align=1
+QtSharedPointer::NormalDeleter (0x0x7ff784ece2a0) 0 empty
+
+Class QtSharedPointer::ExternalRefCountData
+ size=16 align=8
+ base size=16 base align=8
+QtSharedPointer::ExternalRefCountData (0x0x7ff784ece420) 0
+
+Class QDebug::Stream
+ size=80 align=8
+ base size=76 base align=8
+QDebug::Stream (0x0x7ff784b9c060) 0
+
+Class QDebug
+ size=8 align=8
+ base size=8 base align=8
+QDebug (0x0x7ff784b9c000) 0
+
+Class QDebugStateSaver
+ size=8 align=8
+ base size=8 base align=8
+QDebugStateSaver (0x0x7ff784d1f0c0) 0
+
+Class QNoDebug
+ size=1 align=1
+ base size=0 base align=1
+QNoDebug (0x0x7ff784d1f180) 0 empty
+
+Class QCborError
+ size=4 align=4
+ base size=4 base align=4
+QCborError (0x0x7ff7849a5480) 0
+
+Class QRegularExpression
+ size=8 align=8
+ base size=8 base align=8
+QRegularExpression (0x0x7ff7849a5c00) 0
+
+Class QRegularExpressionMatch
+ size=8 align=8
+ base size=8 base align=8
+QRegularExpressionMatch (0x0x7ff784a5dae0) 0
+
+Class QRegularExpressionMatchIterator
+ size=8 align=8
+ base size=8 base align=8
+QRegularExpressionMatchIterator (0x0x7ff784ac88a0) 0
+
+Class QUrl
+ size=8 align=8
+ base size=8 base align=8
+QUrl (0x0x7ff784b3e300) 0
+
+Class QUuid
+ size=16 align=4
+ base size=16 base align=4
+QUuid (0x0x7ff7848922a0) 0
+
+Class QCborParserError
+ size=16 align=8
+ base size=12 base align=8
+QCborParserError (0x0x7ff7848f4de0) 0
+
+Class QCborValue
+ size=24 align=8
+ base size=20 base align=8
+QCborValue (0x0x7ff7848f4ea0) 0
+
+Class QCborValueRef
+ size=16 align=8
+ base size=16 base align=8
+QCborValueRef (0x0x7ff78435dea0) 0
+
+Class QCborArray::Iterator
+ size=16 align=8
+ base size=16 base align=8
+QCborArray::Iterator (0x0x7ff7843fc900) 0
+
+Class QCborArray::ConstIterator
+ size=16 align=8
+ base size=16 base align=8
+QCborArray::ConstIterator (0x0x7ff7843fc960) 0
+
+Class QCborArray
+ size=8 align=8
+ base size=8 base align=8
+QCborArray (0x0x7ff7843fc8a0) 0
+
+Class QCborMap::Iterator
+ size=16 align=8
+ base size=16 base align=8
+QCborMap::Iterator (0x0x7ff784511360) 0
+
+Class QCborMap::ConstIterator
+ size=16 align=8
+ base size=16 base align=8
+QCborMap::ConstIterator (0x0x7ff7845113c0) 0
+
+Class QCborMap
+ size=8 align=8
+ base size=8 base align=8
+QCborMap (0x0x7ff784511300) 0
+
+Class qfloat16
+ size=2 align=2
+ base size=2 base align=2
+qfloat16 (0x0x7ff78430bae0) 0
+
+Class QCborStreamWriter
+ size=8 align=8
+ base size=8 base align=8
+QCborStreamWriter (0x0x7ff783fc2a80) 0
+
+Class QCborStreamReader
+ size=24 align=8
+ base size=20 base align=8
+QCborStreamReader (0x0x7ff783ff77e0) 0
+
+Class QCollatorSortKey
+ size=8 align=8
+ base size=8 base align=8
+QCollatorSortKey (0x0x7ff78407d900) 0
+
+Class QCollator
+ size=8 align=8
+ base size=8 base align=8
+QCollator (0x0x7ff78407dae0) 0
+
+Class QCommandLineOption
+ size=8 align=8
+ base size=8 base align=8
+QCommandLineOption (0x0x7ff783d910c0) 0
+
+Vtable for QEvent
+QEvent::_ZTV6QEvent: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI6QEvent)
+16 (int (*)(...))QEvent::~QEvent
+24 (int (*)(...))QEvent::~QEvent
+
+Class QEvent
+ size=24 align=8
+ base size=20 base align=8
+QEvent (0x0x7ff783de87e0) 0
+ vptr=((& QEvent::_ZTV6QEvent) + 16)
+
+Vtable for QTimerEvent
+QTimerEvent::_ZTV11QTimerEvent: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QTimerEvent)
+16 (int (*)(...))QTimerEvent::~QTimerEvent
+24 (int (*)(...))QTimerEvent::~QTimerEvent
+
+Class QTimerEvent
+ size=24 align=8
+ base size=24 base align=8
+QTimerEvent (0x0x7ff783de6270) 0
+ vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16)
+ QEvent (0x0x7ff783de8ba0) 0
+ primary-for QTimerEvent (0x0x7ff783de6270)
+
+Vtable for QChildEvent
+QChildEvent::_ZTV11QChildEvent: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QChildEvent)
+16 (int (*)(...))QChildEvent::~QChildEvent
+24 (int (*)(...))QChildEvent::~QChildEvent
+
+Class QChildEvent
+ size=32 align=8
+ base size=32 base align=8
+QChildEvent (0x0x7ff783de62d8) 0
+ vptr=((& QChildEvent::_ZTV11QChildEvent) + 16)
+ QEvent (0x0x7ff783de8c60) 0
+ primary-for QChildEvent (0x0x7ff783de62d8)
+
+Vtable for QDynamicPropertyChangeEvent
+QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI27QDynamicPropertyChangeEvent)
+16 (int (*)(...))QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent
+24 (int (*)(...))QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent
+
+Class QDynamicPropertyChangeEvent
+ size=32 align=8
+ base size=32 base align=8
+QDynamicPropertyChangeEvent (0x0x7ff783de6820) 0
+ vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16)
+ QEvent (0x0x7ff783e32300) 0
+ primary-for QDynamicPropertyChangeEvent (0x0x7ff783de6820)
+
+Vtable for QDeferredDeleteEvent
+QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI20QDeferredDeleteEvent)
+16 (int (*)(...))QDeferredDeleteEvent::~QDeferredDeleteEvent
+24 (int (*)(...))QDeferredDeleteEvent::~QDeferredDeleteEvent
+
+Class QDeferredDeleteEvent
+ size=24 align=8
+ base size=24 base align=8
+QDeferredDeleteEvent (0x0x7ff783de6888) 0
+ vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16)
+ QEvent (0x0x7ff783e323c0) 0
+ primary-for QDeferredDeleteEvent (0x0x7ff783de6888)
+
+Class QCoreApplication::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QCoreApplication::QPrivateSignal (0x0x7ff783e324e0) 0 empty
+
+Vtable for QCoreApplication
+QCoreApplication::_ZTV16QCoreApplication: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI16QCoreApplication)
+16 (int (*)(...))QCoreApplication::metaObject
+24 (int (*)(...))QCoreApplication::qt_metacast
+32 (int (*)(...))QCoreApplication::qt_metacall
+40 (int (*)(...))QCoreApplication::~QCoreApplication
+48 (int (*)(...))QCoreApplication::~QCoreApplication
+56 (int (*)(...))QCoreApplication::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QCoreApplication::notify
+120 (int (*)(...))QCoreApplication::compressEvent
+
+Class QCoreApplication
+ size=16 align=8
+ base size=16 base align=8
+QCoreApplication (0x0x7ff783de68f0) 0
+ vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16)
+ QObject (0x0x7ff783e32480) 0
+ primary-for QCoreApplication (0x0x7ff783de68f0)
+
+Class QCommandLineParser
+ size=8 align=8
+ base size=8 base align=8
+QCommandLineParser (0x0x7ff783e32720) 0
+
+Class QConcatenateTablesProxyModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QConcatenateTablesProxyModel::QPrivateSignal (0x0x7ff783e328a0) 0 empty
+
+Vtable for QConcatenateTablesProxyModel
+QConcatenateTablesProxyModel::_ZTV28QConcatenateTablesProxyModel: 48 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI28QConcatenateTablesProxyModel)
+16 (int (*)(...))QConcatenateTablesProxyModel::metaObject
+24 (int (*)(...))QConcatenateTablesProxyModel::qt_metacast
+32 (int (*)(...))QConcatenateTablesProxyModel::qt_metacall
+40 (int (*)(...))QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel
+48 (int (*)(...))QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QConcatenateTablesProxyModel::index
+120 (int (*)(...))QConcatenateTablesProxyModel::parent
+128 (int (*)(...))QAbstractItemModel::sibling
+136 (int (*)(...))QConcatenateTablesProxyModel::rowCount
+144 (int (*)(...))QConcatenateTablesProxyModel::columnCount
+152 (int (*)(...))QAbstractItemModel::hasChildren
+160 (int (*)(...))QConcatenateTablesProxyModel::data
+168 (int (*)(...))QConcatenateTablesProxyModel::setData
+176 (int (*)(...))QConcatenateTablesProxyModel::headerData
+184 (int (*)(...))QAbstractItemModel::setHeaderData
+192 (int (*)(...))QConcatenateTablesProxyModel::itemData
+200 (int (*)(...))QConcatenateTablesProxyModel::setItemData
+208 (int (*)(...))QConcatenateTablesProxyModel::mimeTypes
+216 (int (*)(...))QConcatenateTablesProxyModel::mimeData
+224 (int (*)(...))QConcatenateTablesProxyModel::canDropMimeData
+232 (int (*)(...))QConcatenateTablesProxyModel::dropMimeData
+240 (int (*)(...))QAbstractItemModel::supportedDropActions
+248 (int (*)(...))QAbstractItemModel::supportedDragActions
+256 (int (*)(...))QAbstractItemModel::insertRows
+264 (int (*)(...))QAbstractItemModel::insertColumns
+272 (int (*)(...))QAbstractItemModel::removeRows
+280 (int (*)(...))QAbstractItemModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractItemModel::fetchMore
+312 (int (*)(...))QAbstractItemModel::canFetchMore
+320 (int (*)(...))QConcatenateTablesProxyModel::flags
+328 (int (*)(...))QAbstractItemModel::sort
+336 (int (*)(...))QAbstractItemModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QConcatenateTablesProxyModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractItemModel::submit
+376 (int (*)(...))QAbstractItemModel::revert
+
+Class QConcatenateTablesProxyModel
+ size=16 align=8
+ base size=16 base align=8
+QConcatenateTablesProxyModel (0x0x7ff783de6958) 0
+ vptr=((& QConcatenateTablesProxyModel::_ZTV28QConcatenateTablesProxyModel) + 16)
+ QAbstractItemModel (0x0x7ff783de69c0) 0
+ primary-for QConcatenateTablesProxyModel (0x0x7ff783de6958)
+ QObject (0x0x7ff783e32840) 0
+ primary-for QAbstractItemModel (0x0x7ff783de69c0)
+
+Class QCryptographicHash
+ size=8 align=8
+ base size=8 base align=8
+QCryptographicHash (0x0x7ff783e32a80) 0
+
+Class QDataStream
+ size=32 align=8
+ base size=32 base align=8
+QDataStream (0x0x7ff783e32ba0) 0
+
+Class QtPrivate::StreamStateSaver
+ size=16 align=8
+ base size=12 base align=8
+QtPrivate::StreamStateSaver (0x0x7ff783e32d20) 0
+
+Class QElapsedTimer
+ size=16 align=8
+ base size=16 base align=8
+QElapsedTimer (0x0x7ff783ef6480) 0
+
+Class QDeadlineTimer
+ size=16 align=8
+ base size=16 base align=8
+QDeadlineTimer (0x0x7ff783ef6ba0) 0
+
+Class QFileDevice::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QFileDevice::QPrivateSignal (0x0x7ff783c43900) 0 empty
+
+Vtable for QFileDevice
+QFileDevice::_ZTV11QFileDevice: 34 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QFileDevice)
+16 (int (*)(...))QFileDevice::metaObject
+24 (int (*)(...))QFileDevice::qt_metacast
+32 (int (*)(...))QFileDevice::qt_metacall
+40 (int (*)(...))QFileDevice::~QFileDevice
+48 (int (*)(...))QFileDevice::~QFileDevice
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QFileDevice::isSequential
+120 (int (*)(...))QIODevice::open
+128 (int (*)(...))QFileDevice::close
+136 (int (*)(...))QFileDevice::pos
+144 (int (*)(...))QFileDevice::size
+152 (int (*)(...))QFileDevice::seek
+160 (int (*)(...))QFileDevice::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QIODevice::bytesAvailable
+184 (int (*)(...))QIODevice::bytesToWrite
+192 (int (*)(...))QIODevice::canReadLine
+200 (int (*)(...))QIODevice::waitForReadyRead
+208 (int (*)(...))QIODevice::waitForBytesWritten
+216 (int (*)(...))QFileDevice::readData
+224 (int (*)(...))QFileDevice::readLineData
+232 (int (*)(...))QFileDevice::writeData
+240 (int (*)(...))QFileDevice::fileName
+248 (int (*)(...))QFileDevice::resize
+256 (int (*)(...))QFileDevice::permissions
+264 (int (*)(...))QFileDevice::setPermissions
+
+Class QFileDevice
+ size=16 align=8
+ base size=16 base align=8
+QFileDevice (0x0x7ff783c35bc8) 0
+ vptr=((& QFileDevice::_ZTV11QFileDevice) + 16)
+ QIODevice (0x0x7ff783c35c30) 0
+ primary-for QFileDevice (0x0x7ff783c35bc8)
+ QObject (0x0x7ff783c438a0) 0
+ primary-for QIODevice (0x0x7ff783c35c30)
+
+Class QFile::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QFile::QPrivateSignal (0x0x7ff783c8e240) 0 empty
+
+Vtable for QFile
+QFile::_ZTV5QFile: 34 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI5QFile)
+16 (int (*)(...))QFile::metaObject
+24 (int (*)(...))QFile::qt_metacast
+32 (int (*)(...))QFile::qt_metacall
+40 (int (*)(...))QFile::~QFile
+48 (int (*)(...))QFile::~QFile
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QFileDevice::isSequential
+120 (int (*)(...))QFile::open
+128 (int (*)(...))QFileDevice::close
+136 (int (*)(...))QFileDevice::pos
+144 (int (*)(...))QFile::size
+152 (int (*)(...))QFileDevice::seek
+160 (int (*)(...))QFileDevice::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QIODevice::bytesAvailable
+184 (int (*)(...))QIODevice::bytesToWrite
+192 (int (*)(...))QIODevice::canReadLine
+200 (int (*)(...))QIODevice::waitForReadyRead
+208 (int (*)(...))QIODevice::waitForBytesWritten
+216 (int (*)(...))QFileDevice::readData
+224 (int (*)(...))QFileDevice::readLineData
+232 (int (*)(...))QFileDevice::writeData
+240 (int (*)(...))QFile::fileName
+248 (int (*)(...))QFile::resize
+256 (int (*)(...))QFile::permissions
+264 (int (*)(...))QFile::setPermissions
+
+Class QFile
+ size=16 align=8
+ base size=16 base align=8
+QFile (0x0x7ff783c35d68) 0
+ vptr=((& QFile::_ZTV5QFile) + 16)
+ QFileDevice (0x0x7ff783c35dd0) 0
+ primary-for QFile (0x0x7ff783c35d68)
+ QIODevice (0x0x7ff783c35e38) 0
+ primary-for QFileDevice (0x0x7ff783c35dd0)
+ QObject (0x0x7ff783c8e1e0) 0
+ primary-for QIODevice (0x0x7ff783c35e38)
+
+Class QFileInfo
+ size=8 align=8
+ base size=8 base align=8
+QFileInfo (0x0x7ff783c8e8a0) 0
+
+Class QDir
+ size=8 align=8
+ base size=8 base align=8
+QDir (0x0x7ff783d09c60) 0
+
+Class QDirIterator
+ size=8 align=8
+ base size=8 base align=8
+QDirIterator (0x0x7ff7839a9000) 0
+
+Class QEasingCurve
+ size=8 align=8
+ base size=8 base align=8
+QEasingCurve (0x0x7ff7839a9780) 0
+
+Class QEventTransition::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QEventTransition::QPrivateSignal (0x0x7ff783ad28a0) 0 empty
+
+Vtable for QEventTransition
+QEventTransition::_ZTV16QEventTransition: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI16QEventTransition)
+16 (int (*)(...))QEventTransition::metaObject
+24 (int (*)(...))QEventTransition::qt_metacast
+32 (int (*)(...))QEventTransition::qt_metacall
+40 (int (*)(...))QEventTransition::~QEventTransition
+48 (int (*)(...))QEventTransition::~QEventTransition
+56 (int (*)(...))QEventTransition::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QEventTransition::eventTest
+120 (int (*)(...))QEventTransition::onTransition
+
+Class QEventTransition
+ size=16 align=8
+ base size=16 base align=8
+QEventTransition (0x0x7ff783ade0d0) 0
+ vptr=((& QEventTransition::_ZTV16QEventTransition) + 16)
+ QAbstractTransition (0x0x7ff783ade138) 0
+ primary-for QEventTransition (0x0x7ff783ade0d0)
+ QObject (0x0x7ff783ad2840) 0
+ primary-for QAbstractTransition (0x0x7ff783ade138)
+
+Vtable for QException
+QException::_ZTV10QException: 7 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI10QException)
+16 (int (*)(...))QException::~QException
+24 (int (*)(...))QException::~QException
+32 (int (*)(...))std::exception::what
+40 (int (*)(...))QException::raise
+48 (int (*)(...))QException::clone
+
+Class QException
+ size=8 align=8
+ base size=8 base align=8
+QException (0x0x7ff783ade1a0) 0 nearly-empty
+ vptr=((& QException::_ZTV10QException) + 16)
+ std::exception (0x0x7ff783ad2a80) 0 nearly-empty
+ primary-for QException (0x0x7ff783ade1a0)
+
+Vtable for QUnhandledException
+QUnhandledException::_ZTV19QUnhandledException: 7 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QUnhandledException)
+16 (int (*)(...))QUnhandledException::~QUnhandledException
+24 (int (*)(...))QUnhandledException::~QUnhandledException
+32 (int (*)(...))std::exception::what
+40 (int (*)(...))QUnhandledException::raise
+48 (int (*)(...))QUnhandledException::clone
+
+Class QUnhandledException
+ size=8 align=8
+ base size=8 base align=8
+QUnhandledException (0x0x7ff783ade208) 0 nearly-empty
+ vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16)
+ QException (0x0x7ff783ade270) 0 nearly-empty
+ primary-for QUnhandledException (0x0x7ff783ade208)
+ std::exception (0x0x7ff783ad2ae0) 0 nearly-empty
+ primary-for QException (0x0x7ff783ade270)
+
+Class QtPrivate::ExceptionHolder
+ size=8 align=8
+ base size=8 base align=8
+QtPrivate::ExceptionHolder (0x0x7ff783ad2b40) 0
+
+Class QtPrivate::ExceptionStore
+ size=8 align=8
+ base size=8 base align=8
+QtPrivate::ExceptionStore (0x0x7ff783ad2c00) 0
+
+Vtable for QFactoryInterface
+QFactoryInterface::_ZTV17QFactoryInterface: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI17QFactoryInterface)
+16 0
+24 0
+32 (int (*)(...))__cxa_pure_virtual
+
+Class QFactoryInterface
+ size=8 align=8
+ base size=8 base align=8
+QFactoryInterface (0x0x7ff783ad2c60) 0 nearly-empty
+ vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16)
+
+Class QFileSelector::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QFileSelector::QPrivateSignal (0x0x7ff783ad2ea0) 0 empty
+
+Vtable for QFileSelector
+QFileSelector::_ZTV13QFileSelector: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QFileSelector)
+16 (int (*)(...))QFileSelector::metaObject
+24 (int (*)(...))QFileSelector::qt_metacast
+32 (int (*)(...))QFileSelector::qt_metacall
+40 (int (*)(...))QFileSelector::~QFileSelector
+48 (int (*)(...))QFileSelector::~QFileSelector
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QFileSelector
+ size=16 align=8
+ base size=16 base align=8
+QFileSelector (0x0x7ff783ade2d8) 0
+ vptr=((& QFileSelector::_ZTV13QFileSelector) + 16)
+ QObject (0x0x7ff783ad2e40) 0
+ primary-for QFileSelector (0x0x7ff783ade2d8)
+
+Class QFileSystemWatcher::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QFileSystemWatcher::QPrivateSignal (0x0x7ff78371f120) 0 empty
+
+Vtable for QFileSystemWatcher
+QFileSystemWatcher::_ZTV18QFileSystemWatcher: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QFileSystemWatcher)
+16 (int (*)(...))QFileSystemWatcher::metaObject
+24 (int (*)(...))QFileSystemWatcher::qt_metacast
+32 (int (*)(...))QFileSystemWatcher::qt_metacall
+40 (int (*)(...))QFileSystemWatcher::~QFileSystemWatcher
+48 (int (*)(...))QFileSystemWatcher::~QFileSystemWatcher
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QFileSystemWatcher
+ size=16 align=8
+ base size=16 base align=8
+QFileSystemWatcher (0x0x7ff783ade340) 0
+ vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16)
+ QObject (0x0x7ff78371f0c0) 0
+ primary-for QFileSystemWatcher (0x0x7ff783ade340)
+
+Class QFinalState::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QFinalState::QPrivateSignal (0x0x7ff78371f360) 0 empty
+
+Vtable for QFinalState
+QFinalState::_ZTV11QFinalState: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QFinalState)
+16 (int (*)(...))QFinalState::metaObject
+24 (int (*)(...))QFinalState::qt_metacast
+32 (int (*)(...))QFinalState::qt_metacall
+40 (int (*)(...))QFinalState::~QFinalState
+48 (int (*)(...))QFinalState::~QFinalState
+56 (int (*)(...))QFinalState::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QFinalState::onEntry
+120 (int (*)(...))QFinalState::onExit
+
+Class QFinalState
+ size=16 align=8
+ base size=16 base align=8
+QFinalState (0x0x7ff783ade3a8) 0
+ vptr=((& QFinalState::_ZTV11QFinalState) + 16)
+ QAbstractState (0x0x7ff783ade410) 0
+ primary-for QFinalState (0x0x7ff783ade3a8)
+ QObject (0x0x7ff78371f300) 0
+ primary-for QAbstractState (0x0x7ff783ade410)
+
+Vtable for QRunnable
+QRunnable::_ZTV9QRunnable: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QRunnable)
+16 (int (*)(...))__cxa_pure_virtual
+24 0
+32 0
+
+Class QRunnable
+ size=16 align=8
+ base size=12 base align=8
+QRunnable (0x0x7ff78371f540) 0
+ vptr=((& QRunnable::_ZTV9QRunnable) + 16)
+
+Class QBasicMutex
+ size=8 align=8
+ base size=8 base align=8
+QBasicMutex (0x0x7ff78371f7e0) 0
+
+Class QMutex
+ size=8 align=8
+ base size=8 base align=8
+QMutex (0x0x7ff783ade4e0) 0
+ QBasicMutex (0x0x7ff7837ae480) 0
+
+Class QMutexLocker
+ size=8 align=8
+ base size=8 base align=8
+QMutexLocker (0x0x7ff7837ae6c0) 0
+
+Class QtPrivate::ResultItem
+ size=16 align=8
+ base size=16 base align=8
+QtPrivate::ResultItem (0x0x7ff7837aeb40) 0
+
+Class QtPrivate::ResultIteratorBase
+ size=16 align=8
+ base size=12 base align=8
+QtPrivate::ResultIteratorBase (0x0x7ff7837d8180) 0
+
+Vtable for QtPrivate::ResultStoreBase
+QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN9QtPrivate15ResultStoreBaseE)
+16 (int (*)(...))QtPrivate::ResultStoreBase::~ResultStoreBase
+24 (int (*)(...))QtPrivate::ResultStoreBase::~ResultStoreBase
+
+Class QtPrivate::ResultStoreBase
+ size=48 align=8
+ base size=44 base align=8
+QtPrivate::ResultStoreBase (0x0x7ff7837d8360) 0
+ vptr=((& QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE) + 16)
+
+Vtable for QFutureInterfaceBase
+QFutureInterfaceBase::_ZTV20QFutureInterfaceBase: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI20QFutureInterfaceBase)
+16 (int (*)(...))QFutureInterfaceBase::~QFutureInterfaceBase
+24 (int (*)(...))QFutureInterfaceBase::~QFutureInterfaceBase
+
+Class QFutureInterfaceBase
+ size=16 align=8
+ base size=16 base align=8
+QFutureInterfaceBase (0x0x7ff78384eb40) 0
+ vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16)
+
+Class QFutureWatcherBase::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QFutureWatcherBase::QPrivateSignal (0x0x7ff7838ede40) 0 empty
+
+Vtable for QFutureWatcherBase
+QFutureWatcherBase::_ZTV18QFutureWatcherBase: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QFutureWatcherBase)
+16 (int (*)(...))QFutureWatcherBase::metaObject
+24 (int (*)(...))QFutureWatcherBase::qt_metacast
+32 (int (*)(...))QFutureWatcherBase::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QFutureWatcherBase::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QFutureWatcherBase::connectNotify
+104 (int (*)(...))QFutureWatcherBase::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))__cxa_pure_virtual
+
+Class QFutureWatcherBase
+ size=16 align=8
+ base size=16 base align=8
+QFutureWatcherBase (0x0x7ff783884af8) 0
+ vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16)
+ QObject (0x0x7ff7838edde0) 0
+ primary-for QFutureWatcherBase (0x0x7ff783884af8)
+
+Class QHistoryState::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QHistoryState::QPrivateSignal (0x0x7ff7835371e0) 0 empty
+
+Vtable for QHistoryState
+QHistoryState::_ZTV13QHistoryState: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QHistoryState)
+16 (int (*)(...))QHistoryState::metaObject
+24 (int (*)(...))QHistoryState::qt_metacast
+32 (int (*)(...))QHistoryState::qt_metacall
+40 (int (*)(...))QHistoryState::~QHistoryState
+48 (int (*)(...))QHistoryState::~QHistoryState
+56 (int (*)(...))QHistoryState::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QHistoryState::onEntry
+120 (int (*)(...))QHistoryState::onExit
+
+Class QHistoryState
+ size=16 align=8
+ base size=16 base align=8
+QHistoryState (0x0x7ff783534340) 0
+ vptr=((& QHistoryState::_ZTV13QHistoryState) + 16)
+ QAbstractState (0x0x7ff7835343a8) 0
+ primary-for QHistoryState (0x0x7ff783534340)
+ QObject (0x0x7ff783537180) 0
+ primary-for QAbstractState (0x0x7ff7835343a8)
+
+Class QIdentityProxyModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QIdentityProxyModel::QPrivateSignal (0x0x7ff7835374e0) 0 empty
+
+Vtable for QIdentityProxyModel
+QIdentityProxyModel::_ZTV19QIdentityProxyModel: 53 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QIdentityProxyModel)
+16 (int (*)(...))QIdentityProxyModel::metaObject
+24 (int (*)(...))QIdentityProxyModel::qt_metacast
+32 (int (*)(...))QIdentityProxyModel::qt_metacall
+40 (int (*)(...))QIdentityProxyModel::~QIdentityProxyModel
+48 (int (*)(...))QIdentityProxyModel::~QIdentityProxyModel
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QIdentityProxyModel::index
+120 (int (*)(...))QIdentityProxyModel::parent
+128 (int (*)(...))QIdentityProxyModel::sibling
+136 (int (*)(...))QIdentityProxyModel::rowCount
+144 (int (*)(...))QIdentityProxyModel::columnCount
+152 (int (*)(...))QAbstractProxyModel::hasChildren
+160 (int (*)(...))QAbstractProxyModel::data
+168 (int (*)(...))QAbstractProxyModel::setData
+176 (int (*)(...))QIdentityProxyModel::headerData
+184 (int (*)(...))QAbstractProxyModel::setHeaderData
+192 (int (*)(...))QAbstractProxyModel::itemData
+200 (int (*)(...))QAbstractProxyModel::setItemData
+208 (int (*)(...))QAbstractProxyModel::mimeTypes
+216 (int (*)(...))QAbstractProxyModel::mimeData
+224 (int (*)(...))QAbstractProxyModel::canDropMimeData
+232 (int (*)(...))QIdentityProxyModel::dropMimeData
+240 (int (*)(...))QAbstractProxyModel::supportedDropActions
+248 (int (*)(...))QAbstractProxyModel::supportedDragActions
+256 (int (*)(...))QIdentityProxyModel::insertRows
+264 (int (*)(...))QIdentityProxyModel::insertColumns
+272 (int (*)(...))QIdentityProxyModel::removeRows
+280 (int (*)(...))QIdentityProxyModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractProxyModel::fetchMore
+312 (int (*)(...))QAbstractProxyModel::canFetchMore
+320 (int (*)(...))QAbstractProxyModel::flags
+328 (int (*)(...))QAbstractProxyModel::sort
+336 (int (*)(...))QAbstractProxyModel::buddy
+344 (int (*)(...))QIdentityProxyModel::match
+352 (int (*)(...))QAbstractProxyModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractProxyModel::submit
+376 (int (*)(...))QAbstractProxyModel::revert
+384 (int (*)(...))QIdentityProxyModel::setSourceModel
+392 (int (*)(...))QIdentityProxyModel::mapToSource
+400 (int (*)(...))QIdentityProxyModel::mapFromSource
+408 (int (*)(...))QIdentityProxyModel::mapSelectionToSource
+416 (int (*)(...))QIdentityProxyModel::mapSelectionFromSource
+
+Class QIdentityProxyModel
+ size=16 align=8
+ base size=16 base align=8
+QIdentityProxyModel (0x0x7ff783534410) 0
+ vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16)
+ QAbstractProxyModel (0x0x7ff783534478) 0
+ primary-for QIdentityProxyModel (0x0x7ff783534410)
+ QAbstractItemModel (0x0x7ff7835344e0) 0
+ primary-for QAbstractProxyModel (0x0x7ff783534478)
+ QObject (0x0x7ff783537480) 0
+ primary-for QAbstractItemModel (0x0x7ff7835344e0)
+
+Class QItemSelectionRange
+ size=16 align=8
+ base size=16 base align=8
+QItemSelectionRange (0x0x7ff7835376c0) 0
+
+Class QItemSelectionModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QItemSelectionModel::QPrivateSignal (0x0x7ff783621000) 0 empty
+
+Vtable for QItemSelectionModel
+QItemSelectionModel::_ZTV19QItemSelectionModel: 20 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QItemSelectionModel)
+16 (int (*)(...))QItemSelectionModel::metaObject
+24 (int (*)(...))QItemSelectionModel::qt_metacast
+32 (int (*)(...))QItemSelectionModel::qt_metacall
+40 (int (*)(...))QItemSelectionModel::~QItemSelectionModel
+48 (int (*)(...))QItemSelectionModel::~QItemSelectionModel
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QItemSelectionModel::setCurrentIndex
+120 (int (*)(...))QItemSelectionModel::select
+128 (int (*)(...))QItemSelectionModel::select
+136 (int (*)(...))QItemSelectionModel::clear
+144 (int (*)(...))QItemSelectionModel::reset
+152 (int (*)(...))QItemSelectionModel::clearCurrentIndex
+
+Class QItemSelectionModel
+ size=16 align=8
+ base size=16 base align=8
+QItemSelectionModel (0x0x7ff783605e38) 0
+ vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16)
+ QObject (0x0x7ff783602f60) 0
+ primary-for QItemSelectionModel (0x0x7ff783605e38)
+
+Class QItemSelection
+ size=8 align=8
+ base size=8 base align=8
+QItemSelection (0x0x7ff783686000) 0
+ QList<QItemSelectionRange> (0x0x7ff783686068) 0
+ QListSpecialMethods<QItemSelectionRange> (0x0x7ff783621ae0) 0 empty
+
+Class QJsonValue
+ size=24 align=8
+ base size=20 base align=8
+QJsonValue (0x0x7ff7836ca420) 0
+
+Class QJsonValueRef
+ size=16 align=8
+ base size=12 base align=8
+QJsonValueRef (0x0x7ff78341f600) 0
+
+Class QJsonValuePtr
+ size=24 align=8
+ base size=24 base align=8
+QJsonValuePtr (0x0x7ff7834725a0) 0
+
+Class QJsonValueRefPtr
+ size=16 align=8
+ base size=16 base align=8
+QJsonValueRefPtr (0x0x7ff783472840) 0
+
+Class QJsonArray::iterator
+ size=16 align=8
+ base size=12 base align=8
+QJsonArray::iterator (0x0x7ff7834b2ba0) 0
+
+Class QJsonArray::const_iterator
+ size=16 align=8
+ base size=12 base align=8
+QJsonArray::const_iterator (0x0x7ff7834b2c00) 0
+
+Class QJsonArray
+ size=16 align=8
+ base size=16 base align=8
+QJsonArray (0x0x7ff7834b2b40) 0
+
+Class QJsonParseError
+ size=8 align=4
+ base size=8 base align=4
+QJsonParseError (0x0x7ff7831deae0) 0
+
+Class QJsonDocument
+ size=8 align=8
+ base size=8 base align=8
+QJsonDocument (0x0x7ff7831deb40) 0
+
+Class QJsonObject::iterator
+ size=16 align=8
+ base size=12 base align=8
+QJsonObject::iterator (0x0x7ff78324f360) 0
+
+Class QJsonObject::const_iterator
+ size=16 align=8
+ base size=12 base align=8
+QJsonObject::const_iterator (0x0x7ff78324f3c0) 0
+
+Class QJsonObject
+ size=16 align=8
+ base size=16 base align=8
+QJsonObject (0x0x7ff78324f300) 0
+
+Class QLibrary::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QLibrary::QPrivateSignal (0x0x7ff782f61720) 0 empty
+
+Vtable for QLibrary
+QLibrary::_ZTV8QLibrary: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI8QLibrary)
+16 (int (*)(...))QLibrary::metaObject
+24 (int (*)(...))QLibrary::qt_metacast
+32 (int (*)(...))QLibrary::qt_metacall
+40 (int (*)(...))QLibrary::~QLibrary
+48 (int (*)(...))QLibrary::~QLibrary
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QLibrary
+ size=32 align=8
+ base size=25 base align=8
+QLibrary (0x0x7ff782f6b0d0) 0
+ vptr=((& QLibrary::_ZTV8QLibrary) + 16)
+ QObject (0x0x7ff782f616c0) 0
+ primary-for QLibrary (0x0x7ff782f6b0d0)
+
+Class QVersionNumber::SegmentStorage
+ size=8 align=8
+ base size=8 base align=8
+QVersionNumber::SegmentStorage (0x0x7ff782fad5a0) 0
+
+Class QVersionNumber
+ size=8 align=8
+ base size=8 base align=8
+QVersionNumber (0x0x7ff782fad0c0) 0
+
+Class QLibraryInfo
+ size=1 align=1
+ base size=0 base align=1
+QLibraryInfo (0x0x7ff783044cc0) 0 empty
+
+Class QPoint
+ size=8 align=4
+ base size=8 base align=4
+QPoint (0x0x7ff783044d20) 0
+
+Class QPointF
+ size=16 align=8
+ base size=16 base align=8
+QPointF (0x0x7ff7830b3b40) 0
+
+Class QLine
+ size=16 align=4
+ base size=16 base align=4
+QLine (0x0x7ff782d27cc0) 0
+
+Class QLineF
+ size=32 align=8
+ base size=32 base align=8
+QLineF (0x0x7ff782dbb0c0) 0
+
+Class QLinkedListData
+ size=32 align=8
+ base size=25 base align=8
+QLinkedListData (0x0x7ff782e37360) 0
+
+Class QLockFile
+ size=8 align=8
+ base size=8 base align=8
+QLockFile (0x0x7ff782ed54e0) 0
+
+Class QLoggingCategory::AtomicBools
+ size=4 align=1
+ base size=4 base align=1
+QLoggingCategory::AtomicBools (0x0x7ff782ed5720) 0
+
+Class QLoggingCategory
+ size=24 align=8
+ base size=24 base align=8
+QLoggingCategory (0x0x7ff782ed56c0) 0
+
+Class QMargins
+ size=16 align=4
+ base size=16 base align=4
+QMargins (0x0x7ff782ed5b40) 0
+
+Class QMarginsF
+ size=32 align=8
+ base size=32 base align=8
+QMarginsF (0x0x7ff782b87a80) 0
+
+Class QMessageAuthenticationCode
+ size=8 align=8
+ base size=8 base align=8
+QMessageAuthenticationCode (0x0x7ff7829f82a0) 0
+
+Class QMetaMethod
+ size=16 align=8
+ base size=12 base align=8
+QMetaMethod (0x0x7ff7829f8300) 0
+
+Class QMetaEnum
+ size=16 align=8
+ base size=12 base align=8
+QMetaEnum (0x0x7ff782a5eb40) 0
+
+Class QMetaProperty
+ size=32 align=8
+ base size=32 base align=8
+QMetaProperty (0x0x7ff782a9ed80) 0
+
+Class QMetaClassInfo
+ size=16 align=8
+ base size=12 base align=8
+QMetaClassInfo (0x0x7ff782a9eea0) 0
+
+Class QMimeData::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QMimeData::QPrivateSignal (0x0x7ff782afb480) 0 empty
+
+Vtable for QMimeData
+QMimeData::_ZTV9QMimeData: 17 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QMimeData)
+16 (int (*)(...))QMimeData::metaObject
+24 (int (*)(...))QMimeData::qt_metacast
+32 (int (*)(...))QMimeData::qt_metacall
+40 (int (*)(...))QMimeData::~QMimeData
+48 (int (*)(...))QMimeData::~QMimeData
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QMimeData::hasFormat
+120 (int (*)(...))QMimeData::formats
+128 (int (*)(...))QMimeData::retrieveData
+
+Class QMimeData
+ size=16 align=8
+ base size=16 base align=8
+QMimeData (0x0x7ff782aebd00) 0
+ vptr=((& QMimeData::_ZTV9QMimeData) + 16)
+ QObject (0x0x7ff782afb420) 0
+ primary-for QMimeData (0x0x7ff782aebd00)
+
+Class QMimeType
+ size=8 align=8
+ base size=8 base align=8
+QMimeType (0x0x7ff782afb660) 0
+
+Class QMimeDatabase
+ size=8 align=8
+ base size=8 base align=8
+QMimeDatabase (0x0x7ff78275b780) 0
+
+Class QObjectCleanupHandler::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QObjectCleanupHandler::QPrivateSignal (0x0x7ff78275b840) 0 empty
+
+Vtable for QObjectCleanupHandler
+QObjectCleanupHandler::_ZTV21QObjectCleanupHandler: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI21QObjectCleanupHandler)
+16 (int (*)(...))QObjectCleanupHandler::metaObject
+24 (int (*)(...))QObjectCleanupHandler::qt_metacast
+32 (int (*)(...))QObjectCleanupHandler::qt_metacall
+40 (int (*)(...))QObjectCleanupHandler::~QObjectCleanupHandler
+48 (int (*)(...))QObjectCleanupHandler::~QObjectCleanupHandler
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QObjectCleanupHandler
+ size=24 align=8
+ base size=24 base align=8
+QObjectCleanupHandler (0x0x7ff782767068) 0
+ vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16)
+ QObject (0x0x7ff78275b7e0) 0
+ primary-for QObjectCleanupHandler (0x0x7ff782767068)
+
+Class QOperatingSystemVersion
+ size=16 align=4
+ base size=16 base align=4
+QOperatingSystemVersion (0x0x7ff78275b960) 0
+
+Class QParallelAnimationGroup::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QParallelAnimationGroup::QPrivateSignal (0x0x7ff7827e7120) 0 empty
+
+Vtable for QParallelAnimationGroup
+QParallelAnimationGroup::_ZTV23QParallelAnimationGroup: 18 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI23QParallelAnimationGroup)
+16 (int (*)(...))QParallelAnimationGroup::metaObject
+24 (int (*)(...))QParallelAnimationGroup::qt_metacast
+32 (int (*)(...))QParallelAnimationGroup::qt_metacall
+40 (int (*)(...))QParallelAnimationGroup::~QParallelAnimationGroup
+48 (int (*)(...))QParallelAnimationGroup::~QParallelAnimationGroup
+56 (int (*)(...))QParallelAnimationGroup::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QParallelAnimationGroup::duration
+120 (int (*)(...))QParallelAnimationGroup::updateCurrentTime
+128 (int (*)(...))QParallelAnimationGroup::updateState
+136 (int (*)(...))QParallelAnimationGroup::updateDirection
+
+Class QParallelAnimationGroup
+ size=16 align=8
+ base size=16 base align=8
+QParallelAnimationGroup (0x0x7ff7827de8f0) 0
+ vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16)
+ QAnimationGroup (0x0x7ff7827de958) 0
+ primary-for QParallelAnimationGroup (0x0x7ff7827de8f0)
+ QAbstractAnimation (0x0x7ff7827de9c0) 0
+ primary-for QAnimationGroup (0x0x7ff7827de958)
+ QObject (0x0x7ff7827e70c0) 0
+ primary-for QAbstractAnimation (0x0x7ff7827de9c0)
+
+Class QPauseAnimation::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QPauseAnimation::QPrivateSignal (0x0x7ff7827e7360) 0 empty
+
+Vtable for QPauseAnimation
+QPauseAnimation::_ZTV15QPauseAnimation: 18 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI15QPauseAnimation)
+16 (int (*)(...))QPauseAnimation::metaObject
+24 (int (*)(...))QPauseAnimation::qt_metacast
+32 (int (*)(...))QPauseAnimation::qt_metacall
+40 (int (*)(...))QPauseAnimation::~QPauseAnimation
+48 (int (*)(...))QPauseAnimation::~QPauseAnimation
+56 (int (*)(...))QPauseAnimation::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QPauseAnimation::duration
+120 (int (*)(...))QPauseAnimation::updateCurrentTime
+128 (int (*)(...))QAbstractAnimation::updateState
+136 (int (*)(...))QAbstractAnimation::updateDirection
+
+Class QPauseAnimation
+ size=16 align=8
+ base size=16 base align=8
+QPauseAnimation (0x0x7ff7827dea28) 0
+ vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16)
+ QAbstractAnimation (0x0x7ff7827dea90) 0
+ primary-for QPauseAnimation (0x0x7ff7827dea28)
+ QObject (0x0x7ff7827e7300) 0
+ primary-for QAbstractAnimation (0x0x7ff7827dea90)
+
+Class QStaticPlugin
+ size=16 align=8
+ base size=16 base align=8
+QStaticPlugin (0x0x7ff7827e7f60) 0
+
+Class QPluginLoader::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QPluginLoader::QPrivateSignal (0x0x7ff78285e120) 0 empty
+
+Vtable for QPluginLoader
+QPluginLoader::_ZTV13QPluginLoader: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QPluginLoader)
+16 (int (*)(...))QPluginLoader::metaObject
+24 (int (*)(...))QPluginLoader::qt_metacast
+32 (int (*)(...))QPluginLoader::qt_metacall
+40 (int (*)(...))QPluginLoader::~QPluginLoader
+48 (int (*)(...))QPluginLoader::~QPluginLoader
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QPluginLoader
+ size=32 align=8
+ base size=25 base align=8
+QPluginLoader (0x0x7ff782849dd0) 0
+ vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16)
+ QObject (0x0x7ff78285e0c0) 0
+ primary-for QPluginLoader (0x0x7ff782849dd0)
+
+Class QProcessEnvironment
+ size=8 align=8
+ base size=8 base align=8
+QProcessEnvironment (0x0x7ff78285e240) 0
+
+Class QProcess::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QProcess::QPrivateSignal (0x0x7ff7828ba8a0) 0 empty
+
+Vtable for QProcess
+QProcess::_ZTV8QProcess: 31 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI8QProcess)
+16 (int (*)(...))QProcess::metaObject
+24 (int (*)(...))QProcess::qt_metacast
+32 (int (*)(...))QProcess::qt_metacall
+40 (int (*)(...))QProcess::~QProcess
+48 (int (*)(...))QProcess::~QProcess
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QProcess::isSequential
+120 (int (*)(...))QProcess::open
+128 (int (*)(...))QProcess::close
+136 (int (*)(...))QIODevice::pos
+144 (int (*)(...))QIODevice::size
+152 (int (*)(...))QIODevice::seek
+160 (int (*)(...))QProcess::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QProcess::bytesAvailable
+184 (int (*)(...))QProcess::bytesToWrite
+192 (int (*)(...))QProcess::canReadLine
+200 (int (*)(...))QProcess::waitForReadyRead
+208 (int (*)(...))QProcess::waitForBytesWritten
+216 (int (*)(...))QProcess::readData
+224 (int (*)(...))QIODevice::readLineData
+232 (int (*)(...))QProcess::writeData
+240 (int (*)(...))QProcess::setupChildProcess
+
+Class QProcess
+ size=16 align=8
+ base size=16 base align=8
+QProcess (0x0x7ff7828b9a28) 0
+ vptr=((& QProcess::_ZTV8QProcess) + 16)
+ QIODevice (0x0x7ff7828b9a90) 0
+ primary-for QProcess (0x0x7ff7828b9a28)
+ QObject (0x0x7ff7828ba840) 0
+ primary-for QIODevice (0x0x7ff7828b9a90)
+
+Class QVariantAnimation::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QVariantAnimation::QPrivateSignal (0x0x7ff7828baf60) 0 empty
+
+Vtable for QVariantAnimation
+QVariantAnimation::_ZTV17QVariantAnimation: 20 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI17QVariantAnimation)
+16 (int (*)(...))QVariantAnimation::metaObject
+24 (int (*)(...))QVariantAnimation::qt_metacast
+32 (int (*)(...))QVariantAnimation::qt_metacall
+40 (int (*)(...))QVariantAnimation::~QVariantAnimation
+48 (int (*)(...))QVariantAnimation::~QVariantAnimation
+56 (int (*)(...))QVariantAnimation::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QVariantAnimation::duration
+120 (int (*)(...))QVariantAnimation::updateCurrentTime
+128 (int (*)(...))QVariantAnimation::updateState
+136 (int (*)(...))QAbstractAnimation::updateDirection
+144 (int (*)(...))QVariantAnimation::updateCurrentValue
+152 (int (*)(...))QVariantAnimation::interpolated
+
+Class QVariantAnimation
+ size=16 align=8
+ base size=16 base align=8
+QVariantAnimation (0x0x7ff7828b9af8) 0
+ vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16)
+ QAbstractAnimation (0x0x7ff7828b9b60) 0
+ primary-for QVariantAnimation (0x0x7ff7828b9af8)
+ QObject (0x0x7ff7828baf00) 0
+ primary-for QAbstractAnimation (0x0x7ff7828b9b60)
+
+Class QPropertyAnimation::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QPropertyAnimation::QPrivateSignal (0x0x7ff78290a240) 0 empty
+
+Vtable for QPropertyAnimation
+QPropertyAnimation::_ZTV18QPropertyAnimation: 20 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QPropertyAnimation)
+16 (int (*)(...))QPropertyAnimation::metaObject
+24 (int (*)(...))QPropertyAnimation::qt_metacast
+32 (int (*)(...))QPropertyAnimation::qt_metacall
+40 (int (*)(...))QPropertyAnimation::~QPropertyAnimation
+48 (int (*)(...))QPropertyAnimation::~QPropertyAnimation
+56 (int (*)(...))QPropertyAnimation::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QVariantAnimation::duration
+120 (int (*)(...))QVariantAnimation::updateCurrentTime
+128 (int (*)(...))QPropertyAnimation::updateState
+136 (int (*)(...))QAbstractAnimation::updateDirection
+144 (int (*)(...))QPropertyAnimation::updateCurrentValue
+152 (int (*)(...))QVariantAnimation::interpolated
+
+Class QPropertyAnimation
+ size=16 align=8
+ base size=16 base align=8
+QPropertyAnimation (0x0x7ff7828b9c30) 0
+ vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16)
+ QVariantAnimation (0x0x7ff7828b9c98) 0
+ primary-for QPropertyAnimation (0x0x7ff7828b9c30)
+ QAbstractAnimation (0x0x7ff7828b9d00) 0
+ primary-for QVariantAnimation (0x0x7ff7828b9c98)
+ QObject (0x0x7ff78290a1e0) 0
+ primary-for QAbstractAnimation (0x0x7ff7828b9d00)
+
+Class std::random_device
+ size=5000 align=8
+ base size=5000 base align=8
+std::random_device (0x0x7ff78257f960) 0
+
+Class std::bernoulli_distribution::param_type
+ size=8 align=8
+ base size=8 base align=8
+std::bernoulli_distribution::param_type (0x0x7ff78268e6c0) 0
+
+Class std::bernoulli_distribution
+ size=8 align=8
+ base size=8 base align=8
+std::bernoulli_distribution (0x0x7ff78268e660) 0
+
+Class std::seed_seq
+ size=24 align=8
+ base size=24 base align=8
+std::seed_seq (0x0x7ff782478420) 0
+
+Class QRandomGenerator::Storage
+ size=2504 align=8
+ base size=2504 base align=8
+QRandomGenerator::Storage (0x0x7ff7822b30c0) 0
+
+Class QRandomGenerator
+ size=2512 align=8
+ base size=2512 base align=8
+QRandomGenerator (0x0x7ff7822b3060) 0
+
+Class QRandomGenerator64
+ size=2512 align=8
+ base size=2512 base align=8
+QRandomGenerator64 (0x0x7ff7823159c0) 0
+ QRandomGenerator (0x0x7ff781eaaba0) 0
+
+Class QReadWriteLock
+ size=8 align=8
+ base size=8 base align=8
+QReadWriteLock (0x0x7ff781ed1780) 0
+
+Class QReadLocker
+ size=8 align=8
+ base size=8 base align=8
+QReadLocker (0x0x7ff781ed1a20) 0
+
+Class QWriteLocker
+ size=8 align=8
+ base size=8 base align=8
+QWriteLocker (0x0x7ff781ed1f00) 0
+
+Class QSize
+ size=8 align=4
+ base size=8 base align=4
+QSize (0x0x7ff781f52420) 0
+
+Class QSizeF
+ size=16 align=8
+ base size=16 base align=8
+QSizeF (0x0x7ff781fc2240) 0
+
+Class QRect
+ size=16 align=4
+ base size=16 base align=4
+QRect (0x0x7ff78203d1e0) 0
+
+Class QRectF
+ size=32 align=8
+ base size=32 base align=8
+QRectF (0x0x7ff781cf9240) 0
+
+Class QResource
+ size=8 align=8
+ base size=8 base align=8
+QResource (0x0x7ff781db1360) 0
+
+Class QSaveFile::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSaveFile::QPrivateSignal (0x0x7ff781db1600) 0 empty
+
+Vtable for QSaveFile
+QSaveFile::_ZTV9QSaveFile: 34 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QSaveFile)
+16 (int (*)(...))QSaveFile::metaObject
+24 (int (*)(...))QSaveFile::qt_metacast
+32 (int (*)(...))QSaveFile::qt_metacall
+40 (int (*)(...))QSaveFile::~QSaveFile
+48 (int (*)(...))QSaveFile::~QSaveFile
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QFileDevice::isSequential
+120 (int (*)(...))QSaveFile::open
+128 (int (*)(...))QSaveFile::close
+136 (int (*)(...))QFileDevice::pos
+144 (int (*)(...))QFileDevice::size
+152 (int (*)(...))QFileDevice::seek
+160 (int (*)(...))QFileDevice::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QIODevice::bytesAvailable
+184 (int (*)(...))QIODevice::bytesToWrite
+192 (int (*)(...))QIODevice::canReadLine
+200 (int (*)(...))QIODevice::waitForReadyRead
+208 (int (*)(...))QIODevice::waitForBytesWritten
+216 (int (*)(...))QFileDevice::readData
+224 (int (*)(...))QFileDevice::readLineData
+232 (int (*)(...))QSaveFile::writeData
+240 (int (*)(...))QSaveFile::fileName
+248 (int (*)(...))QFileDevice::resize
+256 (int (*)(...))QFileDevice::permissions
+264 (int (*)(...))QFileDevice::setPermissions
+
+Class QSaveFile
+ size=16 align=8
+ base size=16 base align=8
+QSaveFile (0x0x7ff781d623a8) 0
+ vptr=((& QSaveFile::_ZTV9QSaveFile) + 16)
+ QFileDevice (0x0x7ff781d62410) 0
+ primary-for QSaveFile (0x0x7ff781d623a8)
+ QIODevice (0x0x7ff781d62478) 0
+ primary-for QFileDevice (0x0x7ff781d62410)
+ QObject (0x0x7ff781db15a0) 0
+ primary-for QIODevice (0x0x7ff781d62478)
+
+Class QSemaphore
+ size=8 align=8
+ base size=8 base align=8
+QSemaphore (0x0x7ff781db1c00) 0
+
+Class QSemaphoreReleaser
+ size=16 align=8
+ base size=12 base align=8
+QSemaphoreReleaser (0x0x7ff781db1d80) 0
+
+Class QSequentialAnimationGroup::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSequentialAnimationGroup::QPrivateSignal (0x0x7ff781b06060) 0 empty
+
+Vtable for QSequentialAnimationGroup
+QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup: 18 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI25QSequentialAnimationGroup)
+16 (int (*)(...))QSequentialAnimationGroup::metaObject
+24 (int (*)(...))QSequentialAnimationGroup::qt_metacast
+32 (int (*)(...))QSequentialAnimationGroup::qt_metacall
+40 (int (*)(...))QSequentialAnimationGroup::~QSequentialAnimationGroup
+48 (int (*)(...))QSequentialAnimationGroup::~QSequentialAnimationGroup
+56 (int (*)(...))QSequentialAnimationGroup::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QSequentialAnimationGroup::duration
+120 (int (*)(...))QSequentialAnimationGroup::updateCurrentTime
+128 (int (*)(...))QSequentialAnimationGroup::updateState
+136 (int (*)(...))QSequentialAnimationGroup::updateDirection
+
+Class QSequentialAnimationGroup
+ size=16 align=8
+ base size=16 base align=8
+QSequentialAnimationGroup (0x0x7ff781b031a0) 0
+ vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16)
+ QAnimationGroup (0x0x7ff781b03208) 0
+ primary-for QSequentialAnimationGroup (0x0x7ff781b031a0)
+ QAbstractAnimation (0x0x7ff781b03270) 0
+ primary-for QAnimationGroup (0x0x7ff781b03208)
+ QObject (0x0x7ff781b06000) 0
+ primary-for QAbstractAnimation (0x0x7ff781b03270)
+
+Class QSettings::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSettings::QPrivateSignal (0x0x7ff781b062a0) 0 empty
+
+Vtable for QSettings
+QSettings::_ZTV9QSettings: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QSettings)
+16 (int (*)(...))QSettings::metaObject
+24 (int (*)(...))QSettings::qt_metacast
+32 (int (*)(...))QSettings::qt_metacall
+40 (int (*)(...))QSettings::~QSettings
+48 (int (*)(...))QSettings::~QSettings
+56 (int (*)(...))QSettings::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QSettings
+ size=16 align=8
+ base size=16 base align=8
+QSettings (0x0x7ff781b032d8) 0
+ vptr=((& QSettings::_ZTV9QSettings) + 16)
+ QObject (0x0x7ff781b06240) 0
+ primary-for QSettings (0x0x7ff781b032d8)
+
+Class QSharedMemory::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSharedMemory::QPrivateSignal (0x0x7ff781b06720) 0 empty
+
+Vtable for QSharedMemory
+QSharedMemory::_ZTV13QSharedMemory: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QSharedMemory)
+16 (int (*)(...))QSharedMemory::metaObject
+24 (int (*)(...))QSharedMemory::qt_metacast
+32 (int (*)(...))QSharedMemory::qt_metacall
+40 (int (*)(...))QSharedMemory::~QSharedMemory
+48 (int (*)(...))QSharedMemory::~QSharedMemory
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QSharedMemory
+ size=16 align=8
+ base size=16 base align=8
+QSharedMemory (0x0x7ff781b03340) 0
+ vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16)
+ QObject (0x0x7ff781b066c0) 0
+ primary-for QSharedMemory (0x0x7ff781b03340)
+
+Class QSignalMapper::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSignalMapper::QPrivateSignal (0x0x7ff781b06960) 0 empty
+
+Vtable for QSignalMapper
+QSignalMapper::_ZTV13QSignalMapper: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QSignalMapper)
+16 (int (*)(...))QSignalMapper::metaObject
+24 (int (*)(...))QSignalMapper::qt_metacast
+32 (int (*)(...))QSignalMapper::qt_metacall
+40 (int (*)(...))QSignalMapper::~QSignalMapper
+48 (int (*)(...))QSignalMapper::~QSignalMapper
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QSignalMapper
+ size=16 align=8
+ base size=16 base align=8
+QSignalMapper (0x0x7ff781b033a8) 0
+ vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16)
+ QObject (0x0x7ff781b06900) 0
+ primary-for QSignalMapper (0x0x7ff781b033a8)
+
+Class QSignalTransition::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSignalTransition::QPrivateSignal (0x0x7ff781b06ba0) 0 empty
+
+Vtable for QSignalTransition
+QSignalTransition::_ZTV17QSignalTransition: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI17QSignalTransition)
+16 (int (*)(...))QSignalTransition::metaObject
+24 (int (*)(...))QSignalTransition::qt_metacast
+32 (int (*)(...))QSignalTransition::qt_metacall
+40 (int (*)(...))QSignalTransition::~QSignalTransition
+48 (int (*)(...))QSignalTransition::~QSignalTransition
+56 (int (*)(...))QSignalTransition::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QSignalTransition::eventTest
+120 (int (*)(...))QSignalTransition::onTransition
+
+Class QSignalTransition
+ size=16 align=8
+ base size=16 base align=8
+QSignalTransition (0x0x7ff781b03410) 0
+ vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16)
+ QAbstractTransition (0x0x7ff781b03478) 0
+ primary-for QSignalTransition (0x0x7ff781b03410)
+ QObject (0x0x7ff781b06b40) 0
+ primary-for QAbstractTransition (0x0x7ff781b03478)
+
+Class QSocketNotifier::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSocketNotifier::QPrivateSignal (0x0x7ff781b06e40) 0 empty
+
+Vtable for QSocketNotifier
+QSocketNotifier::_ZTV15QSocketNotifier: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI15QSocketNotifier)
+16 (int (*)(...))QSocketNotifier::metaObject
+24 (int (*)(...))QSocketNotifier::qt_metacast
+32 (int (*)(...))QSocketNotifier::qt_metacall
+40 (int (*)(...))QSocketNotifier::~QSocketNotifier
+48 (int (*)(...))QSocketNotifier::~QSocketNotifier
+56 (int (*)(...))QSocketNotifier::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QSocketNotifier
+ size=16 align=8
+ base size=16 base align=8
+QSocketNotifier (0x0x7ff781b034e0) 0
+ vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16)
+ QObject (0x0x7ff781b06de0) 0
+ primary-for QSocketNotifier (0x0x7ff781b034e0)
+
+Class QSortFilterProxyModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QSortFilterProxyModel::QPrivateSignal (0x0x7ff781b7b0c0) 0 empty
+
+Vtable for QSortFilterProxyModel
+QSortFilterProxyModel::_ZTV21QSortFilterProxyModel: 56 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI21QSortFilterProxyModel)
+16 (int (*)(...))QSortFilterProxyModel::metaObject
+24 (int (*)(...))QSortFilterProxyModel::qt_metacast
+32 (int (*)(...))QSortFilterProxyModel::qt_metacall
+40 (int (*)(...))QSortFilterProxyModel::~QSortFilterProxyModel
+48 (int (*)(...))QSortFilterProxyModel::~QSortFilterProxyModel
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QSortFilterProxyModel::index
+120 (int (*)(...))QSortFilterProxyModel::parent
+128 (int (*)(...))QSortFilterProxyModel::sibling
+136 (int (*)(...))QSortFilterProxyModel::rowCount
+144 (int (*)(...))QSortFilterProxyModel::columnCount
+152 (int (*)(...))QSortFilterProxyModel::hasChildren
+160 (int (*)(...))QSortFilterProxyModel::data
+168 (int (*)(...))QSortFilterProxyModel::setData
+176 (int (*)(...))QSortFilterProxyModel::headerData
+184 (int (*)(...))QSortFilterProxyModel::setHeaderData
+192 (int (*)(...))QAbstractProxyModel::itemData
+200 (int (*)(...))QAbstractProxyModel::setItemData
+208 (int (*)(...))QSortFilterProxyModel::mimeTypes
+216 (int (*)(...))QSortFilterProxyModel::mimeData
+224 (int (*)(...))QAbstractProxyModel::canDropMimeData
+232 (int (*)(...))QSortFilterProxyModel::dropMimeData
+240 (int (*)(...))QSortFilterProxyModel::supportedDropActions
+248 (int (*)(...))QAbstractProxyModel::supportedDragActions
+256 (int (*)(...))QSortFilterProxyModel::insertRows
+264 (int (*)(...))QSortFilterProxyModel::insertColumns
+272 (int (*)(...))QSortFilterProxyModel::removeRows
+280 (int (*)(...))QSortFilterProxyModel::removeColumns
+288 (int (*)(...))QAbstractItemModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QSortFilterProxyModel::fetchMore
+312 (int (*)(...))QSortFilterProxyModel::canFetchMore
+320 (int (*)(...))QSortFilterProxyModel::flags
+328 (int (*)(...))QSortFilterProxyModel::sort
+336 (int (*)(...))QSortFilterProxyModel::buddy
+344 (int (*)(...))QSortFilterProxyModel::match
+352 (int (*)(...))QSortFilterProxyModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractProxyModel::submit
+376 (int (*)(...))QAbstractProxyModel::revert
+384 (int (*)(...))QSortFilterProxyModel::setSourceModel
+392 (int (*)(...))QSortFilterProxyModel::mapToSource
+400 (int (*)(...))QSortFilterProxyModel::mapFromSource
+408 (int (*)(...))QSortFilterProxyModel::mapSelectionToSource
+416 (int (*)(...))QSortFilterProxyModel::mapSelectionFromSource
+424 (int (*)(...))QSortFilterProxyModel::filterAcceptsRow
+432 (int (*)(...))QSortFilterProxyModel::filterAcceptsColumn
+440 (int (*)(...))QSortFilterProxyModel::lessThan
+
+Class QSortFilterProxyModel
+ size=16 align=8
+ base size=16 base align=8
+QSortFilterProxyModel (0x0x7ff781b03548) 0
+ vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16)
+ QAbstractProxyModel (0x0x7ff781b035b0) 0
+ primary-for QSortFilterProxyModel (0x0x7ff781b03548)
+ QAbstractItemModel (0x0x7ff781b03618) 0
+ primary-for QAbstractProxyModel (0x0x7ff781b035b0)
+ QObject (0x0x7ff781b7b060) 0
+ primary-for QAbstractItemModel (0x0x7ff781b03618)
+
+Class QStandardPaths
+ size=1 align=1
+ base size=0 base align=1
+QStandardPaths (0x0x7ff781b7b4e0) 0 empty
+
+Class QState::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QState::QPrivateSignal (0x0x7ff781b7bde0) 0 empty
+
+Vtable for QState
+QState::_ZTV6QState: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI6QState)
+16 (int (*)(...))QState::metaObject
+24 (int (*)(...))QState::qt_metacast
+32 (int (*)(...))QState::qt_metacall
+40 (int (*)(...))QState::~QState
+48 (int (*)(...))QState::~QState
+56 (int (*)(...))QState::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QState::onEntry
+120 (int (*)(...))QState::onExit
+
+Class QState
+ size=16 align=8
+ base size=16 base align=8
+QState (0x0x7ff781b037b8) 0
+ vptr=((& QState::_ZTV6QState) + 16)
+ QAbstractState (0x0x7ff781b03820) 0
+ primary-for QState (0x0x7ff781b037b8)
+ QObject (0x0x7ff781b7bd80) 0
+ primary-for QAbstractState (0x0x7ff781b03820)
+
+Class QStateMachine::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QStateMachine::QPrivateSignal (0x0x7ff781bee2a0) 0 empty
+
+Vtable for QStateMachine::SignalEvent
+QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN13QStateMachine11SignalEventE)
+16 (int (*)(...))QStateMachine::SignalEvent::~SignalEvent
+24 (int (*)(...))QStateMachine::SignalEvent::~SignalEvent
+
+Class QStateMachine::SignalEvent
+ size=48 align=8
+ base size=48 base align=8
+QStateMachine::SignalEvent (0x0x7ff781b039c0) 0
+ vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16)
+ QEvent (0x0x7ff781bee300) 0
+ primary-for QStateMachine::SignalEvent (0x0x7ff781b039c0)
+
+Vtable for QStateMachine::WrappedEvent
+QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE: 4 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN13QStateMachine12WrappedEventE)
+16 (int (*)(...))QStateMachine::WrappedEvent::~WrappedEvent
+24 (int (*)(...))QStateMachine::WrappedEvent::~WrappedEvent
+
+Class QStateMachine::WrappedEvent
+ size=40 align=8
+ base size=40 base align=8
+QStateMachine::WrappedEvent (0x0x7ff781b03a28) 0
+ vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16)
+ QEvent (0x0x7ff781bee360) 0
+ primary-for QStateMachine::WrappedEvent (0x0x7ff781b03a28)
+
+Vtable for QStateMachine
+QStateMachine::_ZTV13QStateMachine: 20 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QStateMachine)
+16 (int (*)(...))QStateMachine::metaObject
+24 (int (*)(...))QStateMachine::qt_metacast
+32 (int (*)(...))QStateMachine::qt_metacall
+40 (int (*)(...))QStateMachine::~QStateMachine
+48 (int (*)(...))QStateMachine::~QStateMachine
+56 (int (*)(...))QStateMachine::event
+64 (int (*)(...))QStateMachine::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QStateMachine::onEntry
+120 (int (*)(...))QStateMachine::onExit
+128 (int (*)(...))QStateMachine::beginSelectTransitions
+136 (int (*)(...))QStateMachine::endSelectTransitions
+144 (int (*)(...))QStateMachine::beginMicrostep
+152 (int (*)(...))QStateMachine::endMicrostep
+
+Class QStateMachine
+ size=16 align=8
+ base size=16 base align=8
+QStateMachine (0x0x7ff781b03888) 0
+ vptr=((& QStateMachine::_ZTV13QStateMachine) + 16)
+ QState (0x0x7ff781b038f0) 0
+ primary-for QStateMachine (0x0x7ff781b03888)
+ QAbstractState (0x0x7ff781b03958) 0
+ primary-for QState (0x0x7ff781b038f0)
+ QObject (0x0x7ff781bee240) 0
+ primary-for QAbstractState (0x0x7ff781b03958)
+
+Class QStorageInfo
+ size=8 align=8
+ base size=8 base align=8
+QStorageInfo (0x0x7ff781bee720) 0
+
+Class QAbstractConcatenable
+ size=1 align=1
+ base size=0 base align=1
+QAbstractConcatenable (0x0x7ff781c8e720) 0 empty
+
+Class QStringListModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QStringListModel::QPrivateSignal (0x0x7ff781917a80) 0 empty
+
+Vtable for QStringListModel
+QStringListModel::_ZTV16QStringListModel: 48 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI16QStringListModel)
+16 (int (*)(...))QStringListModel::metaObject
+24 (int (*)(...))QStringListModel::qt_metacast
+32 (int (*)(...))QStringListModel::qt_metacall
+40 (int (*)(...))QStringListModel::~QStringListModel
+48 (int (*)(...))QStringListModel::~QStringListModel
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QAbstractListModel::index
+120 (int (*)(...))QAbstractListModel::parent
+128 (int (*)(...))QStringListModel::sibling
+136 (int (*)(...))QStringListModel::rowCount
+144 (int (*)(...))QAbstractListModel::columnCount
+152 (int (*)(...))QAbstractListModel::hasChildren
+160 (int (*)(...))QStringListModel::data
+168 (int (*)(...))QStringListModel::setData
+176 (int (*)(...))QAbstractItemModel::headerData
+184 (int (*)(...))QAbstractItemModel::setHeaderData
+192 (int (*)(...))QStringListModel::itemData
+200 (int (*)(...))QStringListModel::setItemData
+208 (int (*)(...))QAbstractItemModel::mimeTypes
+216 (int (*)(...))QAbstractItemModel::mimeData
+224 (int (*)(...))QAbstractItemModel::canDropMimeData
+232 (int (*)(...))QAbstractListModel::dropMimeData
+240 (int (*)(...))QStringListModel::supportedDropActions
+248 (int (*)(...))QAbstractItemModel::supportedDragActions
+256 (int (*)(...))QStringListModel::insertRows
+264 (int (*)(...))QAbstractItemModel::insertColumns
+272 (int (*)(...))QStringListModel::removeRows
+280 (int (*)(...))QAbstractItemModel::removeColumns
+288 (int (*)(...))QStringListModel::moveRows
+296 (int (*)(...))QAbstractItemModel::moveColumns
+304 (int (*)(...))QAbstractItemModel::fetchMore
+312 (int (*)(...))QAbstractItemModel::canFetchMore
+320 (int (*)(...))QStringListModel::flags
+328 (int (*)(...))QStringListModel::sort
+336 (int (*)(...))QAbstractItemModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QAbstractItemModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractItemModel::submit
+376 (int (*)(...))QAbstractItemModel::revert
+
+Class QStringListModel
+ size=24 align=8
+ base size=24 base align=8
+QStringListModel (0x0x7ff781906b60) 0
+ vptr=((& QStringListModel::_ZTV16QStringListModel) + 16)
+ QAbstractListModel (0x0x7ff781906bc8) 0
+ primary-for QStringListModel (0x0x7ff781906b60)
+ QAbstractItemModel (0x0x7ff781906c30) 0
+ primary-for QAbstractListModel (0x0x7ff781906bc8)
+ QObject (0x0x7ff781917a20) 0
+ primary-for QAbstractItemModel (0x0x7ff781906c30)
+
+Class QSystemSemaphore
+ size=8 align=8
+ base size=8 base align=8
+QSystemSemaphore (0x0x7ff781917ba0) 0
+
+Class QTemporaryDir
+ size=8 align=8
+ base size=8 base align=8
+QTemporaryDir (0x0x7ff781917c60) 0
+
+Class QTemporaryFile::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QTemporaryFile::QPrivateSignal (0x0x7ff781917d80) 0 empty
+
+Vtable for QTemporaryFile
+QTemporaryFile::_ZTV14QTemporaryFile: 34 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI14QTemporaryFile)
+16 (int (*)(...))QTemporaryFile::metaObject
+24 (int (*)(...))QTemporaryFile::qt_metacast
+32 (int (*)(...))QTemporaryFile::qt_metacall
+40 (int (*)(...))QTemporaryFile::~QTemporaryFile
+48 (int (*)(...))QTemporaryFile::~QTemporaryFile
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QFileDevice::isSequential
+120 (int (*)(...))QTemporaryFile::open
+128 (int (*)(...))QFileDevice::close
+136 (int (*)(...))QFileDevice::pos
+144 (int (*)(...))QFile::size
+152 (int (*)(...))QFileDevice::seek
+160 (int (*)(...))QFileDevice::atEnd
+168 (int (*)(...))QIODevice::reset
+176 (int (*)(...))QIODevice::bytesAvailable
+184 (int (*)(...))QIODevice::bytesToWrite
+192 (int (*)(...))QIODevice::canReadLine
+200 (int (*)(...))QIODevice::waitForReadyRead
+208 (int (*)(...))QIODevice::waitForBytesWritten
+216 (int (*)(...))QFileDevice::readData
+224 (int (*)(...))QFileDevice::readLineData
+232 (int (*)(...))QFileDevice::writeData
+240 (int (*)(...))QTemporaryFile::fileName
+248 (int (*)(...))QFile::resize
+256 (int (*)(...))QFile::permissions
+264 (int (*)(...))QFile::setPermissions
+
+Class QTemporaryFile
+ size=16 align=8
+ base size=16 base align=8
+QTemporaryFile (0x0x7ff781906c98) 0
+ vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16)
+ QFile (0x0x7ff781906d00) 0
+ primary-for QTemporaryFile (0x0x7ff781906c98)
+ QFileDevice (0x0x7ff781906d68) 0
+ primary-for QFile (0x0x7ff781906d00)
+ QIODevice (0x0x7ff781906dd0) 0
+ primary-for QFileDevice (0x0x7ff781906d68)
+ QObject (0x0x7ff781917d20) 0
+ primary-for QIODevice (0x0x7ff781906dd0)
+
+Class QTextBoundaryFinder
+ size=48 align=8
+ base size=48 base align=8
+QTextBoundaryFinder (0x0x7ff781974120) 0
+
+Class QTextCodec::ConverterState
+ size=32 align=8
+ base size=32 base align=8
+QTextCodec::ConverterState (0x0x7ff781974960) 0
+
+Vtable for QTextCodec
+QTextCodec::_ZTV10QTextCodec: 9 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI10QTextCodec)
+16 (int (*)(...))__cxa_pure_virtual
+24 (int (*)(...))QTextCodec::aliases
+32 (int (*)(...))__cxa_pure_virtual
+40 (int (*)(...))__cxa_pure_virtual
+48 (int (*)(...))__cxa_pure_virtual
+56 0
+64 0
+
+Class QTextCodec
+ size=8 align=8
+ base size=8 base align=8
+QTextCodec (0x0x7ff781974900) 0 nearly-empty
+ vptr=((& QTextCodec::_ZTV10QTextCodec) + 16)
+
+Class QTextEncoder
+ size=40 align=8
+ base size=40 base align=8
+QTextEncoder (0x0x7ff7819e0360) 0
+
+Class QTextDecoder
+ size=40 align=8
+ base size=40 base align=8
+QTextDecoder (0x0x7ff7819e0540) 0
+
+Class std::__mutex_base
+ size=40 align=8
+ base size=40 base align=8
+std::__mutex_base (0x0x7ff7819e0720) 0
+
+Class std::mutex
+ size=40 align=8
+ base size=40 base align=8
+std::mutex (0x0x7ff781a04000) 0
+ std::__mutex_base (0x0x7ff7819e0780) 0
+
+Class std::defer_lock_t
+ size=1 align=1
+ base size=0 base align=1
+std::defer_lock_t (0x0x7ff7819e0960) 0 empty
+
+Class std::try_to_lock_t
+ size=1 align=1
+ base size=0 base align=1
+std::try_to_lock_t (0x0x7ff7819e09c0) 0 empty
+
+Class std::adopt_lock_t
+ size=1 align=1
+ base size=0 base align=1
+std::adopt_lock_t (0x0x7ff7819e0a20) 0 empty
+
+Class std::__recursive_mutex_base
+ size=40 align=8
+ base size=40 base align=8
+std::__recursive_mutex_base (0x0x7ff781a2a480) 0
+
+Class std::recursive_mutex
+ size=40 align=8
+ base size=40 base align=8
+std::recursive_mutex (0x0x7ff781a04068) 0
+ std::__recursive_mutex_base (0x0x7ff781a2a4e0) 0
+
+Class std::timed_mutex
+ size=40 align=8
+ base size=40 base align=8
+std::timed_mutex (0x0x7ff7819e4ee0) 0
+ std::__mutex_base (0x0x7ff781a2a8a0) 0
+ std::__timed_mutex_impl<std::timed_mutex> (0x0x7ff781a2a900) 0 empty
+
+Class std::recursive_timed_mutex
+ size=40 align=8
+ base size=40 base align=8
+std::recursive_timed_mutex (0x0x7ff781a50230) 0
+ std::__recursive_mutex_base (0x0x7ff781a2ac60) 0
+ std::__timed_mutex_impl<std::recursive_timed_mutex> (0x0x7ff781a2acc0) 0 empty
+
+Class std::once_flag
+ size=4 align=4
+ base size=4 base align=4
+std::once_flag (0x0x7ff781a68420) 0
+
+Vtable for __gnu_cxx::__concurrence_lock_error
+__gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_lock_errorE)
+16 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error
+24 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error
+32 (int (*)(...))__gnu_cxx::__concurrence_lock_error::what
+
+Class __gnu_cxx::__concurrence_lock_error
+ size=8 align=8
+ base size=8 base align=8
+__gnu_cxx::__concurrence_lock_error (0x0x7ff781a041a0) 0 nearly-empty
+ vptr=((& __gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE) + 16)
+ std::exception (0x0x7ff781a68960) 0 nearly-empty
+ primary-for __gnu_cxx::__concurrence_lock_error (0x0x7ff781a041a0)
+
+Vtable for __gnu_cxx::__concurrence_unlock_error
+__gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN9__gnu_cxx26__concurrence_unlock_errorE)
+16 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error
+24 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error
+32 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::what
+
+Class __gnu_cxx::__concurrence_unlock_error
+ size=8 align=8
+ base size=8 base align=8
+__gnu_cxx::__concurrence_unlock_error (0x0x7ff781a04208) 0 nearly-empty
+ vptr=((& __gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE) + 16)
+ std::exception (0x0x7ff781a68a80) 0 nearly-empty
+ primary-for __gnu_cxx::__concurrence_unlock_error (0x0x7ff781a04208)
+
+Vtable for __gnu_cxx::__concurrence_broadcast_error
+__gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN9__gnu_cxx29__concurrence_broadcast_errorE)
+16 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error
+24 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error
+32 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::what
+
+Class __gnu_cxx::__concurrence_broadcast_error
+ size=8 align=8
+ base size=8 base align=8
+__gnu_cxx::__concurrence_broadcast_error (0x0x7ff781a04270) 0 nearly-empty
+ vptr=((& __gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE) + 16)
+ std::exception (0x0x7ff781a68ba0) 0 nearly-empty
+ primary-for __gnu_cxx::__concurrence_broadcast_error (0x0x7ff781a04270)
+
+Vtable for __gnu_cxx::__concurrence_wait_error
+__gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_wait_errorE)
+16 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error
+24 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error
+32 (int (*)(...))__gnu_cxx::__concurrence_wait_error::what
+
+Class __gnu_cxx::__concurrence_wait_error
+ size=8 align=8
+ base size=8 base align=8
+__gnu_cxx::__concurrence_wait_error (0x0x7ff781a04340) 0 nearly-empty
+ vptr=((& __gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE) + 16)
+ std::exception (0x0x7ff781a68cc0) 0 nearly-empty
+ primary-for __gnu_cxx::__concurrence_wait_error (0x0x7ff781a04340)
+
+Class __gnu_cxx::__mutex
+ size=40 align=8
+ base size=40 base align=8
+__gnu_cxx::__mutex (0x0x7ff78169dd20) 0
+
+Class __gnu_cxx::__recursive_mutex
+ size=40 align=8
+ base size=40 base align=8
+__gnu_cxx::__recursive_mutex (0x0x7ff7816bd060) 0
+
+Class __gnu_cxx::__scoped_lock
+ size=8 align=8
+ base size=8 base align=8
+__gnu_cxx::__scoped_lock (0x0x7ff7816bd360) 0
+
+Class __gnu_cxx::__cond
+ size=48 align=8
+ base size=48 base align=8
+__gnu_cxx::__cond (0x0x7ff7816bd6c0) 0
+
+Vtable for std::bad_weak_ptr
+std::bad_weak_ptr::_ZTVSt12bad_weak_ptr: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt12bad_weak_ptr)
+16 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr
+24 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr
+32 (int (*)(...))std::bad_weak_ptr::what
+
+Class std::bad_weak_ptr
+ size=8 align=8
+ base size=8 base align=8
+std::bad_weak_ptr (0x0x7ff781a043a8) 0 nearly-empty
+ vptr=((& std::bad_weak_ptr::_ZTVSt12bad_weak_ptr) + 16)
+ std::exception (0x0x7ff7817348a0) 0 nearly-empty
+ primary-for std::bad_weak_ptr (0x0x7ff781a043a8)
+
+Class std::_Sp_make_shared_tag
+ size=1 align=1
+ base size=0 base align=1
+std::_Sp_make_shared_tag (0x0x7ff7817a2840) 0 empty
+
+Class std::__sp_array_delete
+ size=1 align=1
+ base size=0 base align=1
+std::__sp_array_delete (0x0x7ff7817a2c60) 0 empty
+
+Class std::_Sp_locker
+ size=2 align=1
+ base size=2 base align=1
+std::_Sp_locker (0x0x7ff7814e1ae0) 0
+
+Vtable for std::thread::_State
+std::thread::_State::_ZTVNSt6thread6_StateE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt6thread6_StateE)
+16 0
+24 0
+32 (int (*)(...))__cxa_pure_virtual
+
+Class std::thread::_State
+ size=8 align=8
+ base size=8 base align=8
+std::thread::_State (0x0x7ff781514f60) 0 nearly-empty
+ vptr=((& std::thread::_State::_ZTVNSt6thread6_StateE) + 16)
+
+Class std::thread::id
+ size=8 align=8
+ base size=8 base align=8
+std::thread::id (0x0x7ff78153f000) 0
+
+Class std::thread
+ size=8 align=8
+ base size=8 base align=8
+std::thread (0x0x7ff781514f00) 0
+
+Class std::condition_variable
+ size=48 align=8
+ base size=48 base align=8
+std::condition_variable (0x0x7ff7813d63c0) 0
+
+Class std::__at_thread_exit_elt
+ size=16 align=8
+ base size=16 base align=8
+std::__at_thread_exit_elt (0x0x7ff7813d6780) 0
+
+Class std::_V2::condition_variable_any
+ size=64 align=8
+ base size=64 base align=8
+std::_V2::condition_variable_any (0x0x7ff7813d67e0) 0
+
+Class std::__atomic_futex_unsigned_base
+ size=1 align=1
+ base size=0 base align=1
+std::__atomic_futex_unsigned_base (0x0x7ff781161ae0) 0 empty
+
+Vtable for std::future_error
+std::future_error::_ZTVSt12future_error: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt12future_error)
+16 (int (*)(...))std::future_error::~future_error
+24 (int (*)(...))std::future_error::~future_error
+32 (int (*)(...))std::future_error::what
+
+Class std::future_error
+ size=32 align=8
+ base size=32 base align=8
+std::future_error (0x0x7ff781160c30) 0
+ vptr=((& std::future_error::_ZTVSt12future_error) + 16)
+ std::logic_error (0x0x7ff781160c98) 0
+ primary-for std::future_error (0x0x7ff781160c30)
+ std::exception (0x0x7ff78118d240) 0 nearly-empty
+ primary-for std::logic_error (0x0x7ff781160c98)
+
+Class std::__future_base::_Result_base::_Deleter
+ size=1 align=1
+ base size=0 base align=1
+std::__future_base::_Result_base::_Deleter (0x0x7ff78118d960) 0 empty
+
+Vtable for std::__future_base::_Result_base
+std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE: 5 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt13__future_base12_Result_baseE)
+16 (int (*)(...))__cxa_pure_virtual
+24 0
+32 0
+
+Class std::__future_base::_Result_base
+ size=16 align=8
+ base size=16 base align=8
+std::__future_base::_Result_base (0x0x7ff78118d900) 0
+ vptr=((& std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE) + 16)
+
+Class std::__future_base::_State_baseV2::__exception_ptr_tag
+ size=1 align=1
+ base size=0 base align=1
+std::__future_base::_State_baseV2::__exception_ptr_tag (0x0x7ff780fa60c0) 0 empty
+
+Class std::__future_base::_State_baseV2::_Make_ready
+ size=32 align=8
+ base size=32 base align=8
+std::__future_base::_State_baseV2::_Make_ready (0x0x7ff780f844e0) 0
+ std::__at_thread_exit_elt (0x0x7ff780fa6180) 0
+
+Vtable for std::__future_base::_State_baseV2
+std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E: 6 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt13__future_base13_State_baseV2E)
+16 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2
+24 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2
+32 (int (*)(...))std::__future_base::_State_baseV2::_M_complete_async
+40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future
+
+Class std::__future_base::_State_baseV2
+ size=32 align=8
+ base size=28 base align=8
+std::__future_base::_State_baseV2 (0x0x7ff78118dae0) 0
+ vptr=((& std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E) + 16)
+
+Class std::__future_base
+ size=1 align=1
+ base size=0 base align=1
+std::__future_base (0x0x7ff78118d8a0) 0 empty
+
+Vtable for std::__future_base::_Async_state_commonV2
+std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E: 6 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTINSt13__future_base21_Async_state_commonV2E)
+16 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2
+24 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2
+32 (int (*)(...))std::__future_base::_Async_state_commonV2::_M_complete_async
+40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future
+
+Class std::__future_base::_Async_state_commonV2
+ size=48 align=8
+ base size=44 base align=8
+std::__future_base::_Async_state_commonV2 (0x0x7ff78073f208) 0
+ vptr=((& std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E) + 16)
+ std::__future_base::_State_baseV2 (0x0x7ff780743180) 0
+ primary-for std::__future_base::_Async_state_commonV2 (0x0x7ff78073f208)
+
+Class QThread::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QThread::QPrivateSignal (0x0x7ff780743a20) 0 empty
+
+Vtable for QThread
+QThread::_ZTV7QThread: 15 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI7QThread)
+16 (int (*)(...))QThread::metaObject
+24 (int (*)(...))QThread::qt_metacast
+32 (int (*)(...))QThread::qt_metacall
+40 (int (*)(...))QThread::~QThread
+48 (int (*)(...))QThread::~QThread
+56 (int (*)(...))QThread::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QThread::run
+
+Class QThread
+ size=16 align=8
+ base size=16 base align=8
+QThread (0x0x7ff78073f548) 0
+ vptr=((& QThread::_ZTV7QThread) + 16)
+ QObject (0x0x7ff7807439c0) 0
+ primary-for QThread (0x0x7ff78073f548)
+
+Class QThreadPool::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QThreadPool::QPrivateSignal (0x0x7ff780743de0) 0 empty
+
+Vtable for QThreadPool
+QThreadPool::_ZTV11QThreadPool: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QThreadPool)
+16 (int (*)(...))QThreadPool::metaObject
+24 (int (*)(...))QThreadPool::qt_metacast
+32 (int (*)(...))QThreadPool::qt_metacall
+40 (int (*)(...))QThreadPool::~QThreadPool
+48 (int (*)(...))QThreadPool::~QThreadPool
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QThreadPool
+ size=16 align=8
+ base size=16 base align=8
+QThreadPool (0x0x7ff78073f5b0) 0
+ vptr=((& QThreadPool::_ZTV11QThreadPool) + 16)
+ QObject (0x0x7ff780743d80) 0
+ primary-for QThreadPool (0x0x7ff78073f5b0)
+
+Class QThreadStorageData
+ size=4 align=4
+ base size=4 base align=4
+QThreadStorageData (0x0x7ff780788000) 0
+
+Class QTimeLine::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QTimeLine::QPrivateSignal (0x0x7ff7807886c0) 0 empty
+
+Vtable for QTimeLine
+QTimeLine::_ZTV9QTimeLine: 15 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QTimeLine)
+16 (int (*)(...))QTimeLine::metaObject
+24 (int (*)(...))QTimeLine::qt_metacast
+32 (int (*)(...))QTimeLine::qt_metacall
+40 (int (*)(...))QTimeLine::~QTimeLine
+48 (int (*)(...))QTimeLine::~QTimeLine
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QTimeLine::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QTimeLine::valueForTime
+
+Class QTimeLine
+ size=16 align=8
+ base size=16 base align=8
+QTimeLine (0x0x7ff78073f618) 0
+ vptr=((& QTimeLine::_ZTV9QTimeLine) + 16)
+ QObject (0x0x7ff780788660) 0
+ primary-for QTimeLine (0x0x7ff78073f618)
+
+Class QTimer::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QTimer::QPrivateSignal (0x0x7ff780788900) 0 empty
+
+Vtable for QTimer
+QTimer::_ZTV6QTimer: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI6QTimer)
+16 (int (*)(...))QTimer::metaObject
+24 (int (*)(...))QTimer::qt_metacast
+32 (int (*)(...))QTimer::qt_metacall
+40 (int (*)(...))QTimer::~QTimer
+48 (int (*)(...))QTimer::~QTimer
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QTimer::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QTimer
+ size=32 align=8
+ base size=29 base align=8
+QTimer (0x0x7ff78073f680) 0
+ vptr=((& QTimer::_ZTV6QTimer) + 16)
+ QObject (0x0x7ff7807888a0) 0
+ primary-for QTimer (0x0x7ff78073f680)
+
+Class QTimeZone::OffsetData
+ size=32 align=8
+ base size=28 base align=8
+QTimeZone::OffsetData (0x0x7ff7807fa2a0) 0
+
+Class QTimeZone
+ size=8 align=8
+ base size=8 base align=8
+QTimeZone (0x0x7ff7807fa240) 0
+
+Class QTranslator::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QTranslator::QPrivateSignal (0x0x7ff780895360) 0 empty
+
+Vtable for QTranslator
+QTranslator::_ZTV11QTranslator: 16 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QTranslator)
+16 (int (*)(...))QTranslator::metaObject
+24 (int (*)(...))QTranslator::qt_metacast
+32 (int (*)(...))QTranslator::qt_metacall
+40 (int (*)(...))QTranslator::~QTranslator
+48 (int (*)(...))QTranslator::~QTranslator
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QTranslator::translate
+120 (int (*)(...))QTranslator::isEmpty
+
+Class QTranslator
+ size=16 align=8
+ base size=16 base align=8
+QTranslator (0x0x7ff780882d68) 0
+ vptr=((& QTranslator::_ZTV11QTranslator) + 16)
+ QObject (0x0x7ff780895300) 0
+ primary-for QTranslator (0x0x7ff780882d68)
+
+Class QTransposeProxyModel::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QTransposeProxyModel::QPrivateSignal (0x0x7ff7808955a0) 0 empty
+
+Vtable for QTransposeProxyModel
+QTransposeProxyModel::_ZTV20QTransposeProxyModel: 53 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI20QTransposeProxyModel)
+16 (int (*)(...))QTransposeProxyModel::metaObject
+24 (int (*)(...))QTransposeProxyModel::qt_metacast
+32 (int (*)(...))QTransposeProxyModel::qt_metacall
+40 (int (*)(...))QTransposeProxyModel::~QTransposeProxyModel
+48 (int (*)(...))QTransposeProxyModel::~QTransposeProxyModel
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))QTransposeProxyModel::index
+120 (int (*)(...))QTransposeProxyModel::parent
+128 (int (*)(...))QAbstractProxyModel::sibling
+136 (int (*)(...))QTransposeProxyModel::rowCount
+144 (int (*)(...))QTransposeProxyModel::columnCount
+152 (int (*)(...))QAbstractProxyModel::hasChildren
+160 (int (*)(...))QAbstractProxyModel::data
+168 (int (*)(...))QAbstractProxyModel::setData
+176 (int (*)(...))QTransposeProxyModel::headerData
+184 (int (*)(...))QTransposeProxyModel::setHeaderData
+192 (int (*)(...))QTransposeProxyModel::itemData
+200 (int (*)(...))QTransposeProxyModel::setItemData
+208 (int (*)(...))QAbstractProxyModel::mimeTypes
+216 (int (*)(...))QAbstractProxyModel::mimeData
+224 (int (*)(...))QAbstractProxyModel::canDropMimeData
+232 (int (*)(...))QAbstractProxyModel::dropMimeData
+240 (int (*)(...))QAbstractProxyModel::supportedDropActions
+248 (int (*)(...))QAbstractProxyModel::supportedDragActions
+256 (int (*)(...))QTransposeProxyModel::insertRows
+264 (int (*)(...))QTransposeProxyModel::insertColumns
+272 (int (*)(...))QTransposeProxyModel::removeRows
+280 (int (*)(...))QTransposeProxyModel::removeColumns
+288 (int (*)(...))QTransposeProxyModel::moveRows
+296 (int (*)(...))QTransposeProxyModel::moveColumns
+304 (int (*)(...))QAbstractProxyModel::fetchMore
+312 (int (*)(...))QAbstractProxyModel::canFetchMore
+320 (int (*)(...))QAbstractProxyModel::flags
+328 (int (*)(...))QTransposeProxyModel::sort
+336 (int (*)(...))QAbstractProxyModel::buddy
+344 (int (*)(...))QAbstractItemModel::match
+352 (int (*)(...))QTransposeProxyModel::span
+360 (int (*)(...))QAbstractItemModel::roleNames
+368 (int (*)(...))QAbstractProxyModel::submit
+376 (int (*)(...))QAbstractProxyModel::revert
+384 (int (*)(...))QTransposeProxyModel::setSourceModel
+392 (int (*)(...))QTransposeProxyModel::mapToSource
+400 (int (*)(...))QTransposeProxyModel::mapFromSource
+408 (int (*)(...))QAbstractProxyModel::mapSelectionToSource
+416 (int (*)(...))QAbstractProxyModel::mapSelectionFromSource
+
+Class QTransposeProxyModel
+ size=16 align=8
+ base size=16 base align=8
+QTransposeProxyModel (0x0x7ff780882dd0) 0
+ vptr=((& QTransposeProxyModel::_ZTV20QTransposeProxyModel) + 16)
+ QAbstractProxyModel (0x0x7ff780882e38) 0
+ primary-for QTransposeProxyModel (0x0x7ff780882dd0)
+ QAbstractItemModel (0x0x7ff780882ea0) 0
+ primary-for QAbstractProxyModel (0x0x7ff780882e38)
+ QObject (0x0x7ff780895540) 0
+ primary-for QAbstractItemModel (0x0x7ff780882ea0)
+
+Class QUrlQuery
+ size=8 align=8
+ base size=8 base align=8
+QUrlQuery (0x0x7ff780895780) 0
+
+Class QWaitCondition
+ size=8 align=8
+ base size=8 base align=8
+QWaitCondition (0x0x7ff78053b180) 0
+
+Class QXmlStreamStringRef
+ size=16 align=8
+ base size=16 base align=8
+QXmlStreamStringRef (0x0x7ff78053b2a0) 0
+
+Class QXmlStreamAttribute
+ size=80 align=8
+ base size=73 base align=8
+QXmlStreamAttribute (0x0x7ff7805c9660) 0
+
+Class QXmlStreamAttributes
+ size=8 align=8
+ base size=8 base align=8
+QXmlStreamAttributes (0x0x7ff780638548) 0
+ QVector<QXmlStreamAttribute> (0x0x7ff780629d80) 0
+
+Class QXmlStreamNamespaceDeclaration
+ size=40 align=8
+ base size=40 base align=8
+QXmlStreamNamespaceDeclaration (0x0x7ff7806730c0) 0
+
+Class QXmlStreamNotationDeclaration
+ size=56 align=8
+ base size=56 base align=8
+QXmlStreamNotationDeclaration (0x0x7ff7802cb060) 0
+
+Class QXmlStreamEntityDeclaration
+ size=88 align=8
+ base size=88 base align=8
+QXmlStreamEntityDeclaration (0x0x7ff780328060) 0
+
+Vtable for QXmlStreamEntityResolver
+QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver: 6 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI24QXmlStreamEntityResolver)
+16 (int (*)(...))QXmlStreamEntityResolver::~QXmlStreamEntityResolver
+24 (int (*)(...))QXmlStreamEntityResolver::~QXmlStreamEntityResolver
+32 (int (*)(...))QXmlStreamEntityResolver::resolveEntity
+40 (int (*)(...))QXmlStreamEntityResolver::resolveUndeclaredEntity
+
+Class QXmlStreamEntityResolver
+ size=8 align=8
+ base size=8 base align=8
+QXmlStreamEntityResolver (0x0x7ff780391120) 0 nearly-empty
+ vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16)
+
+Class QXmlStreamReader
+ size=8 align=8
+ base size=8 base align=8
+QXmlStreamReader (0x0x7ff780391180) 0
+
+Class QXmlStreamWriter
+ size=8 align=8
+ base size=8 base align=8
+QXmlStreamWriter (0x0x7ff7803f1060) 0
+
+Class QNdefRecord
+ size=8 align=8
+ base size=8 base align=8
+QNdefRecord (0x0x7ff7803f1240) 0
+
+Class QNdefFilter::Record
+ size=24 align=8
+ base size=24 base align=8
+QNdefFilter::Record (0x0x7ff7803f1420) 0
+
+Class QNdefFilter
+ size=8 align=8
+ base size=8 base align=8
+QNdefFilter (0x0x7ff7803f13c0) 0
+
+Class QNdefMessage
+ size=8 align=8
+ base size=8 base align=8
+QNdefMessage (0x0x7ff7803eb270) 0
+ QList<QNdefRecord> (0x0x7ff7803eb2d8) 0
+ QListSpecialMethods<QNdefRecord> (0x0x7ff7803f1660) 0 empty
+
+Class QNdefNfcTextRecord
+ size=8 align=8
+ base size=8 base align=8
+QNdefNfcTextRecord (0x0x7ff7803eb340) 0
+ QNdefRecord (0x0x7ff7803f1f00) 0
+
+Class QNdefNfcUriRecord
+ size=8 align=8
+ base size=8 base align=8
+QNdefNfcUriRecord (0x0x7ff7803eb888) 0
+ QNdefRecord (0x0x7ff780477780) 0
+
+Class QNdefNfcIconRecord
+ size=8 align=8
+ base size=8 base align=8
+QNdefNfcIconRecord (0x0x7ff7803eb8f0) 0
+ QNdefRecord (0x0x7ff780477b40) 0
+
+Class QNdefNfcSmartPosterRecord
+ size=16 align=8
+ base size=16 base align=8
+QNdefNfcSmartPosterRecord (0x0x7ff7803eb958) 0
+ QNdefRecord (0x0x7ff780477ea0) 0
+
+Class QNearFieldTarget::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QNearFieldTarget::QPrivateSignal (0x0x7ff7800dd0c0) 0 empty
+
+Class QNearFieldTarget::RequestId
+ size=8 align=8
+ base size=8 base align=8
+QNearFieldTarget::RequestId (0x0x7ff7800dd120) 0
+
+Vtable for QNearFieldTarget
+QNearFieldTarget::_ZTV16QNearFieldTarget: 25 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI16QNearFieldTarget)
+16 (int (*)(...))QNearFieldTarget::metaObject
+24 (int (*)(...))QNearFieldTarget::qt_metacast
+32 (int (*)(...))QNearFieldTarget::qt_metacall
+40 0
+48 0
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+112 (int (*)(...))__cxa_pure_virtual
+120 (int (*)(...))QNearFieldTarget::url
+128 (int (*)(...))__cxa_pure_virtual
+136 (int (*)(...))__cxa_pure_virtual
+144 (int (*)(...))QNearFieldTarget::hasNdefMessage
+152 (int (*)(...))QNearFieldTarget::readNdefMessages
+160 (int (*)(...))QNearFieldTarget::writeNdefMessages
+168 (int (*)(...))QNearFieldTarget::sendCommand
+176 (int (*)(...))QNearFieldTarget::sendCommands
+184 (int (*)(...))QNearFieldTarget::waitForRequestCompleted
+192 (int (*)(...))QNearFieldTarget::handleResponse
+
+Class QNearFieldTarget
+ size=24 align=8
+ base size=24 base align=8
+QNearFieldTarget (0x0x7ff7803eb9c0) 0
+ vptr=((& QNearFieldTarget::_ZTV16QNearFieldTarget) + 16)
+ QObject (0x0x7ff7800dd060) 0
+ primary-for QNearFieldTarget (0x0x7ff7803eb9c0)
+
+Class QNearFieldManager::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QNearFieldManager::QPrivateSignal (0x0x7ff7800ddea0) 0 empty
+
+Vtable for QNearFieldManager
+QNearFieldManager::_ZTV17QNearFieldManager: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI17QNearFieldManager)
+16 (int (*)(...))QNearFieldManager::metaObject
+24 (int (*)(...))QNearFieldManager::qt_metacast
+32 (int (*)(...))QNearFieldManager::qt_metacall
+40 (int (*)(...))QNearFieldManager::~QNearFieldManager
+48 (int (*)(...))QNearFieldManager::~QNearFieldManager
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QNearFieldManager
+ size=24 align=8
+ base size=24 base align=8
+QNearFieldManager (0x0x7ff7803ebaf8) 0
+ vptr=((& QNearFieldManager::_ZTV17QNearFieldManager) + 16)
+ QObject (0x0x7ff7800dde40) 0
+ primary-for QNearFieldManager (0x0x7ff7803ebaf8)
+
+Class QNearFieldShareManager::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QNearFieldShareManager::QPrivateSignal (0x0x7ff78014c960) 0 empty
+
+Vtable for QNearFieldShareManager
+QNearFieldShareManager::_ZTV22QNearFieldShareManager: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI22QNearFieldShareManager)
+16 (int (*)(...))QNearFieldShareManager::metaObject
+24 (int (*)(...))QNearFieldShareManager::qt_metacast
+32 (int (*)(...))QNearFieldShareManager::qt_metacall
+40 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager
+48 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QNearFieldShareManager
+ size=24 align=8
+ base size=24 base align=8
+QNearFieldShareManager (0x0x7ff7803ebc30) 0
+ vptr=((& QNearFieldShareManager::_ZTV22QNearFieldShareManager) + 16)
+ QObject (0x0x7ff78014c900) 0
+ primary-for QNearFieldShareManager (0x0x7ff7803ebc30)
+
+Class QNearFieldShareTarget::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QNearFieldShareTarget::QPrivateSignal (0x0x7ff7801ae4e0) 0 empty
+
+Vtable for QNearFieldShareTarget
+QNearFieldShareTarget::_ZTV21QNearFieldShareTarget: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI21QNearFieldShareTarget)
+16 (int (*)(...))QNearFieldShareTarget::metaObject
+24 (int (*)(...))QNearFieldShareTarget::qt_metacast
+32 (int (*)(...))QNearFieldShareTarget::qt_metacall
+40 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget
+48 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QNearFieldShareTarget
+ size=24 align=8
+ base size=24 base align=8
+QNearFieldShareTarget (0x0x7ff7803ebd68) 0
+ vptr=((& QNearFieldShareTarget::_ZTV21QNearFieldShareTarget) + 16)
+ QObject (0x0x7ff7801ae480) 0
+ primary-for QNearFieldShareTarget (0x0x7ff7803ebd68)
+
+Class QQmlNdefRecord::QPrivateSignal
+ size=1 align=1
+ base size=0 base align=1
+QQmlNdefRecord::QPrivateSignal (0x0x7ff7801ae720) 0 empty
+
+Vtable for QQmlNdefRecord
+QQmlNdefRecord::_ZTV14QQmlNdefRecord: 14 entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI14QQmlNdefRecord)
+16 (int (*)(...))QQmlNdefRecord::metaObject
+24 (int (*)(...))QQmlNdefRecord::qt_metacast
+32 (int (*)(...))QQmlNdefRecord::qt_metacall
+40 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord
+48 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord
+56 (int (*)(...))QObject::event
+64 (int (*)(...))QObject::eventFilter
+72 (int (*)(...))QObject::timerEvent
+80 (int (*)(...))QObject::childEvent
+88 (int (*)(...))QObject::customEvent
+96 (int (*)(...))QObject::connectNotify
+104 (int (*)(...))QObject::disconnectNotify
+
+Class QQmlNdefRecord
+ size=24 align=8
+ base size=24 base align=8
+QQmlNdefRecord (0x0x7ff7803ebdd0) 0
+ vptr=((& QQmlNdefRecord::_ZTV14QQmlNdefRecord) + 16)
+ QObject (0x0x7ff7801ae6c0) 0
+ primary-for QQmlNdefRecord (0x0x7ff7803ebdd0)
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff7801fecc0) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff78021d060) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff78021d240) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff78021d5a0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff78021d780) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff78021dae0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff78021dcc0) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff78025c060) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff78025c240) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff78025c5a0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff78025c780) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff78025cae0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff78025ccc0) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff780291060) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff780291240) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff7802915a0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77fec4a80) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77fec4de0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77fec4f60) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77fef3300) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77fef3480) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77fef37e0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77fef3960) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77fef3cc0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77fef3e40) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77ff221e0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77ff22360) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77ff226c0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77ff22840) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77ff22ba0) 0 empty
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno
+ size=4 align=4
+ base size=4 base align=4
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77ff22d20) 0
+
+Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk
+ size=1 align=1
+ base size=0 base align=1
+__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77ff500c0) 0 empty
+
diff --git a/tests/auto/qbluetoothdeviceinfo/tst_qbluetoothdeviceinfo.cpp b/tests/auto/qbluetoothdeviceinfo/tst_qbluetoothdeviceinfo.cpp
index 6636f0cd..d8c80291 100644
--- a/tests/auto/qbluetoothdeviceinfo/tst_qbluetoothdeviceinfo.cpp
+++ b/tests/auto/qbluetoothdeviceinfo/tst_qbluetoothdeviceinfo.cpp
@@ -447,21 +447,15 @@ void tst_QBluetoothDeviceInfo::tst_serviceUuids()
QBluetoothDeviceInfo deviceInfo;
QBluetoothDeviceInfo copyInfo = deviceInfo;
- QList<QBluetoothUuid> servicesList;
+ QVector<QBluetoothUuid> servicesList;
servicesList.append(QBluetoothUuid::L2cap);
servicesList.append(QBluetoothUuid::Rfcomm);
QVERIFY(servicesList.count() > 0);
- deviceInfo.setServiceUuids(servicesList.toVector());
+ deviceInfo.setServiceUuids(servicesList);
QVERIFY(deviceInfo.serviceUuids().count() > 0);
deviceInfo.setServiceUuids(QVector<QBluetoothUuid>());
QCOMPARE(deviceInfo.serviceUuids().count(), 0);
-
- deviceInfo.setServiceUuids(servicesList, QBluetoothDeviceInfo::DataComplete);
- QVERIFY(deviceInfo.serviceUuids().count() > 0);
- QVERIFY(deviceInfo != copyInfo);
-
- QVERIFY(deviceInfo.serviceUuidsCompleteness() == QBluetoothDeviceInfo::DataComplete);
}
void tst_QBluetoothDeviceInfo::tst_cached()
diff --git a/tests/auto/qbluetoothserviceinfo/tst_qbluetoothserviceinfo.cpp b/tests/auto/qbluetoothserviceinfo/tst_qbluetoothserviceinfo.cpp
index 7833495d..f89802d2 100644
--- a/tests/auto/qbluetoothserviceinfo/tst_qbluetoothserviceinfo.cpp
+++ b/tests/auto/qbluetoothserviceinfo/tst_qbluetoothserviceinfo.cpp
@@ -61,6 +61,8 @@ private slots:
void tst_assignment();
void tst_serviceClassUuids();
+
+ void tst_writeByteArray();
};
tst_QBluetoothServiceInfo::tst_QBluetoothServiceInfo()
@@ -385,6 +387,49 @@ void tst_QBluetoothServiceInfo::tst_serviceClassUuids()
QCOMPARE(svclids.at(1), QBluetoothUuid(QBluetoothUuid::SerialPort));
}
+static QByteArray debugOutput;
+
+void debugHandler(QtMsgType type, const QMessageLogContext &, const QString &msg)
+{
+ switch (type) {
+ case QtDebugMsg :
+ debugOutput = msg.toLocal8Bit();
+ break;
+ default:
+ break;
+ }
+}
+
+void tst_QBluetoothServiceInfo::tst_writeByteArray()
+{
+ // We cannot directly test the produced XML output for Bluez
+ // as there no public API to retrieve it and it would be Bluez specific.
+ // However we can check the debug output.
+ // It should contain a qbyteArray rather than a string. In the XML the QByteArray
+ // is converted to a text tag with hex encoding.
+
+ const QByteArray expected("\n (518)\tSequence\n (518)\t\tSequence\n (518)\t\t\tuchar 34\n (518)\t\t\tbytearray 05010906a101850105079508750119e029e7150025018102950175088103050795067508150026ff00190029ff8100050895057501190129059102950175039103c005010902a10185020901a1000509190129031500250175019503810275059501810105010930093109381581257f750895038106c0c0\n");
+
+ const QByteArray hidDescriptor =
+ QByteArray::fromHex("05010906a101850105079508750119e029e7150025018102950175088103050795067508150026FF00190029FF8100050895057501190129059102950175039103c005010902a10185020901a1000509190129031500250175019503810275059501810105010930093109381581257f750895038106c0c0");
+ const QBluetoothServiceInfo::Sequence hidDescriptorList({
+ QVariant::fromValue(quint8(0x22)), // Report type
+ QByteArray(hidDescriptor) // Descriptor array
+ });
+ const QBluetoothServiceInfo::Sequence hidDescriptorListSeq({
+ QVariant::fromValue(hidDescriptorList)
+ });
+ QBluetoothServiceInfo srvInfo;
+ srvInfo.setAttribute(0x0206, QVariant::fromValue(hidDescriptorListSeq));
+
+ const QVariant attribute = srvInfo.attribute(0x0206);
+ debugOutput.clear();
+ qInstallMessageHandler(debugHandler);
+ qDebug() << srvInfo;
+ qInstallMessageHandler(nullptr);
+ QCOMPARE(debugOutput, expected);
+}
+
QTEST_MAIN(tst_QBluetoothServiceInfo)
#include "tst_qbluetoothserviceinfo.moc"
diff --git a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
index b175ddd0..ab393210 100644
--- a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
+++ b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
@@ -451,14 +451,18 @@ void tst_QLowEnergyController::tst_concurrentDiscovery()
// 2. new controller to same device fails
{
+#ifdef Q_OS_DARWIN
+ QLowEnergyController control2(remoteDeviceInfo);
+#else
QLowEnergyController control2(remoteDevice);
+#endif
control2.connectToDevice();
{
QTRY_IMPL(control2.state() != QLowEnergyController::ConnectingState,
30000);
}
-#if defined(Q_OS_ANDROID) || QT_CONFIG(winrt_bt)
+#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || QT_CONFIG(winrt_bt)
QCOMPARE(control.state(), QLowEnergyController::ConnectedState);
QCOMPARE(control2.state(), QLowEnergyController::ConnectedState);
control2.disconnectFromDevice();
@@ -1755,7 +1759,8 @@ void tst_QLowEnergyController::tst_writeCharacteristic()
QTRY_VERIFY_WITH_TIMEOUT(
service->state() == QLowEnergyService::ServiceDiscovered, 30000);
- //test service described by http://processors.wiki.ti.com/index.php/SensorTag_User_Guide
+ // test service described by
+ // http://processors.wiki.ti.com/index.php/CC2650_SensorTag_User%27s_Guide
const QList<QLowEnergyCharacteristic> chars = service->characteristics();
QLowEnergyCharacteristic dataChar;
@@ -1929,7 +1934,7 @@ void tst_QLowEnergyController::tst_readWriteDescriptor()
service->state() == QLowEnergyService::ServiceDiscovered, 30000);
// Temperature service described by
- // http://processors.wiki.ti.com/index.php/SensorTag_User_Guide
+ // http://processors.wiki.ti.com/index.php/CC2650_SensorTag_User%27s_Guide
// 1. Find temperature data characteristic
const QLowEnergyCharacteristic tempData = service->characteristic(
diff --git a/tests/bttestui/btlocaldevice.cpp b/tests/bttestui/btlocaldevice.cpp
index 583a8c6b..55b99fc3 100644
--- a/tests/bttestui/btlocaldevice.cpp
+++ b/tests/bttestui/btlocaldevice.cpp
@@ -49,56 +49,59 @@ BtLocalDevice::BtLocalDevice(QObject *parent) :
QObject(parent), securityFlags(QBluetooth::NoSecurity)
{
localDevice = new QBluetoothLocalDevice(this);
- connect(localDevice, SIGNAL(error(QBluetoothLocalDevice::Error)),
- this, SIGNAL(error(QBluetoothLocalDevice::Error)));
- connect(localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)),
- this, SIGNAL(hostModeStateChanged()));
- connect(localDevice, SIGNAL(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing)),
- this, SLOT(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing)));
- connect(localDevice, SIGNAL(deviceConnected(QBluetoothAddress)),
- this, SLOT(connected(QBluetoothAddress)));
- connect(localDevice, SIGNAL(deviceDisconnected(QBluetoothAddress)),
- this, SLOT(disconnected(QBluetoothAddress)));
- connect(localDevice, SIGNAL(pairingDisplayConfirmation(QBluetoothAddress,QString)),
- this, SLOT(pairingDisplayConfirmation(QBluetoothAddress,QString)));
+ connect(localDevice, &QBluetoothLocalDevice::error,
+ this, &BtLocalDevice::error);
+ connect(localDevice, &QBluetoothLocalDevice::hostModeStateChanged,
+ this, &BtLocalDevice::hostModeStateChanged);
+ connect(localDevice, &QBluetoothLocalDevice::pairingFinished,
+ this, &BtLocalDevice::pairingFinished);
+ connect(localDevice, &QBluetoothLocalDevice::deviceConnected,
+ this, &BtLocalDevice::connected);
+ connect(localDevice, &QBluetoothLocalDevice::deviceDisconnected,
+ this, &BtLocalDevice::disconnected);
+ connect(localDevice, &QBluetoothLocalDevice::pairingDisplayConfirmation,
+ this, &BtLocalDevice::pairingDisplayConfirmation);
connect(localDevice, &QBluetoothLocalDevice::pairingDisplayPinCode,
this, &BtLocalDevice::pairingDisplayPinCode);
if (localDevice->isValid()) {
deviceAgent = new QBluetoothDeviceDiscoveryAgent(this);
- connect(deviceAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
- this, SLOT(deviceDiscovered(QBluetoothDeviceInfo)));
- connect(deviceAgent, SIGNAL(finished()),
- this, SLOT(discoveryFinished()));
- connect(deviceAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)),
- this, SLOT(discoveryError(QBluetoothDeviceDiscoveryAgent::Error)));
- connect(deviceAgent, SIGNAL(canceled()),
- this, SLOT(discoveryCanceled()));
+ connect(deviceAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered,
+ this, &BtLocalDevice::deviceDiscovered);
+ connect(deviceAgent, &QBluetoothDeviceDiscoveryAgent::finished,
+ this, &BtLocalDevice::discoveryFinished);
+ connect(deviceAgent, QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error),
+ this, &BtLocalDevice::discoveryError);
+ connect(deviceAgent, &QBluetoothDeviceDiscoveryAgent::canceled,
+ this, &BtLocalDevice::discoveryCanceled);
serviceAgent = new QBluetoothServiceDiscoveryAgent(this);
- connect(serviceAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
- this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
- connect(serviceAgent, SIGNAL(finished()),
- this, SLOT(serviceDiscoveryFinished()));
- connect(serviceAgent, SIGNAL(canceled()),
- this, SLOT(serviceDiscoveryCanceled()));
- connect(serviceAgent, SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)),
- this, SLOT(serviceDiscoveryError(QBluetoothServiceDiscoveryAgent::Error)));
+ connect(serviceAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered,
+ this, &BtLocalDevice::serviceDiscovered);
+ connect(serviceAgent, &QBluetoothServiceDiscoveryAgent::finished,
+ this, &BtLocalDevice::serviceDiscoveryFinished);
+ connect(serviceAgent, &QBluetoothServiceDiscoveryAgent::canceled,
+ this, &BtLocalDevice::serviceDiscoveryCanceled);
+ connect(serviceAgent, QOverload<QBluetoothServiceDiscoveryAgent::Error>::of(&QBluetoothServiceDiscoveryAgent::error),
+ this, &BtLocalDevice::serviceDiscoveryError);
socket = new QBluetoothSocket(SOCKET_PROTOCOL, this);
- connect(socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)),
- this, SLOT(socketStateChanged(QBluetoothSocket::SocketState)));
- connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)),
- this, SLOT(socketError(QBluetoothSocket::SocketError)));
- connect(socket, SIGNAL(connected()), this, SLOT(socketConnected()));
- connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
- connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
+ connect(socket, &QBluetoothSocket::stateChanged,
+ this, &BtLocalDevice::socketStateChanged);
+ connect(socket, QOverload<QBluetoothSocket::SocketError>::of(&QBluetoothSocket::error),
+ this, &BtLocalDevice::socketError);
+ connect(socket, &QBluetoothSocket::connected, this, &BtLocalDevice::socketConnected);
+ connect(socket, &QBluetoothSocket::disconnected, this, &BtLocalDevice::socketDisconnected);
+ connect(socket, &QIODevice::readyRead, this, &BtLocalDevice::readData);
+ connect(socket, &QBluetoothSocket::bytesWritten, this, [](qint64 bytesWritten){
+ qDebug() << "Bytes Written to Client socket:" << bytesWritten;
+ });
setSecFlags(static_cast<int>(socket->preferredSecurityFlags()));
server = new QBluetoothServer(SOCKET_PROTOCOL, this);
- connect(server, SIGNAL(newConnection()), this, SLOT(serverNewConnection()));
- connect(server, SIGNAL(error(QBluetoothServer::Error)),
- this, SLOT(serverError(QBluetoothServer::Error)));
+ connect(server, &QBluetoothServer::newConnection, this, &BtLocalDevice::serverNewConnection);
+ connect(server, QOverload<QBluetoothServer::Error>::of(&QBluetoothServer::error),
+ this, &BtLocalDevice::serverError);
} else {
deviceAgent = nullptr;
serviceAgent = nullptr;
@@ -675,13 +678,16 @@ void BtLocalDevice::serverNewConnection()
}
client->setParent(this);
- connect(client, SIGNAL(disconnected()), this, SLOT(clientSocketDisconnected()));
- connect(client, SIGNAL(readyRead()), this, SLOT(clientSocketReadyRead()));
- connect(client, SIGNAL(stateChanged(QBluetoothSocket::SocketState)),
- this, SLOT(socketStateChanged(QBluetoothSocket::SocketState)));
- connect(client, SIGNAL(error(QBluetoothSocket::SocketError)),
- this, SLOT(socketError(QBluetoothSocket::SocketError)));
- connect(client, SIGNAL(connected()), this, SLOT(socketConnected()));
+ connect(client, &QBluetoothSocket::disconnected, this, &BtLocalDevice::clientSocketDisconnected);
+ connect(client, &QIODevice::readyRead, this, &BtLocalDevice::clientSocketReadyRead);
+ connect(client, &QBluetoothSocket::stateChanged,
+ this, &BtLocalDevice::socketStateChanged);
+ connect(client, QOverload<QBluetoothSocket::SocketError>::of(&QBluetoothSocket::error),
+ this, &BtLocalDevice::socketError);
+ connect(client, &QBluetoothSocket::connected, this, &BtLocalDevice::socketConnected);
+ connect(client, &QBluetoothSocket::bytesWritten, this, [](qint64 bytesWritten){
+ qDebug() << "Bytes Written to Server socket:" << bytesWritten;
+ });
serverSockets.append(client);
}