diff options
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(¤t); } + // 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 ¶ms) +{ + 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 ¶ms, - const QLowEnergyAdvertisingData &advertisingData, - const QLowEnergyAdvertisingData &scanResponseData) +void QLowEnergyControllerPrivateDarwin::startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, + 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 ¶ms) -{ - 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 ¶ms) override; + void addToGenericAttributeList(const QLowEnergyServiceData &service, + QLowEnergyHandle startHandle) override; + + void startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, + 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); } |