src/eric7/MicroPython/BluetoothDialogs/BluetoothScanWindow.py

Wed, 08 Mar 2023 14:25:24 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 08 Mar 2023 14:25:24 +0100
branch
mpy_network
changeset 9857
0122ae72618d
child 9859
829c1edbf253
permissions
-rw-r--r--

MicroPython
- Added support for Bluetooth scans for CircuitPython devices.

# -*- coding: utf-8 -*-

# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing a dialog to scan for Bluetooth devices.
"""

from PyQt6.QtCore import Qt, pyqtSlot
from PyQt6.QtWidgets import QHeaderView, QTreeWidgetItem, QWidget

from eric7.EricGui.EricOverrideCursor import EricOverrideCursor
from eric7.EricWidgets import EricMessageBox

from .Ui_BluetoothScanWindow import Ui_BluetoothScanWindow


class BluetoothScanWindow(QWidget, Ui_BluetoothScanWindow):
    """
    Class implementing a dialog to scan for Bluetooth devices.
    """

    def __init__(self, device, parent=None):
        """
        Constructor

        @param device reference to the connected device
        @type BaseDevice
        @param parent reference to the parent widget (defaults to None)
        @type QWidget (optional)
        """
        super().__init__(parent)
        self.setupUi(self)

        windowFlags = self.windowFlags()
        windowFlags |= Qt.WindowType.Window
        windowFlags |= Qt.WindowType.WindowContextHelpButtonHint
        self.setWindowFlags(windowFlags)

        self.__device = device

        self.devicesList.setColumnCount(4)
        self.devicesList.headerItem().setText(3, "")

        self.scanButton.clicked.connect(self.scanDevices)

        self.devicesList.sortByColumn(0, Qt.SortOrder.AscendingOrder)

    @pyqtSlot()
    def scanDevices(self):
        """
        Public slot to ask the device for a Bluetooth scan and display the result.
        """
        self.devicesList.clear()
        self.statusLabel.clear()

        self.scanButton.setEnabled(False)
        with EricOverrideCursor():
            scanResults, error = self.__device.getDeviceScan(
                timeout=self.durationSpinBox.value()
            )
        self.scanButton.setEnabled(True)

        if error:
            EricMessageBox.warning(
                self,
                self.tr("Bluetooth Scan"),
                self.tr(
                    """<p>The scan for available devices failed.</p>"""
                    """<p>Reason: {0}</p>"""
                ).format(error),
            )

        else:
            for res in scanResults.values():
                name = res.name
                if not name:
                    name = self.tr("N/A")
                itm = QTreeWidgetItem(
                    self.devicesList, [name, res.address, str(res.rssi)]
                )
                itm.setTextAlignment(1, Qt.AlignmentFlag.AlignHCenter)
                itm.setTextAlignment(2, Qt.AlignmentFlag.AlignHCenter)

                for service, isComplete in res.services:
                    if len(service) == 6:
                        bits = 16
                    elif len(service) == 10:
                        bits = 32
                    else:
                        bits = 128
                    template = (
                        self.tr("Complete {0}-bit Service UUID: {1}")
                        if isComplete
                        else self.tr("Incomplete {0}-bit Service UUID: {1}")
                    )
                    sitm = QTreeWidgetItem(itm, [template.format(bits, service)])
                    sitm.setFirstColumnSpanned(True)

                for mid, _, mname in res.manufacturer(withName=True):
                    mitm = QTreeWidgetItem(
                        itm,
                        [
                            self.tr("Manufacturer ID: 0x{0:x} ({1})").format(mid, mname)
                            if bool(mname)
                            else self.tr("Manufacturer ID: 0x{0:x}").format(mid)
                        ],
                    )
                    mitm.setFirstColumnSpanned(True)

            self.__resizeColumns()
            self.__resort()

    def __resort(self):
        """
        Private method to resort the devices list.
        """
        self.devicesList.sortItems(
            self.devicesList.sortColumn(),
            self.devicesList.header().sortIndicatorOrder(),
        )

    def __resizeColumns(self):
        """
        Private method to resize the columns of the result list.
        """
        self.devicesList.header().resizeSections(
            QHeaderView.ResizeMode.ResizeToContents
        )
        self.devicesList.header().setStretchLastSection(True)

eric ide

mercurial