Remove concept of Local and Remote Bluetooth Devices.
They both essentially do the same thing - to return the hardware address, and show whether the adapter is available. Remove RemoteBluetoothDevice, merge into LocalBluetoothDevice Introduce routine to SettingsWindow to bring in list of adapters.
This commit is contained in:
parent
478526b953
commit
28caa06b09
@ -24,11 +24,8 @@ namespace f1x::openauto::autoapp::configuration {
|
||||
enum class BluetoothAdapterType {
|
||||
NONE,
|
||||
LOCAL,
|
||||
REMOTE
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
EXTERNAL
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
@ -109,8 +109,9 @@ public:
|
||||
|
||||
BluetoothAdapterType getBluetoothAdapterType() const override;
|
||||
void setBluetoothAdapterType(BluetoothAdapterType value) override;
|
||||
std::string getBluetoothRemoteAdapterAddress() const override;
|
||||
void setBluetoothRemoteAdapterAddress(const std::string& value) override;
|
||||
std::string getBluetoothAdapterAddress() const override;
|
||||
|
||||
void setBluetoothAdapterAddress(const std::string& value) override;
|
||||
|
||||
bool musicAudioChannelEnabled() const override;
|
||||
void setMusicAudioChannelEnabled(bool value) override;
|
||||
@ -157,7 +158,7 @@ private:
|
||||
bool enablePlayerControl_;
|
||||
ButtonCodes buttonCodes_;
|
||||
BluetoothAdapterType bluetoothAdapterType_;
|
||||
std::string bluetoothRemoteAdapterAddress_;
|
||||
std::string bluetoothAdapterAddress_;
|
||||
bool _audioChannelEnabledMedia;
|
||||
bool _audioChannelEnabledGuidance;
|
||||
bool _audioChannelEnabledSystem;
|
||||
@ -204,7 +205,7 @@ private:
|
||||
static const std::string cAudioOutputBackendType;
|
||||
|
||||
static const std::string cBluetoothAdapterTypeKey;
|
||||
static const std::string cBluetoothRemoteAdapterAddressKey;
|
||||
static const std::string cBluetoothAdapterAddressKey;
|
||||
|
||||
static const std::string cInputEnableTouchscreenKey;
|
||||
static const std::string cInputEnablePlayerControlKey;
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <aap_protobuf/service/media/sink/message/VideoFrameRateType.pb.h>
|
||||
#include <aap_protobuf/service/media/sink/message/VideoCodecResolutionType.pb.h>
|
||||
#include <aap_protobuf/service/media/sink/message/KeyCode.pb.h>
|
||||
#include <f1x/openauto/autoapp/Configuration/BluetootAdapterType.hpp>
|
||||
#include <f1x/openauto/autoapp/Configuration/BluetoothAdapterType.hpp>
|
||||
#include <f1x/openauto/autoapp/Configuration/HandednessOfTrafficType.hpp>
|
||||
#include <f1x/openauto/autoapp/Configuration/AudioOutputBackendType.hpp>
|
||||
|
||||
@ -112,8 +112,8 @@ public:
|
||||
|
||||
virtual BluetoothAdapterType getBluetoothAdapterType() const = 0;
|
||||
virtual void setBluetoothAdapterType(BluetoothAdapterType value) = 0;
|
||||
virtual std::string getBluetoothRemoteAdapterAddress() const = 0;
|
||||
virtual void setBluetoothRemoteAdapterAddress(const std::string& value) = 0;
|
||||
virtual std::string getBluetoothAdapterAddress() const = 0;
|
||||
virtual void setBluetoothAdapterAddress(const std::string& value) = 0;
|
||||
|
||||
virtual bool musicAudioChannelEnabled() const = 0;
|
||||
virtual void setMusicAudioChannelEnabled(bool value) = 0;
|
||||
|
@ -34,8 +34,7 @@ class DummyBluetoothDevice: public IBluetoothDevice
|
||||
public:
|
||||
void stop() override;
|
||||
bool isPaired(const std::string& address) const override;
|
||||
void pair(const std::string& address, PairingPromise::Pointer promise) override;
|
||||
std::string getLocalAddress() const override;
|
||||
std::string getAdapterAddress() const override;
|
||||
bool isAvailable() const override;
|
||||
};
|
||||
|
||||
|
@ -37,8 +37,7 @@ public:
|
||||
|
||||
virtual void stop() = 0;
|
||||
virtual bool isPaired(const std::string& address) const = 0;
|
||||
virtual void pair(const std::string& address, PairingPromise::Pointer promise) = 0;
|
||||
virtual std::string getLocalAddress() const = 0;
|
||||
virtual std::string getAdapterAddress() const = 0;
|
||||
virtual bool isAvailable() const = 0;
|
||||
};
|
||||
|
||||
|
@ -35,8 +35,7 @@ public:
|
||||
|
||||
void stop() override;
|
||||
bool isPaired(const std::string& address) const override;
|
||||
void pair(const std::string& address, PairingPromise::Pointer promise) override;
|
||||
std::string getLocalAddress() const override;
|
||||
std::string getAdapterAddress() const override;
|
||||
bool isAvailable() const override;
|
||||
|
||||
signals:
|
||||
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* This file is part of openauto project.
|
||||
* Copyright (C) 2018 f1x.studio (Michal Szwaj)
|
||||
*
|
||||
* openauto is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* openauto is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with openauto. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <f1x/openauto/autoapp/Projection/IBluetoothDevice.hpp>
|
||||
|
||||
namespace f1x
|
||||
{
|
||||
namespace openauto
|
||||
{
|
||||
namespace autoapp
|
||||
{
|
||||
namespace projection
|
||||
{
|
||||
|
||||
class RemoteBluetoothDevice: public IBluetoothDevice
|
||||
{
|
||||
public:
|
||||
RemoteBluetoothDevice(const std::string& address);
|
||||
|
||||
void stop() override;
|
||||
bool isPaired(const std::string& address) const override;
|
||||
void pair(const std::string& address, PairingPromise::Pointer promise) override;
|
||||
std::string getLocalAddress() const override;
|
||||
bool isAvailable() const override;
|
||||
|
||||
private:
|
||||
std::string address_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -65,7 +65,7 @@ const std::string Configuration::cAudioChannelTelephonyEnabled = "AudioChannel.T
|
||||
const std::string Configuration::cAudioOutputBackendType = "Audio.OutputBackendType";
|
||||
|
||||
const std::string Configuration::cBluetoothAdapterTypeKey = "Bluetooth.AdapterType";
|
||||
const std::string Configuration::cBluetoothRemoteAdapterAddressKey = "Bluetooth.RemoteAdapterAddress";
|
||||
const std::string Configuration::cBluetoothAdapterAddressKey = "Bluetooth.AdapterAddress";
|
||||
|
||||
const std::string Configuration::cInputEnableTouchscreenKey = "Input.EnableTouchscreen";
|
||||
const std::string Configuration::cInputEnablePlayerControlKey = "Input.EnablePlayerControl";
|
||||
@ -137,7 +137,7 @@ void Configuration::load()
|
||||
bluetoothAdapterType_ = static_cast<BluetoothAdapterType>(iniConfig.get<uint32_t>(cBluetoothAdapterTypeKey,
|
||||
static_cast<uint32_t>(BluetoothAdapterType::NONE)));
|
||||
|
||||
bluetoothRemoteAdapterAddress_ = iniConfig.get<std::string>(cBluetoothRemoteAdapterAddressKey, "");
|
||||
bluetoothAdapterAddress_ = iniConfig.get<std::string>(cBluetoothAdapterAddressKey, "");
|
||||
|
||||
_audioChannelEnabledMedia = iniConfig.get<bool>(cAudioChannelMediaEnabled, true);
|
||||
_audioChannelEnabledGuidance = iniConfig.get<bool>(cAudioChannelGuidanceEnabled, true);
|
||||
@ -184,7 +184,7 @@ void Configuration::reset()
|
||||
enablePlayerControl_ = false;
|
||||
buttonCodes_.clear();
|
||||
bluetoothAdapterType_ = BluetoothAdapterType::NONE;
|
||||
bluetoothRemoteAdapterAddress_ = "";
|
||||
bluetoothAdapterAddress_ = "";
|
||||
|
||||
_audioChannelEnabledMedia = true;
|
||||
_audioChannelEnabledGuidance = true;
|
||||
@ -229,7 +229,7 @@ void Configuration::save()
|
||||
this->writeButtonCodes(iniConfig);
|
||||
|
||||
iniConfig.put<uint32_t>(cBluetoothAdapterTypeKey, static_cast<uint32_t>(bluetoothAdapterType_));
|
||||
iniConfig.put<std::string>(cBluetoothRemoteAdapterAddressKey, bluetoothRemoteAdapterAddress_);
|
||||
iniConfig.put<std::string>(cBluetoothAdapterAddressKey, bluetoothAdapterAddress_);
|
||||
|
||||
iniConfig.put<bool>(cAudioChannelMediaEnabled, _audioChannelEnabledMedia);
|
||||
iniConfig.put<bool>(cAudioChannelGuidanceEnabled, _audioChannelEnabledGuidance);
|
||||
@ -529,14 +529,14 @@ void Configuration::setBluetoothAdapterType(BluetoothAdapterType value)
|
||||
bluetoothAdapterType_ = value;
|
||||
}
|
||||
|
||||
std::string Configuration::getBluetoothRemoteAdapterAddress() const
|
||||
std::string Configuration::getBluetoothAdapterAddress() const
|
||||
{
|
||||
return bluetoothRemoteAdapterAddress_;
|
||||
return bluetoothAdapterAddress_;
|
||||
}
|
||||
|
||||
void Configuration::setBluetoothRemoteAdapterAddress(const std::string& value)
|
||||
void Configuration::setBluetoothAdapterAddress(const std::string& value)
|
||||
{
|
||||
bluetoothRemoteAdapterAddress_ = value;
|
||||
bluetoothAdapterAddress_ = value;
|
||||
}
|
||||
|
||||
bool Configuration::musicAudioChannelEnabled() const
|
||||
|
@ -74,8 +74,7 @@ void LocalBluetoothDevice::pair(const std::string& address, PairingPromise::Poin
|
||||
emit startPairing(QString::fromStdString(address), std::move(promise));
|
||||
}
|
||||
|
||||
std::string LocalBluetoothDevice::getLocalAddress() const
|
||||
{
|
||||
std::string LocalBluetoothDevice::getAdapterAddress() const {
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
return localDevice_->isValid() ? localDevice_->address().toString().toStdString() : "";
|
||||
}
|
||||
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* This file is part of openauto project.
|
||||
* Copyright (C) 2018 f1x.studio (Michal Szwaj)
|
||||
*
|
||||
* openauto is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* openauto is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with openauto. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <f1x/openauto/autoapp/Projection/RemoteBluetoothDevice.hpp>
|
||||
|
||||
namespace f1x
|
||||
{
|
||||
namespace openauto
|
||||
{
|
||||
namespace autoapp
|
||||
{
|
||||
namespace projection
|
||||
{
|
||||
|
||||
RemoteBluetoothDevice::RemoteBluetoothDevice(const std::string& address)
|
||||
: address_(address)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RemoteBluetoothDevice::stop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool RemoteBluetoothDevice::isPaired(const std::string&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemoteBluetoothDevice::pair(const std::string&, PairingPromise::Pointer promise)
|
||||
{
|
||||
promise->resolve();
|
||||
}
|
||||
|
||||
std::string RemoteBluetoothDevice::getLocalAddress() const
|
||||
{
|
||||
return address_;
|
||||
}
|
||||
|
||||
bool RemoteBluetoothDevice::isAvailable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -60,23 +60,29 @@ namespace f1x::openauto::autoapp::service::bluetooth {
|
||||
aap_protobuf::service::control::message::ServiceDiscoveryResponse &response) {
|
||||
OPENAUTO_LOG(info) << "[BluetoothService] fillFeatures()";
|
||||
|
||||
if (bluetoothDevice_->isAvailable()) {
|
||||
OPENAUTO_LOG(info) << "[BluetoothService] Local Address: " << bluetoothDevice_->getLocalAddress();
|
||||
auto *service = response.add_channels();
|
||||
service->set_id(static_cast<uint32_t>(channel_->getId()));
|
||||
|
||||
auto *service = response.add_channels();
|
||||
service->set_id(static_cast<uint32_t>(channel_->getId()));
|
||||
auto bluetooth = service->mutable_bluetooth_service();
|
||||
|
||||
auto bluetooth = service->mutable_bluetooth_service();
|
||||
// If the HU wants the MD to skip the Bluetooth Pairing and Connection process, the HU can declaire it's address as SKIP_THIS_BLUETOOTH
|
||||
bluetooth->set_car_address(bluetoothDevice_->getLocalAddress());
|
||||
if (bluetoothDevice_->isAvailable()) {
|
||||
OPENAUTO_LOG(info) << "[BluetoothService] Local Address: " << bluetoothDevice_->getAdapterAddress();
|
||||
|
||||
// AAP supports bth PIN and Numeric Comparison as pairing methods.
|
||||
bluetooth->add_supported_pairing_methods(aap_protobuf::service::bluetooth::message::BluetoothPairingMethod::BLUETOOTH_PAIRING_PIN);
|
||||
bluetooth->add_supported_pairing_methods(aap_protobuf::service::bluetooth::message::BluetoothPairingMethod::BLUETOOTH_PAIRING_NUMERIC_COMPARISON);
|
||||
} else {
|
||||
OPENAUTO_LOG(info) << "[BluetoothService] Bluetooth Not Available ";
|
||||
}
|
||||
}
|
||||
// TODO: Also need to re-establish Bluetooth
|
||||
// If the HU wants the MD to skip the Bluetooth Pairing and Connection process, the HU can declare its address as SKIP_THIS_BLUETOOTH
|
||||
bluetooth->set_car_address(bluetoothDevice_->getAdapterAddress());
|
||||
|
||||
// AAP supports bth PIN and Numeric Comparison as pairing methods.
|
||||
bluetooth->add_supported_pairing_methods(
|
||||
aap_protobuf::service::bluetooth::message::BluetoothPairingMethod::BLUETOOTH_PAIRING_PIN);
|
||||
bluetooth->add_supported_pairing_methods(
|
||||
aap_protobuf::service::bluetooth::message::BluetoothPairingMethod::BLUETOOTH_PAIRING_NUMERIC_COMPARISON);
|
||||
} else {
|
||||
OPENAUTO_LOG(info) << "[BluetoothService] Bluetooth Not Available ";
|
||||
bluetooth->set_car_address("");
|
||||
bluetooth->add_supported_pairing_methods(aap_protobuf::service::bluetooth::message::BluetoothPairingMethod::BLUETOOTH_PAIRING_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothService::onChannelOpenRequest(const aap_protobuf::service::control::message::ChannelOpenRequest &request) {
|
||||
|
@ -72,28 +72,18 @@ namespace f1x::openauto::autoapp::service {
|
||||
return serviceList;
|
||||
}
|
||||
|
||||
IService::Pointer ServiceFactory::createBluetoothService(aasdk::messenger::IMessenger::Pointer messenger) {
|
||||
OPENAUTO_LOG(info) << "[ServiceFactory] createBluetoothService()";
|
||||
projection::IBluetoothDevice::Pointer bluetoothDevice;
|
||||
switch (configuration_->getBluetoothAdapterType()) {
|
||||
case configuration::BluetoothAdapterType::LOCAL:
|
||||
OPENAUTO_LOG(info) << "[ServiceFactory] Using Local Bluetooth Adapter";
|
||||
bluetoothDevice = projection::IBluetoothDevice::Pointer(new projection::LocalBluetoothDevice(),
|
||||
std::bind(&QObject::deleteLater,
|
||||
std::placeholders::_1));
|
||||
break;
|
||||
|
||||
case configuration::BluetoothAdapterType::REMOTE:
|
||||
OPENAUTO_LOG(debug) << "[ServiceFactory] Using Remote Bluetooth Adapter";
|
||||
bluetoothDevice = std::make_shared<projection::RemoteBluetoothDevice>(
|
||||
configuration_->getBluetoothRemoteAdapterAddress());
|
||||
break;
|
||||
|
||||
default:
|
||||
OPENAUTO_LOG(debug) << "[ServiceFactory] Using Dummy Bluetooth";
|
||||
bluetoothDevice = std::make_shared<projection::DummyBluetoothDevice>();
|
||||
break;
|
||||
}
|
||||
IService::Pointer ServiceFactory::createBluetoothService(aasdk::messenger::IMessenger::Pointer messenger) {
|
||||
OPENAUTO_LOG(info) << "[ServiceFactory] createBluetoothService()";
|
||||
projection::IBluetoothDevice::Pointer bluetoothDevice;
|
||||
if (configuration_->getBluetoothAdapterAddress() == "") {
|
||||
OPENAUTO_LOG(debug) << "[ServiceFactory] Using Dummy Bluetooth";
|
||||
bluetoothDevice = std::make_shared<projection::DummyBluetoothDevice>();
|
||||
} else {
|
||||
OPENAUTO_LOG(info) << "[ServiceFactory] Using Local Bluetooth Adapter";
|
||||
bluetoothDevice = projection::IBluetoothDevice::Pointer(new projection::LocalBluetoothDevice(),
|
||||
std::bind(&QObject::deleteLater,
|
||||
std::placeholders::_1));
|
||||
}
|
||||
|
||||
return std::make_shared<bluetooth::BluetoothService>(ioService_, messenger, std::move(bluetoothDevice));
|
||||
}
|
||||
|
@ -49,61 +49,56 @@
|
||||
|
||||
namespace f1x::openauto::autoapp::ui {
|
||||
|
||||
SettingsWindow::SettingsWindow(configuration::IConfiguration::Pointer configuration, QWidget *parent)
|
||||
: QWidget(parent), ui_(new Ui::SettingsWindow), configuration_(std::move(configuration)) {
|
||||
ui_->setupUi(this);
|
||||
connect(ui_->pushButtonCancel, &QPushButton::clicked, this, &SettingsWindow::close);
|
||||
connect(ui_->pushButtonSave, &QPushButton::clicked, this, &SettingsWindow::onSave);
|
||||
connect(ui_->pushButtonUnpair, &QPushButton::clicked, this, &SettingsWindow::unpairAll);
|
||||
connect(ui_->pushButtonUnpair, &QPushButton::clicked, this, &SettingsWindow::close);
|
||||
connect(ui_->horizontalSliderScreenDPI, &QSlider::valueChanged, this, &SettingsWindow::onUpdateScreenDPI);
|
||||
connect(ui_->horizontalSliderAlphaTrans, &QSlider::valueChanged, this, &SettingsWindow::onUpdateAlphaTrans);
|
||||
connect(ui_->horizontalSliderDay, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightnessDay);
|
||||
connect(ui_->horizontalSliderNight, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightnessNight);
|
||||
connect(ui_->horizontalSliderBrightness1, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightness1);
|
||||
connect(ui_->horizontalSliderBrightness2, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightness2);
|
||||
connect(ui_->horizontalSliderBrightness3, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightness3);
|
||||
connect(ui_->horizontalSliderBrightness4, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightness4);
|
||||
connect(ui_->horizontalSliderBrightness5, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightness5);
|
||||
connect(ui_->horizontalSliderLux1, &QSlider::valueChanged, this, &SettingsWindow::onUpdateLux1);
|
||||
connect(ui_->horizontalSliderLux2, &QSlider::valueChanged, this, &SettingsWindow::onUpdateLux2);
|
||||
connect(ui_->horizontalSliderLux3, &QSlider::valueChanged, this, &SettingsWindow::onUpdateLux3);
|
||||
connect(ui_->horizontalSliderLux4, &QSlider::valueChanged, this, &SettingsWindow::onUpdateLux4);
|
||||
connect(ui_->horizontalSliderLux5, &QSlider::valueChanged, this, &SettingsWindow::onUpdateLux5);
|
||||
connect(ui_->radioButtonUseExternalBluetoothAdapter, &QRadioButton::clicked,
|
||||
[&](bool checked) { ui_->lineEditExternalBluetoothAdapterAddress->setEnabled(checked); });
|
||||
connect(ui_->radioButtonDisableBluetooth, &QRadioButton::clicked,
|
||||
[&]() { ui_->lineEditExternalBluetoothAdapterAddress->setEnabled(false); });
|
||||
connect(ui_->radioButtonUseLocalBluetoothAdapter, &QRadioButton::clicked,
|
||||
[&]() { ui_->lineEditExternalBluetoothAdapterAddress->setEnabled(false); });
|
||||
connect(ui_->pushButtonClearSelection, &QPushButton::clicked,
|
||||
std::bind(&SettingsWindow::setButtonCheckBoxes, this, false));
|
||||
connect(ui_->pushButtonSelectAll, &QPushButton::clicked,
|
||||
std::bind(&SettingsWindow::setButtonCheckBoxes, this, true));
|
||||
connect(ui_->pushButtonResetToDefaults, &QPushButton::clicked, this, &SettingsWindow::onResetToDefaults);
|
||||
connect(ui_->horizontalSliderSystemVolume, &QSlider::valueChanged, this,
|
||||
&SettingsWindow::onUpdateSystemVolume);
|
||||
connect(ui_->horizontalSliderSystemCapture, &QSlider::valueChanged, this,
|
||||
&SettingsWindow::onUpdateSystemCapture);
|
||||
connect(ui_->radioButtonHotspot, &QPushButton::clicked, this, &SettingsWindow::onStartHotspot);
|
||||
connect(ui_->radioButtonClient, &QPushButton::clicked, this, &SettingsWindow::onStopHotspot);
|
||||
connect(ui_->pushButtonSetTime, &QPushButton::clicked, this, &SettingsWindow::setTime);
|
||||
connect(ui_->pushButtonSetTime, &QPushButton::clicked, this, &SettingsWindow::close);
|
||||
connect(ui_->pushButtonNTP, &QPushButton::clicked, [&]() { system("/usr/local/bin/crankshaft rtc sync &"); });
|
||||
connect(ui_->pushButtonNTP, &QPushButton::clicked, this, &SettingsWindow::close);
|
||||
connect(ui_->pushButtonCheckNow, &QPushButton::clicked,
|
||||
[&]() { system("/usr/local/bin/crankshaft update check &"); });
|
||||
connect(ui_->pushButtonDebuglog, &QPushButton::clicked, this, &SettingsWindow::close);
|
||||
connect(ui_->pushButtonDebuglog, &QPushButton::clicked,
|
||||
[&]() { system("/usr/local/bin/crankshaft debuglog &"); });
|
||||
connect(ui_->pushButtonNetworkAuto, &QPushButton::clicked,
|
||||
[&]() { system("/usr/local/bin/crankshaft network auto &"); });
|
||||
connect(ui_->pushButtonNetwork0, &QPushButton::clicked, this, &SettingsWindow::on_pushButtonNetwork0_clicked);
|
||||
connect(ui_->pushButtonNetwork1, &QPushButton::clicked, this, &SettingsWindow::on_pushButtonNetwork1_clicked);
|
||||
connect(ui_->pushButtonSambaStart, &QPushButton::clicked,
|
||||
[&]() { system("/usr/local/bin/crankshaft samba start &"); });
|
||||
connect(ui_->pushButtonSambaStop, &QPushButton::clicked,
|
||||
[&]() { system("/usr/local/bin/crankshaft samba stop &"); });
|
||||
SettingsWindow::SettingsWindow(configuration::IConfiguration::Pointer configuration, QWidget *parent)
|
||||
: QWidget(parent), ui_(new Ui::SettingsWindow), configuration_(std::move(configuration)) {
|
||||
ui_->setupUi(this);
|
||||
connect(ui_->pushButtonCancel, &QPushButton::clicked, this, &SettingsWindow::close);
|
||||
connect(ui_->pushButtonSave, &QPushButton::clicked, this, &SettingsWindow::onSave);
|
||||
connect(ui_->pushButtonUnpair, &QPushButton::clicked, this, &SettingsWindow::unpairAll);
|
||||
connect(ui_->pushButtonUnpair, &QPushButton::clicked, this, &SettingsWindow::close);
|
||||
connect(ui_->horizontalSliderScreenDPI, &QSlider::valueChanged, this, &SettingsWindow::onUpdateScreenDPI);
|
||||
connect(ui_->horizontalSliderAlphaTrans, &QSlider::valueChanged, this, &SettingsWindow::onUpdateAlphaTrans);
|
||||
connect(ui_->horizontalSliderDay, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightnessDay);
|
||||
connect(ui_->horizontalSliderNight, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightnessNight);
|
||||
connect(ui_->horizontalSliderBrightness1, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightness1);
|
||||
connect(ui_->horizontalSliderBrightness2, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightness2);
|
||||
connect(ui_->horizontalSliderBrightness3, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightness3);
|
||||
connect(ui_->horizontalSliderBrightness4, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightness4);
|
||||
connect(ui_->horizontalSliderBrightness5, &QSlider::valueChanged, this, &SettingsWindow::onUpdateBrightness5);
|
||||
connect(ui_->horizontalSliderLux1, &QSlider::valueChanged, this, &SettingsWindow::onUpdateLux1);
|
||||
connect(ui_->horizontalSliderLux2, &QSlider::valueChanged, this, &SettingsWindow::onUpdateLux2);
|
||||
connect(ui_->horizontalSliderLux3, &QSlider::valueChanged, this, &SettingsWindow::onUpdateLux3);
|
||||
connect(ui_->horizontalSliderLux4, &QSlider::valueChanged, this, &SettingsWindow::onUpdateLux4);
|
||||
connect(ui_->horizontalSliderLux5, &QSlider::valueChanged, this, &SettingsWindow::onUpdateLux5);
|
||||
|
||||
connect(ui_->pushButtonClearSelection, &QPushButton::clicked,
|
||||
std::bind(&SettingsWindow::setButtonCheckBoxes, this, false));
|
||||
connect(ui_->pushButtonSelectAll, &QPushButton::clicked,
|
||||
std::bind(&SettingsWindow::setButtonCheckBoxes, this, true));
|
||||
connect(ui_->pushButtonResetToDefaults, &QPushButton::clicked, this, &SettingsWindow::onResetToDefaults);
|
||||
connect(ui_->horizontalSliderSystemVolume, &QSlider::valueChanged, this,
|
||||
&SettingsWindow::onUpdateSystemVolume);
|
||||
connect(ui_->horizontalSliderSystemCapture, &QSlider::valueChanged, this,
|
||||
&SettingsWindow::onUpdateSystemCapture);
|
||||
connect(ui_->radioButtonHotspot, &QPushButton::clicked, this, &SettingsWindow::onStartHotspot);
|
||||
connect(ui_->radioButtonClient, &QPushButton::clicked, this, &SettingsWindow::onStopHotspot);
|
||||
connect(ui_->pushButtonSetTime, &QPushButton::clicked, this, &SettingsWindow::setTime);
|
||||
connect(ui_->pushButtonSetTime, &QPushButton::clicked, this, &SettingsWindow::close);
|
||||
connect(ui_->pushButtonNTP, &QPushButton::clicked, [&]() { system("/usr/local/bin/crankshaft rtc sync &"); });
|
||||
connect(ui_->pushButtonNTP, &QPushButton::clicked, this, &SettingsWindow::close);
|
||||
connect(ui_->pushButtonCheckNow, &QPushButton::clicked,
|
||||
[&]() { system("/usr/local/bin/crankshaft update check &"); });
|
||||
connect(ui_->pushButtonDebuglog, &QPushButton::clicked, this, &SettingsWindow::close);
|
||||
connect(ui_->pushButtonDebuglog, &QPushButton::clicked,
|
||||
[&]() { system("/usr/local/bin/crankshaft debuglog &"); });
|
||||
connect(ui_->pushButtonNetworkAuto, &QPushButton::clicked,
|
||||
[&]() { system("/usr/local/bin/crankshaft network auto &"); });
|
||||
connect(ui_->pushButtonNetwork0, &QPushButton::clicked, this, &SettingsWindow::on_pushButtonNetwork0_clicked);
|
||||
connect(ui_->pushButtonNetwork1, &QPushButton::clicked, this, &SettingsWindow::on_pushButtonNetwork1_clicked);
|
||||
connect(ui_->pushButtonSambaStart, &QPushButton::clicked,
|
||||
[&]() { system("/usr/local/bin/crankshaft samba start &"); });
|
||||
connect(ui_->pushButtonSambaStop, &QPushButton::clicked,
|
||||
[&]() { system("/usr/local/bin/crankshaft samba stop &"); });
|
||||
|
||||
// menu
|
||||
ui_->tab1->show();
|
||||
@ -116,10 +111,8 @@ namespace f1x::openauto::autoapp::ui {
|
||||
ui_->tab8->hide();
|
||||
ui_->tab9->hide();
|
||||
|
||||
ui_->horizontalGroupBox->hide();
|
||||
ui_->labelBluetoothAdapterAddress->hide();
|
||||
ui_->lineEditExternalBluetoothAdapterAddress->hide();
|
||||
ui_->labelTestInProgress->hide();
|
||||
|
||||
ui_->labelTestInProgress->hide();
|
||||
|
||||
connect(ui_->pushButtonTab1, &QPushButton::clicked, this, &SettingsWindow::show_tab1);
|
||||
connect(ui_->pushButtonTab2, &QPushButton::clicked, this, &SettingsWindow::show_tab2);
|
||||
@ -201,14 +194,105 @@ namespace f1x::openauto::autoapp::ui {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void SettingsWindow::updateInfo() {
|
||||
if (ui_->tab6->isVisible() == true) {
|
||||
updateSystemInfo();
|
||||
}
|
||||
if (ui_->tab5->isVisible() == true) {
|
||||
updateNetworkInfo();
|
||||
}
|
||||
#ifdef Q_OS_LINUX
|
||||
void SettingsWindow::populateBluetoothComboBoxLinux(QComboBox *comboBoxBluetooth) {
|
||||
QList<QBluetoothHostInfo> adapters = QBluetoothLocalDevice::allDevices();
|
||||
|
||||
qDebug() << "Found" << adapters.count() << "Bluetooth adapters:";
|
||||
// Iterate over the adapters and print their information.
|
||||
comboBoxBluetooth->clear(); // Clear existing items
|
||||
|
||||
if (!adapters.isEmpty()) {
|
||||
for (const QBluetoothHostInfo &adapter: adapters) {
|
||||
QString adapterAddress = adapter.address().toString();
|
||||
comboBoxBluetooth->addItem(QCoreApplication::translate("SettingsWindow",
|
||||
QString("%1 (%2)").arg(adapter.name()).arg(
|
||||
adapterAddress).toUtf8().constData()),
|
||||
QVariant(adapterAddress));
|
||||
}
|
||||
} else {
|
||||
comboBoxBluetooth->addItem(QCoreApplication::translate("SettingsWindow", "none", nullptr));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef Q_OS_WIN
|
||||
void SettingsWindow::populateBluetoothComboBoxWindows(QComboBox *comboBoxBluetooth) {
|
||||
QProcess process;
|
||||
process.start("wmic",
|
||||
QStringList() << "path" << "Win32_PnPEntity" << "where" << "\"PNPDeviceID like '%BTHENUM%'\"" << "get"
|
||||
<< "Name,PNPDeviceID");
|
||||
process.waitForFinished(-1);
|
||||
|
||||
QString output = process.readAllStandardOutput();
|
||||
QStringList lines = output.split("\n", QString::SkipEmptyParts);
|
||||
|
||||
comboBoxBluetooth->clear(); // Clear existing items
|
||||
|
||||
int index = 0;
|
||||
for (auto line: lines) {
|
||||
if (line.contains("BTH", Qt::CaseInsensitive)) {
|
||||
QStringList parts = line.split(" ", QString::SkipEmptyParts);
|
||||
if (parts.count() >= 2) {
|
||||
QString name = parts[0].trimmed();
|
||||
QString address = parts[1].trimmed(); // This might not be an address in all cases
|
||||
comboBoxBluetooth->addItem(QCoreApplication::translate("SettingsWindow", QString("%1 (%2)").arg(name).arg(
|
||||
address).toUtf8().constData()), QVariant(address));
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Optionally, add "none" if no adapters were found
|
||||
if (index == 0) {
|
||||
comboBoxBluetooth->addItem(QCoreApplication::translate("SettingsWindow", "none", nullptr));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef Q_OS_MAC
|
||||
void SettingsWindow::populateBluetoothComboBoxMac(QComboBox *comboBoxBluetooth) {
|
||||
BluetoothAdapterLister lister;
|
||||
QStringList adapters = lister.listAdapters();
|
||||
|
||||
comboBoxBluetooth->clear(); // Clear existing items
|
||||
|
||||
if (adapters.isEmpty()) {
|
||||
comboBoxBluetooth->addItem(QCoreApplication::translate("SettingsWindow", "none", nullptr));
|
||||
} else {
|
||||
for (const QString &adapter: adapters) {
|
||||
QStringList parts = adapter.split(" (");
|
||||
if (parts.count() == 2) {
|
||||
QString name = parts[0];
|
||||
QString address = parts[1].left(parts[1].length() - 1); // Remove trailing ')'
|
||||
comboBoxBluetooth->addItem(QCoreApplication::translate("SettingsWindow", adapter.toUtf8().constData()),
|
||||
QVariant(address));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void SettingsWindow::populateBluetoothComboBox(QComboBox *comboBoxBluetooth) {
|
||||
#ifdef Q_OS_LINUX
|
||||
populateBluetoothComboBoxLinux(comboBoxBluetooth);
|
||||
#elif defined Q_OS_WIN
|
||||
populateBluetoothComboBoxWindows(comboBoxBluetooth);
|
||||
#elif defined Q_OS_MAC
|
||||
populateBluetoothComboBoxMac(comboBoxBluetooth);
|
||||
#else
|
||||
// Fallback for other platforms
|
||||
comboBoxBluetooth->clear();
|
||||
comboBoxBluetooth->addItem("Test");
|
||||
comboBoxBluetooth->addItem(QCoreApplication::translate("SettingsWindow", "none", nullptr));
|
||||
#endif
|
||||
}
|
||||
|
||||
void SettingsWindow::updateInfo() {
|
||||
if (ui_->tab6->isVisible() == true) {
|
||||
updateSystemInfo();
|
||||
}
|
||||
if (ui_->tab5->isVisible() == true) {
|
||||
updateNetworkInfo();
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsWindow::onSave() {
|
||||
configuration_->setHandednessOfTrafficType(
|
||||
@ -262,14 +346,11 @@ namespace f1x::openauto::autoapp::ui {
|
||||
ui_->comboBoxBluetooth->currentData().toString().toStdString());
|
||||
}
|
||||
|
||||
configuration_->setMusicAudioChannelEnabled(ui_->checkBoxMusicAudioChannel->isChecked());
|
||||
configuration_->setGuidanceAudioChannelEnabled(ui_->checkBoxSpeechAudioChannel->isChecked());
|
||||
configuration_->setTelephonyAudioChannelEnabled(ui_->checkBoxVoiceAudioChannel->isChecked());
|
||||
configuration_->setAudioOutputBackendType(
|
||||
ui_->radioButtonRtAudio->isChecked() ? configuration::AudioOutputBackendType::RTAUDIO
|
||||
: configuration::AudioOutputBackendType::QT);
|
||||
configuration_->setMusicAudioChannelEnabled(ui_->checkBoxMusicAudioChannel->isChecked());
|
||||
configuration_->setGuidanceAudioChannelEnabled(ui_->checkBoxSpeechAudioChannel->isChecked());
|
||||
//configuration_->setTelephonyAudioChannelEnabled(ui_->checkBoxVoiceAudioChannel->isChecked());
|
||||
// TODO: Add CheckBox In
|
||||
configuration_->setTelephonyAudioChannelEnabled(true);
|
||||
configuration_->setAudioOutputBackendType(
|
||||
ui_->radioButtonRtAudio->isChecked() ? configuration::AudioOutputBackendType::RTAUDIO
|
||||
: configuration::AudioOutputBackendType::QT);
|
||||
@ -541,20 +622,9 @@ namespace f1x::openauto::autoapp::ui {
|
||||
this->loadButtonCheckBoxes();
|
||||
ui_->checkBoxPlayerControl->setChecked(configuration_->playerButtonControl());
|
||||
|
||||
ui_->radioButtonDisableBluetooth->setChecked(
|
||||
configuration_->getBluetoothAdapterType() == configuration::BluetoothAdapterType::NONE);
|
||||
ui_->radioButtonUseLocalBluetoothAdapter->setChecked(
|
||||
configuration_->getBluetoothAdapterType() == configuration::BluetoothAdapterType::LOCAL);
|
||||
ui_->radioButtonUseExternalBluetoothAdapter->setChecked(
|
||||
configuration_->getBluetoothAdapterType() == configuration::BluetoothAdapterType::REMOTE);
|
||||
ui_->lineEditExternalBluetoothAdapterAddress->setEnabled(
|
||||
configuration_->getBluetoothAdapterType() == configuration::BluetoothAdapterType::REMOTE);
|
||||
ui_->lineEditExternalBluetoothAdapterAddress->setText(
|
||||
QString::fromStdString(configuration_->getBluetoothRemoteAdapterAddress()));
|
||||
|
||||
ui_->checkBoxMusicAudioChannel->setChecked(configuration_->musicAudioChannelEnabled());
|
||||
ui_->checkBoxSpeechAudioChannel->setChecked(configuration_->guidanceAudioChannelEnabled());
|
||||
ui_->telephonyAudioChannelEnabled->setChecked(configuration_->guidanceAudioChannelEnabled());
|
||||
ui_->checkBoxMusicAudioChannel->setChecked(configuration_->musicAudioChannelEnabled());
|
||||
ui_->checkBoxSpeechAudioChannel->setChecked(configuration_->guidanceAudioChannelEnabled());
|
||||
//ui_->telephonyAudioChannelEnabled->setChecked(configuration_->telephonyAudioChannelEnabled());
|
||||
|
||||
const auto &audioOutputBackendType = configuration_->getAudioOutputBackendType();
|
||||
ui_->radioButtonRtAudio->setChecked(audioOutputBackendType == configuration::AudioOutputBackendType::RTAUDIO);
|
||||
@ -1094,36 +1164,34 @@ namespace f1x::openauto::autoapp::ui {
|
||||
ui_->checkBoxFlipYUSB->setChecked(false);
|
||||
}
|
||||
|
||||
// set bluetooth
|
||||
if (configuration_->getCSValue("ENABLE_BLUETOOTH") == "1") {
|
||||
// check external bluetooth enabled
|
||||
if (configuration_->getCSValue("EXTERNAL_BLUETOOTH") == "1") {
|
||||
ui_->radioButtonUseExternalBluetoothAdapter->setChecked(true);
|
||||
} else {
|
||||
ui_->radioButtonUseLocalBluetoothAdapter->setChecked(true);
|
||||
}
|
||||
// mac
|
||||
//ui_->lineEditExternalBluetoothAdapterAddress->setText(getparams[37]);
|
||||
} else {
|
||||
ui_->radioButtonDisableBluetooth->setChecked(true);
|
||||
ui_->lineEditExternalBluetoothAdapterAddress->setText("");
|
||||
}
|
||||
if (configuration_->getCSValue("ENABLE_PAIRABLE") == "1") {
|
||||
ui_->checkBoxBluetoothAutoPair->setChecked(true);
|
||||
} else {
|
||||
ui_->checkBoxBluetoothAutoPair->setChecked(false);
|
||||
}
|
||||
// set bluetooth type
|
||||
if (configuration_->getCSValue("ENABLE_BLUETOOTH") == "1") {
|
||||
QString bt = configuration_->getParamFromFile("/boot/config.txt", "dtoverlay=pi3-disable-bt");
|
||||
if (bt.contains("pi3-disable-bt")) {
|
||||
ui_->comboBoxBluetooth->setCurrentText("external");
|
||||
} else {
|
||||
ui_->comboBoxBluetooth->setCurrentText("builtin");
|
||||
}
|
||||
} else {
|
||||
ui_->comboBoxBluetooth->setCurrentText("none");
|
||||
}
|
||||
if (configuration_->getCSValue("ENABLE_PAIRABLE") == "1") {
|
||||
ui_->checkBoxBluetoothAutoPair->setChecked(true);
|
||||
} else {
|
||||
ui_->checkBoxBluetoothAutoPair->setChecked(false);
|
||||
}
|
||||
// set bluetooth type
|
||||
if (configuration_->getCSValue("ENABLE_BLUETOOTH") == "1") {
|
||||
QString bt = configuration_->getParamFromFile("/boot/config.txt", "dtoverlay=pi3-disable-bt");
|
||||
|
||||
QString selectedAddress = QString::fromStdString(
|
||||
configuration_->getBluetoothAdapterAddress()); //.value("BluetoothAdapterAddress", "none").toString();
|
||||
|
||||
// Iterate through the items to find the one with the matching data
|
||||
bool found = false;
|
||||
for (int i = 0; i < ui_->comboBoxBluetooth->count(); ++i) {
|
||||
if (ui_->comboBoxBluetooth->itemData(i).toString() == selectedAddress) {
|
||||
ui_->comboBoxBluetooth->setCurrentIndex(i);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
ui_->comboBoxBluetooth->setCurrentIndex(ui_->comboBoxBluetooth->findText("none"));
|
||||
}
|
||||
} else {
|
||||
ui_->comboBoxBluetooth->setCurrentText("none");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -2754,51 +2754,6 @@ QSlider::groove:horizontal { background: #6d6d6d; height: 32px;}</string>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="horizontalGroupBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Bluetooth Adapter</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_32">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonDisableBluetooth">
|
||||
<property name="text">
|
||||
<string>Disable bluetooth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonUseLocalBluetoothAdapter">
|
||||
<property name="text">
|
||||
<string>Use local adapter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonUseExternalBluetoothAdapter">
|
||||
<property name="text">
|
||||
<string>Use external adapter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxBluetoothAdapter">
|
||||
<property name="sizePolicy">
|
||||
@ -2932,47 +2887,6 @@ outline: none;</string>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelBluetoothAdapterAddress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Used Address:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEditExternalBluetoothAdapterAddress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -8897,21 +8811,6 @@ QComboBox::item:selected {
|
||||
min-height: 32px;
|
||||
}</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>none</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>builtin</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>external</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
Loading…
x
Reference in New Issue
Block a user