mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-04 09:23:03 +00:00

用 push_front 应先将未连接设备从头插入,再将已连接设备从头插入,保证最终的列表中,已连接设备在最前面。 Log: 修复蓝牙列表排序问题。 Bug: https://pms.uniontech.com/zentao/bug-view-58098.html Change-Id: I35219ea97181a8889cec91b1b2d0293511acbb6f
345 lines
11 KiB
C++
345 lines
11 KiB
C++
/*
|
||
* Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd.
|
||
*
|
||
* Author: zhaolong <zhaolong@uniontech.com>
|
||
*
|
||
* Maintainer: zhaolong <zhaolong@uniontech.com>
|
||
*
|
||
*
|
||
* This program 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
|
||
* any later version.
|
||
*
|
||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#include "adapteritem.h"
|
||
#include "switchitem.h"
|
||
#include "deviceitem.h"
|
||
#include "adapter.h"
|
||
#include "adaptersmanager.h"
|
||
#include "bluetoothconstants.h"
|
||
|
||
#include <QLabel>
|
||
#include <QVBoxLayout>
|
||
|
||
extern void initFontColor(QWidget *widget);
|
||
|
||
AdapterItem::AdapterItem(AdaptersManager *adapterManager, Adapter *adapter, QWidget *parent)
|
||
: QScrollArea(parent)
|
||
, m_centralWidget(new QWidget(this))
|
||
, m_line(new HorizontalSeparator(this))
|
||
, m_deviceLayout(new QVBoxLayout)
|
||
, m_adaptersManager(adapterManager)
|
||
, m_adapter(adapter)
|
||
, m_switchItem(new SwitchItem(this))
|
||
{
|
||
m_centralWidget->setFixedWidth(POPUPWIDTH);
|
||
m_line->setVisible(true);
|
||
m_deviceLayout->setMargin(0);
|
||
m_deviceLayout->setSpacing(0);
|
||
|
||
m_switchItem->setTitle(adapter->name());
|
||
m_switchItem->setChecked(adapter->powered(),false);
|
||
m_switchItem->setLoading(adapter->discover());
|
||
|
||
m_deviceLayout->addWidget(m_switchItem, Qt::AlignCenter);
|
||
m_deviceLayout->addWidget(m_line);
|
||
m_centralWidget->setFixedWidth(POPUPWIDTH);
|
||
m_centralWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||
m_centralWidget->setLayout(m_deviceLayout);
|
||
|
||
setFixedWidth(POPUPWIDTH);
|
||
setWidget(m_centralWidget);
|
||
setFrameShape(QFrame::NoFrame);
|
||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||
m_centralWidget->setAutoFillBackground(false);
|
||
viewport()->setAutoFillBackground(false);
|
||
|
||
QMap<QString, const Device *> myDevices = adapter->devices();
|
||
for (const Device *constDevice : myDevices) {
|
||
auto device = const_cast<Device *>(constDevice);
|
||
if (device)
|
||
createDeviceItem(device);
|
||
}
|
||
|
||
m_initDeviceState = Device::StateUnavailable;
|
||
for (const Device *constDevice : myDevices) {
|
||
auto device = const_cast<Device *>(constDevice);
|
||
if (device) {
|
||
if (device->state() == Device::StateAvailable) {
|
||
m_initDeviceState = Device::StateAvailable;
|
||
continue;
|
||
}
|
||
if (device->state() == Device::StateConnected && device->connectState()) {
|
||
m_initDeviceState = Device::StateConnected;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
connect(m_switchItem, &SwitchItem::checkedChanged, this, &AdapterItem::showAndConnect);
|
||
connect(m_switchItem, &SwitchItem::refresh, this, &AdapterItem::refresh);
|
||
connect(m_switchItem, &SwitchItem::justUpdateView, [&](bool checked){
|
||
showDevices(checked);
|
||
emit powerChanged(checked);
|
||
});
|
||
connect(adapter, &Adapter::nameChanged, m_switchItem, &SwitchItem::setTitle);
|
||
connect(adapter, &Adapter::deviceAdded, this, &AdapterItem::addDeviceItem);
|
||
connect(adapter, &Adapter::deviceRemoved, this, &AdapterItem::removeDeviceItem);
|
||
connect(adapter, &Adapter::poweredChanged, m_switchItem, [=](const bool powered){
|
||
m_switchItem->setChecked(powered, false);
|
||
});
|
||
|
||
connect(adapter, &Adapter::discoveringChanged, m_switchItem, [=](const bool discovering){
|
||
m_switchItem->setLoading(discovering);
|
||
});
|
||
|
||
showDevices(adapter->powered());
|
||
}
|
||
|
||
int AdapterItem::deviceCount()
|
||
{
|
||
return m_deviceItems.size();
|
||
}
|
||
|
||
void AdapterItem::setPowered(bool powered)
|
||
{
|
||
m_switchItem->setChecked(powered,true);
|
||
}
|
||
|
||
bool AdapterItem::isPowered()
|
||
{
|
||
return m_switchItem->checkState();
|
||
}
|
||
|
||
QStringList AdapterItem::connectedDevsName()
|
||
{
|
||
QStringList devsName;
|
||
for (DeviceItem *devItem : m_sortConnected) {
|
||
if (devItem) {
|
||
devsName << devItem->title();
|
||
}
|
||
}
|
||
|
||
return devsName;
|
||
}
|
||
|
||
void AdapterItem::deviceItemPaired(const bool paired)
|
||
{
|
||
auto device = qobject_cast<Device *>(sender());
|
||
if (device) {
|
||
DeviceItem *deviceItem = m_deviceItems.value(device->id());
|
||
if (paired) {
|
||
int index = m_sortConnected.indexOf(deviceItem);
|
||
|
||
if (index < 0) {
|
||
m_sortUnConnect.removeOne(deviceItem);
|
||
m_sortConnected << deviceItem;
|
||
}
|
||
} else {
|
||
int index = m_sortUnConnect.indexOf(deviceItem);
|
||
|
||
if(index < 0){
|
||
m_sortConnected.removeOne(deviceItem);
|
||
m_sortUnConnect << deviceItem;
|
||
}
|
||
}
|
||
showDevices(m_adapter->powered());
|
||
}
|
||
}
|
||
|
||
void AdapterItem::removeDeviceItem(const Device *device)
|
||
{
|
||
if (!device)
|
||
return;
|
||
|
||
DeviceItem *deviceItem = m_deviceItems.value(device->id());
|
||
if (deviceItem) {
|
||
m_deviceItems.remove(device->id());
|
||
m_sortConnected.removeOne(deviceItem);
|
||
m_sortUnConnect.removeOne(deviceItem);
|
||
m_deviceLayout->removeWidget(deviceItem);
|
||
delete deviceItem;
|
||
}
|
||
showDevices(m_adapter->powered());
|
||
}
|
||
|
||
void AdapterItem::showAndConnect(bool change)
|
||
{
|
||
m_adaptersManager->setAdapterPowered(m_adapter, change);
|
||
showDevices(change);
|
||
emit powerChanged(change);
|
||
}
|
||
|
||
void AdapterItem::addDeviceItem(const Device *constDevice)
|
||
{
|
||
auto device = const_cast<Device *>(constDevice);
|
||
if (!device)
|
||
return;
|
||
|
||
createDeviceItem(device);
|
||
showDevices(m_adapter->powered());
|
||
}
|
||
|
||
void AdapterItem::deviceChangeState(const Device::State state)
|
||
{
|
||
auto device = qobject_cast<Device *>(sender());
|
||
|
||
auto setUnavailableItem = [this](const Device::State state, DeviceItem *deviceItem){
|
||
int index = m_sortUnConnect.indexOf(deviceItem);
|
||
if (index < 0) {
|
||
m_sortConnected.removeOne(deviceItem);
|
||
m_sortUnConnect << deviceItem;
|
||
moveDeviceItem(state, deviceItem);
|
||
}
|
||
};
|
||
|
||
if (device) {
|
||
DeviceItem *deviceItem = m_deviceItems.value(device->id());
|
||
if (deviceItem) {
|
||
switch (state) {
|
||
case Device::StateUnavailable: {
|
||
setUnavailableItem(state, deviceItem);
|
||
}
|
||
break;
|
||
case Device::StateAvailable: {
|
||
int index = m_sortUnConnect.indexOf(deviceItem);
|
||
if (index < 0)
|
||
m_sortConnected.removeOne(deviceItem);
|
||
}
|
||
break;
|
||
case Device::StateConnected: {
|
||
if (!device->connectState()) {
|
||
setUnavailableItem(state, deviceItem);
|
||
break;
|
||
}
|
||
int index = m_sortConnected.indexOf(deviceItem);
|
||
if (index < 0) {
|
||
m_sortUnConnect.removeOne(deviceItem);
|
||
m_sortConnected << deviceItem;
|
||
moveDeviceItem(state, deviceItem);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (m_sortConnected.size() > 0)
|
||
m_currentDeviceState = Device::StateConnected;
|
||
else if (state == Device::StateAvailable)
|
||
m_currentDeviceState = Device::StateAvailable;
|
||
else
|
||
m_currentDeviceState = Device::StateUnavailable;
|
||
|
||
emit deviceStateChanged();
|
||
}
|
||
}
|
||
|
||
void AdapterItem::moveDeviceItem(Device::State state, DeviceItem *item)
|
||
{
|
||
int size = m_sortConnected.size();
|
||
int index = 0;
|
||
switch (state) {
|
||
case Device::StateUnavailable:
|
||
case Device::StateAvailable: {
|
||
index = m_sortUnConnect.indexOf(item);
|
||
index += size;
|
||
}
|
||
break;
|
||
case Device::StateConnected: {
|
||
index = m_sortUnConnect.indexOf(item);
|
||
}
|
||
break;
|
||
}
|
||
index += 2;
|
||
m_deviceLayout->removeWidget(item);
|
||
m_deviceLayout->insertWidget(index, item);
|
||
}
|
||
|
||
void AdapterItem::createDeviceItem(Device *device)
|
||
{
|
||
if (!device)
|
||
return;
|
||
|
||
QString deviceId = device->id();
|
||
auto deviceItem = new DeviceItem(device, this);
|
||
m_deviceItems[deviceId] = deviceItem;
|
||
if (device->state() == Device::StateConnected)
|
||
m_sortConnected << deviceItem;
|
||
else
|
||
m_sortUnConnect << deviceItem;
|
||
|
||
connect(device, &Device::pairedChanged, this, &AdapterItem::deviceItemPaired);
|
||
connect(device, &Device::nameChanged, deviceItem, &DeviceItem::setTitle);
|
||
connect(device, &Device::stateChanged, deviceItem, &DeviceItem::changeState);
|
||
connect(device, &Device::stateChanged, this, &AdapterItem::deviceChangeState);
|
||
connect(deviceItem, &DeviceItem::clicked, m_adaptersManager, [this, deviceItem](Device *device) {
|
||
m_adaptersManager->connectDevice(device, m_adapter);
|
||
m_deviceLayout->removeWidget(deviceItem);
|
||
m_deviceLayout->insertWidget(1, deviceItem);
|
||
});
|
||
}
|
||
|
||
void AdapterItem::updateView()
|
||
{
|
||
int contentHeight = m_switchItem->height();
|
||
contentHeight += (m_deviceLayout->count() - 2) * ITEMHEIGHT;
|
||
m_centralWidget->setFixedHeight(contentHeight);
|
||
setFixedHeight(contentHeight);
|
||
emit sizeChange();
|
||
}
|
||
|
||
void AdapterItem::showDevices(bool powered)
|
||
{
|
||
QList<DeviceItem *> deviceItems;
|
||
for (DeviceItem *deviceItem : m_sortUnConnect) {
|
||
deviceItems.push_front(deviceItem); // 未连接设备倒序放进list里
|
||
}
|
||
for (DeviceItem *deviceItem : m_sortConnected) {
|
||
deviceItems.push_front(deviceItem); // 已连接设备倒序放进list里
|
||
}
|
||
|
||
// 在蓝牙关闭的时候,会出现不在connected和Unconnect列表中的设备(连接/关闭中的状态),关闭的时候使用总表参数
|
||
qDebug() << m_sortConnected.size() << m_sortUnConnect.size() << m_deviceItems.size();
|
||
if (powered) {
|
||
for (DeviceItem *deviceItem : deviceItems) {
|
||
if (deviceItem) {
|
||
m_deviceLayout->addWidget(deviceItem);
|
||
deviceItem->setVisible(powered);
|
||
}
|
||
}
|
||
} else {
|
||
for (DeviceItem *deviceItem : m_deviceItems) {
|
||
if (deviceItem) {
|
||
m_deviceLayout->removeWidget(deviceItem);
|
||
deviceItem->setVisible(powered);
|
||
}
|
||
}
|
||
|
||
for (DeviceItem *deviceItem : m_sortConnected) {
|
||
if (deviceItem) {
|
||
m_adaptersManager->disconnectDevice(deviceItem->device());
|
||
}
|
||
}
|
||
}
|
||
|
||
m_line->setVisible(powered);
|
||
updateView();
|
||
}
|
||
|
||
void AdapterItem::refresh()
|
||
{
|
||
if (m_adapter->discover())
|
||
return;
|
||
m_adaptersManager->adapterRefresh(m_adapter);
|
||
}
|