11#include "ui_settingspage.h"
24 m_localDevice =
new QBluetoothLocalDevice(
this);
29 m_discoveryTimer =
new QTimer(
this);
30 m_discoveryTimer->setSingleShot(
true);
31 m_discoveryTimer->setInterval(120000);
32 connect(m_discoveryTimer, &QTimer::timeout,
this, &SettingsPage::stopDiscovery);
34 connect(m_localDevice, &QBluetoothLocalDevice::errorOccurred,
35 this, &SettingsPage::errorOccurred);
38 connect(ui->btnVisible, &QPushButton::clicked,
this, &SettingsPage::onVisibleClicked);
39 connect(ui->btnForget, &QPushButton::clicked,
this, &SettingsPage::onForgetClicked);
42 ui->btnForget->setEnabled(
false);
43 connect(ui->listDevices, &QListWidget::itemSelectionChanged,
this, [
this](){
44 QListWidgetItem *item = ui->listDevices->currentItem();
45 bool hasSelection = item && !item->data(Qt::UserRole).toString().isEmpty();
46 ui->btnForget->setEnabled(hasSelection);
51 m_pollTimer =
new QTimer(
this);
52 connect(m_pollTimer, &QTimer::timeout,
this, &SettingsPage::refreshPairedList);
53 m_pollTimer->start(2000);
62void SettingsPage::showAutoClosingMessage(
const QString &title,
const QString &text,
int timeoutMs)
65 QMessageBox *msgBox =
new QMessageBox(
this);
66 msgBox->setWindowTitle(title);
67 msgBox->setText(text);
68 msgBox->setStandardButtons(QMessageBox::NoButton);
69 msgBox->setIcon(QMessageBox::Information);
73 QTimer::singleShot(timeoutMs, msgBox, [msgBox]() {
75 msgBox->deleteLater();
79void SettingsPage::refreshPairedList()
84 process.start(
"bluetoothctl", QStringList() <<
"devices");
85 process.waitForFinished();
86 QString output = process.readAllStandardOutput().trimmed();
90 if (ui->listDevices->currentItem()) {
91 selectedMac = ui->listDevices->currentItem()->data(Qt::UserRole).toString();
94 ui->listDevices->clear();
96 QStringList lines = output.split(
'\n');
100 QString newcomerName;
101 QMap<QString, QString> connectedDevices;
104 for (
const QString &line : lines) {
106 if (line.trimmed().isEmpty())
continue;
108 QStringList parts = line.split(
' ');
109 if (parts.size() >= 3 && parts[0] ==
"Device") {
110 QString mac = parts[1];
111 QString name = parts.mid(2).join(
' ');
114 QProcess infoProcess;
115 infoProcess.start(
"bluetoothctl", QStringList() <<
"info" << mac);
116 infoProcess.waitForFinished();
117 QString infoOutput = infoProcess.readAllStandardOutput();
118 bool isConnected = infoOutput.contains(
"Connected: yes");
121 connectedDevices.insert(mac, name);
124 if (mac != m_lastActiveMac) {
132 if (!m_knownMacs.contains(mac)) {
133 m_knownMacs.insert(mac);
134 QProcess::execute(
"bluetoothctl", QStringList() <<
"trust" << mac);
137 if (ui->btnVisible->isChecked()) setDiscoverable(
false);
141 QString label = name +
" (" + mac +
")";
142 if (isConnected) label +=
" (connecté)";
144 QListWidgetItem *item =
new QListWidgetItem(
"📱 " + label, ui->listDevices);
145 item->setData(Qt::UserRole, mac);
149 item->setForeground(Qt::green);
153 if (mac == selectedMac) {
154 ui->listDevices->setCurrentItem(item);
163 if (connectedDevices.size() > 1 && !newcomerMac.isEmpty()) {
164 QString oldDeviceName;
166 QMapIterator<QString, QString> i(connectedDevices);
167 while (i.hasNext()) {
170 if (i.key() != newcomerMac) {
171 oldDeviceName = i.value();
172 QProcess::execute(
"bluetoothctl", QStringList() <<
"disconnect" << i.key());
173 qDebug() <<
"Exclusivité : Déconnexion de" << oldDeviceName;
178 showAutoClosingMessage(
"Changement d'appareil",
179 QString(
"Priorité à '%1'.\n'%2' a été déconnecté.")
180 .arg(newcomerName).arg(oldDeviceName),
183 m_lastActiveMac = newcomerMac;
185 else if (connectedDevices.size() == 1) {
186 m_lastActiveMac = connectedDevices.keys().first();
188 else if (connectedDevices.isEmpty()) {
189 m_lastActiveMac =
"";
194 new QListWidgetItem(
"(Aucun appareil enregistré)", ui->listDevices);
195 ui->btnForget->setEnabled(
false);
199void SettingsPage::onVisibleClicked()
201 setDiscoverable(ui->btnVisible->isChecked());
204void SettingsPage::setDiscoverable(
bool enable)
207 QProcess::execute(
"bluetoothctl", QStringList() <<
"discoverable" <<
"on");
208 ui->btnVisible->setText(
"Visible (120s max)...");
209 ui->btnVisible->setChecked(
true);
212 m_discoveryTimer->start();
214 QProcess::execute(
"bluetoothctl", QStringList() <<
"discoverable" <<
"off");
215 ui->btnVisible->setText(
"Rendre Visible (Appairage)");
216 ui->btnVisible->setChecked(
false);
217 m_discoveryTimer->stop();
221void SettingsPage::stopDiscovery()
223 setDiscoverable(
false);
226void SettingsPage::onForgetClicked()
228 QListWidgetItem *item = ui->listDevices->currentItem();
231 QString mac = item->data(Qt::UserRole).toString();
232 QString name = item->text().remove(
"📱 ").remove(
" (connecté)");
233 if (mac.isEmpty())
return;
236 QMessageBox::StandardButton reply;
237 reply = QMessageBox::question(
this,
"Supprimer l'appareil",
238 QString(
"Voulez-vous vraiment oublier l'appareil %1 ?").arg(name),
239 QMessageBox::Yes | QMessageBox::No);
241 if (reply == QMessageBox::No)
return;
244 QProcess::execute(
"bluetoothctl", QStringList() <<
"remove" << mac);
246 m_knownMacs.remove(mac);
247 if(m_lastActiveMac == mac) m_lastActiveMac =
"";
250 ui->listDevices->clear();
251 ui->btnForget->setEnabled(
false);
256void SettingsPage::errorOccurred(QBluetoothLocalDevice::Error error)
258 qDebug() <<
"Erreur Bluetooth LocalDevice:" << error;
Interface graphique de gestion des paramètres et des connexions sans fil. Permet de rendre le véhicul...
~SettingsPage()
Destructeur. Libère l'interface générée par Qt Designer.
SettingsPage(QWidget *parent=nullptr)
Constructeur de la page des paramètres.
Rôle architectural : Page de configuration système et Bluetooth utilisateur.
Rôle architectural : Modèle central de télémétrie partagé entre les modules C++ et l'interface QML.