#include "bluetoothsettingspage.h" #include "../transport/utun_node.h" #include "../transport/config_updater.h" #include "../transport/node_config.h" #include #include #include #include #include #include BluetoothSettingsPage::BluetoothSettingsPage(const QString& path, UtunNode* node, QWidget* parent) : QWidget(parent), m_path(path), m_node(node) { auto* layout = new QVBoxLayout(this); m_enabled = new QCheckBox(QCoreApplication::translate("ChatGui", "Enable Bluetooth"), this); m_advertise = new QCheckBox(QCoreApplication::translate("ChatGui", "Advertise this device"), this); m_incoming = new QCheckBox(QCoreApplication::translate("ChatGui", "Allow incoming Bluetooth connections"), this); m_enabled->setObjectName("bluetoothEnabled"); m_advertise->setObjectName("bluetoothAdvertise"); m_incoming->setObjectName("bluetoothIncoming"); NodeConfig config(path); const int flags = config.exists() && config.load() ? config.bluetoothFlags() : 0; m_enabled->setChecked(flags & 1); m_advertise->setChecked(flags & 2); m_incoming->setChecked(flags & 4); auto permissions = [this](bool enabled) { m_advertise->setEnabled(enabled); m_incoming->setEnabled(enabled); }; connect(m_enabled, &QCheckBox::toggled, this, permissions); permissions(flags & 1); layout->addWidget(m_enabled); layout->addWidget(m_advertise); layout->addWidget(m_incoming); auto* note = new QLabel(QCoreApplication::translate("ChatGui", "Nearby VibeChat devices can see your node ID and name when advertising is enabled. Bluetooth must also be enabled in system settings."), this); note->setWordWrap(true); layout->addWidget(note); m_status = new QLabel(this); m_status->setWordWrap(true); m_status->setTextFormat(Qt::PlainText); m_advertisingStatus = new QLabel(this); m_advertisingStatus->setWordWrap(true); m_advertisingStatus->setTextFormat(Qt::PlainText); layout->addWidget(m_status); layout->addWidget(m_advertisingStatus); layout->addWidget(new QLabel(QCoreApplication::translate("ChatGui", "Nearby VibeChat devices:"), this)); m_peers = new QListWidget(this); layout->addWidget(m_peers, 1); auto* timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [this] { refresh(); }); timer->start(1000); refresh(); } void BluetoothSettingsPage::refresh() { const auto state = m_node ? m_node->bluetoothSnapshot() : DesktopBleSnapshot{}; QString status; if (!m_node || !m_node->isRunning()) status = QCoreApplication::translate("ChatGui", "Bluetooth: node is not running"); else if (!(state.flags & 1)) status = QCoreApplication::translate("ChatGui", "Bluetooth is off"); else if (state.state == BLE_STARTING) status = QCoreApplication::translate("ChatGui", "Starting Bluetooth..."); else if (state.state == BLE_READY) status = QCoreApplication::translate("ChatGui", "Bluetooth is ready. Connections: %1").arg(state.connections); else status = QCoreApplication::translate("ChatGui", "Bluetooth is unavailable: %1").arg(state.reason); m_status->setText(status); m_advertisingStatus->setVisible((state.flags & 3) == 3); m_advertisingStatus->setText(state.advertising == BLE_READY ? QCoreApplication::translate("ChatGui", "Advertising is active") : QCoreApplication::translate("ChatGui", "Advertising: %1").arg(state.advertisingReason)); m_peers->clear(); m_peers->addItems(state.peers); } bool BluetoothSettingsPage::save() { const int flags = (m_enabled->isChecked() ? 1 : 0) | (m_advertise->isChecked() ? 2 : 0) | (m_incoming->isChecked() ? 4 : 0); if (!config_update_option(m_path, "gui", "bluetooth_flags", QString::number(flags))) return false; if (m_node && m_node->isRunning()) m_node->setBluetoothFlags(flags); return true; }