Zhang Qipeng 4013fe035c fix: 蓝牙列表排序问题
用 push_front 应先将未连接设备从头插入,再将已连接设备从头插入,保证最终的列表中,已连接设备在最前面。

Log: 修复蓝牙列表排序问题。
Bug: https://pms.uniontech.com/zentao/bug-view-58098.html
Change-Id: I35219ea97181a8889cec91b1b2d0293511acbb6f
2020-12-22 21:45:25 +08:00

345 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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);
}