fix: 完善音量功能

1、只要存在音量设备,就显示设备列表
2、当设备在控制中心被禁用后,快捷面板音量滑块不可调节,并且变灰显示

Log: 完善音量功能
Influence: 从控制中心关闭设备,观察任务栏设备状态是否发生变化
Bug: https://pms.uniontech.com/bug-view-172429.html
Change-Id: Ib98f77f49998d6f55f9ad69a18e7fbb30081acf1
This commit is contained in:
donghualin 2022-11-28 14:01:16 +08:00
parent 4386f13cd9
commit 6bcaead473
5 changed files with 100 additions and 84 deletions

View File

@ -44,6 +44,10 @@ DWIDGET_USE_NAMESPACE
#define HEADERHEIGHT 30
#define ITEMSPACE 16
#define ROWSPACE 10
#define DESCRIPTIONHEIGHT 15
#define ITEMRADIUS 12
#define SLIDERHEIGHT 36
#define AUDIOPORT 0
#define AUDIOSETTING 1
@ -60,15 +64,13 @@ SoundDevicesWidget::SoundDevicesWidget(QWidget *parent)
, m_sinkInter(new DBusSink("org.deepin.daemon.Audio1", m_soundInter->defaultSink().path(), QDBusConnection::sessionBus(), this))
, m_model(new QStandardItemModel(this))
, m_delegate(new SettingDelegate(m_deviceList))
, m_lastPort(nullptr)
{
initUi();
initConnection();
onAudioDevicesChanged();
m_sliderParent->installEventFilter(this);
QMetaObject::invokeMethod(this, [ this ] {
resetVolumeInfo();
deviceEnabled(m_ports.size() > 0);
resizeHeight();
}, Qt::QueuedConnection);
}
@ -98,7 +100,7 @@ void SoundDevicesWidget::initUi()
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(6);
m_sliderParent->setFixedHeight(36);
m_sliderParent->setFixedHeight(SLIDERHEIGHT);
QHBoxLayout *sliderLayout = new QHBoxLayout(m_sliderParent);
sliderLayout->setContentsMargins(11, 0, 11, 0);
@ -119,22 +121,22 @@ void SoundDevicesWidget::initUi()
topLayout->addWidget(m_sliderParent);
layout->addLayout(topLayout);
layout->addSpacing(4);
layout->addWidget(m_descriptionLabel);
m_deviceList->setModel(m_model);
m_deviceList->setViewMode(QListView::ListMode);
m_deviceList->setMovement(QListView::Free);
m_deviceList->setItemRadius(12);
m_deviceList->setItemRadius(ITEMRADIUS);
m_deviceList->setWordWrap(false);
m_deviceList->verticalScrollBar()->setVisible(false);
m_deviceList->horizontalScrollBar()->setVisible(false);
m_deviceList->setOrientation(QListView::Flow::TopToBottom, false);
layout->addWidget(m_deviceList);
m_deviceList->setSpacing(10);
m_deviceList->setSpacing(ROWSPACE);
m_deviceList->setItemDelegate(m_delegate);
m_model->setSortRole(sortRole);
m_descriptionLabel->setFixedHeight(DESCRIPTIONHEIGHT);
// 增加音量设置
DStandardItem *settingItem = new DStandardItem;
@ -143,6 +145,8 @@ void SoundDevicesWidget::initUi()
settingItem->setData(false, itemCheckRole);
settingItem->setData(AUDIOSETTING, itemFlagRole);
m_model->appendRow(settingItem);
m_sliderParent->installEventFilter(this);
}
void SoundDevicesWidget::onAudioDevicesChanged()
@ -150,61 +154,55 @@ void SoundDevicesWidget::onAudioDevicesChanged()
QMap<uint, QStringList> tmpCardIds;
const QString cards = m_soundInter->cardsWithoutUnavailable();
QJsonDocument doc = QJsonDocument::fromJson(cards.toUtf8());
QJsonArray jCards = doc.array();
for (QJsonValue cV : jCards) {
QJsonObject jCard = cV.toObject();
const uint cardId = jCard["Id"].toInt();
const QString cardName = jCard["Name"].toString();
QJsonArray jPorts = jCard["Ports"].toArray();
QJsonArray jCards = doc.array();
for (QJsonValue cV : jCards) {
QJsonObject jCard = cV.toObject();
const uint cardId = jCard["Id"].toInt();
const QString cardName = jCard["Name"].toString();
QJsonArray jPorts = jCard["Ports"].toArray();
QStringList tmpPorts;
QStringList tmpPorts;
for (QJsonValue pV : jPorts) {
QJsonObject jPort = pV.toObject();
const double portAvai = jPort["Available"].toDouble();
if (portAvai == 2 || portAvai == 0 ) {
const QString portId = jPort["Name"].toString();
const QString portName = jPort["Description"].toString();
for (QJsonValue pV : jPorts) {
QJsonObject jPort = pV.toObject();
const double portAvai = jPort["Available"].toDouble();
if (portAvai != 2 && portAvai != 0 )
continue;
SoundDevicePort *port = findPort(portId, cardId);
bool includePort = (port != nullptr);
if (!port)
port = new SoundDevicePort(m_model);
const QString portId = jPort["Name"].toString();
const QString portName = jPort["Description"].toString();
port->setId(portId);
port->setName(portName);
port->setDirection(SoundDevicePort::Direction(jPort["Direction"].toDouble()));
port->setCardId(cardId);
port->setCardName(cardName);
SoundDevicePort *port = findPort(portId, cardId);
bool includePort = (port != nullptr);
if (!port)
port = new SoundDevicePort(m_model);
if (!includePort)
startAddPort(port);
port->setId(portId);
port->setName(portName);
port->setDirection(SoundDevicePort::Direction(jPort["Direction"].toDouble()));
port->setCardId(cardId);
port->setCardName(cardName);
tmpPorts << portId;
}
}
tmpCardIds.insert(cardId, tmpPorts);
if (!includePort)
startAddPort(port);
tmpPorts << portId;
}
tmpCardIds.insert(cardId, tmpPorts);
}
onDefaultSinkChanged(m_soundInter->defaultSink());//重新获取切换的设备信息
// 重新获取切换的设备信息
onDefaultSinkChanged(m_soundInter->defaultSink());
for (SoundDevicePort *port : m_ports) {
//只要有一个设备在控制中心被禁用后,在任务栏声音设备列表中该设备会被移除,
if (!m_soundInter->IsPortEnabled(port->cardId(), port->id())) {
removeDisabledDevice(port->id(), port->cardId());
}
//判断端口是否在最新的设备列表中
if (tmpCardIds.contains(port->cardId())) {
if (!tmpCardIds[port->cardId()].contains(port->id())) {
startRemovePort(port->id(), port->cardId());
}
}
else {
startRemovePort(port->id(), port->cardId());
}
}
//当只有一个设备剩余时,该设备也需要移除
removeLastDevice();
for (SoundDevicePort *port : m_ports) {
// 只要有一个设备在控制中心被禁用后,在任务栏声音设备列表中该设备会被移除,
if (!m_soundInter->IsPortEnabled(port->cardId(), port->id()))
removeDisabledDevice(port->id(), port->cardId());
// 判断端口是否在最新的设备列表中
if (!tmpCardIds.contains(port->cardId()) || !tmpCardIds[port->cardId()].contains(port->id()))
startRemovePort(port->id(), port->cardId());
}
}
void SoundDevicesWidget::initConnection()
@ -288,6 +286,10 @@ void SoundDevicesWidget::addPort(const SoundDevicePort *port)
}
m_model->sort(0);
if (m_ports.size() == 1)
deviceEnabled(true);
resizeHeight();
}
void SoundDevicesWidget::removePort(const QString &portId, const uint &cardId)
@ -307,6 +309,11 @@ void SoundDevicesWidget::removePort(const QString &portId, const uint &cardId)
if (removeRow >= 0)
m_model->removeRow(removeRow);
if (m_ports.size() == 0)
deviceEnabled(false);
resizeHeight();
}
void SoundDevicesWidget::activePort(const QString &portId, const uint &cardId)
@ -315,20 +322,6 @@ void SoundDevicesWidget::activePort(const QString &portId, const uint &cardId)
it->setIsActive(it->id() == portId && it->cardId() == cardId);
}
void SoundDevicesWidget::removeLastDevice()
{
if (m_ports.count() == 1 && m_ports.at(0)) {
m_lastPort = new SoundDevicePort(m_model);
m_lastPort->setId(m_ports.at(0)->id());
m_lastPort->setName(m_ports.at(0)->name());
m_lastPort->setDirection(m_ports.at(0)->direction());
m_lastPort->setCardId(m_ports.at(0)->cardId());
m_lastPort->setCardName(m_ports.at(0)->cardName());
startRemovePort(m_ports.at(0)->id(), m_ports.at(0)->cardId());
qDebug() << "remove last output device";
}
}
void SoundDevicesWidget::removeDisabledDevice(QString portId, unsigned int cardId)
{
startRemovePort(portId, cardId);
@ -338,6 +331,12 @@ void SoundDevicesWidget::removeDisabledDevice(QString portId, unsigned int cardI
}
}
void SoundDevicesWidget::deviceEnabled(bool enable)
{
m_sliderContainer->setEnabled(enable);
Q_EMIT enableChanged(enable);
}
QString SoundDevicesWidget::leftIcon()
{
QString iconLeft = QString(":/icons/resources/audio-volume-%1").arg(m_sinkInter->mute() ? "muted" : "low");
@ -366,7 +365,14 @@ const QString SoundDevicesWidget::soundIconFile() const
void SoundDevicesWidget::resizeHeight()
{
m_deviceList->adjustSize();
int deviceListHeight = 0;
for (int i = 0; i < m_model->rowCount(); i++) {
QModelIndex index = m_model->index(i, 0);
deviceListHeight += m_deviceList->visualRect(index).height() + m_deviceList->spacing() * 2;
if (i >= 9) // 最大显示12个条目包含标题、滑块和设备标题、设备列表因此设备列表最多显示9个条目
break;
}
m_deviceList->setFixedHeight(deviceListHeight);
QMargins m = layout()->contentsMargins();
int height = m.top() + m.bottom() + HEADERHEIGHT + m_sliderContainer->height() + ITEMSPACE
+ m_descriptionLabel->height() + m_deviceList->height();
@ -453,10 +459,6 @@ void SoundDevicesWidget::onDefaultSinkChanged(const QDBusObjectPath &value)
QString portId = m_sinkInter->activePort().name;
uint cardId = m_sinkInter->card();
//最后一个设备会被移除,但是当在控制中心选中此设备后需要添加,并勾选
if (m_lastPort && m_lastPort->cardId() == cardId && m_lastPort->id() == portId)
startAddPort(m_lastPort);
activePort(portId, cardId);
for (int i = 0; i < m_model->rowCount() ; i++) {

View File

@ -51,6 +51,9 @@ public:
explicit SoundDevicesWidget(QWidget *parent = nullptr);
~SoundDevicesWidget() override;
Q_SIGNALS:
void enableChanged(bool);
protected:
bool eventFilter(QObject *watcher, QEvent *event) override;
@ -75,9 +78,10 @@ private:
void activePort(const QString &portId, const uint &cardId);
void removeLastDevice();
void removeDisabledDevice(QString portId, unsigned int cardId);
void deviceEnabled(bool enable);
private Q_SLOTS:
void onSelectIndexChanged(const QModelIndex &index);
void onDefaultSinkChanged(const QDBusObjectPath & value);
@ -93,7 +97,6 @@ private:
QStandardItemModel *m_model;
SettingDelegate *m_delegate;
QList<SoundDevicePort *> m_ports;
SoundDevicePort *m_lastPort;
};
#endif // VOLUMEDEVICESWIDGET_H

View File

@ -66,6 +66,8 @@ void SoundPlugin::init(PluginProxyInterface *proxyInter)
proxyInter->requestSetAppletVisible(this, QUICK_ITEM_KEY, true);
});
}
connect(m_soundDeviceWidget.data(), &SoundDevicesWidget::enableChanged, m_soundWidget.data(), &SoundWidget::setEnabled);
}
void SoundPlugin::pluginStateSwitched()

View File

@ -239,29 +239,36 @@ void SliderProxyStyle::drawComplexControl(QStyle::ComplexControl control, const
QRect rectGroove = subControlRect(CC_Slider, sliderOption, SC_SliderGroove, widget);
QRect rectHandle = subControlRect(CC_Slider, sliderOption, SC_SliderHandle, widget);
if (m_drawSpecial == RoundHandler)
drawRoundSlider(painter, rectGroove, rectHandle);
drawRoundSlider(painter, rectGroove, rectHandle, widget);
else
drawNormalSlider(painter, rectGroove, rectHandle, const_cast<QWidget *>(widget));
drawNormalSlider(painter, rectGroove, rectHandle, widget);
painter->restore();
}
// 绘制通用的滑动条
void SliderProxyStyle::drawNormalSlider(QPainter *painter, QRect rectGroove, QRect rectHandle, QWidget *wigdet) const
void SliderProxyStyle::drawNormalSlider(QPainter *painter, QRect rectGroove, QRect rectHandle, const QWidget *wigdet) const
{
DPalette dpa = DPaletteHelper::instance()->palette(wigdet);
QPen penLine = QPen(dpa.color(DPalette::Highlight), 2);
QColor color = dpa.color(DPalette::Highlight);
QColor rightColor(Qt::gray);
if (!wigdet->isEnabled()) {
color.setAlphaF(0.8);
rightColor.setAlphaF(0.8);
}
QPen penLine = QPen(color, 2);
// 绘制上下的竖线一根竖线的宽度是2+4个像素刚好保证中间也是间隔2个像素
for (int i = rectGroove.x(); i < rectGroove.x() + rectGroove.width(); i = i + 4) {
if (i < rectHandle.x())
painter->setPen(penLine);
else
painter->setPen(QPen(Qt::gray, 2));
painter->setPen(QPen(rightColor, 2));
painter->drawLine(i, rectGroove.y() + 2, i, rectGroove.y() + rectGroove.height() - 2);
}
// 绘制滚动区域
painter->setBrush(dpa.color(DPalette::Highlight));
painter->setBrush(color);
painter->setPen(Qt::NoPen);
QPainterPath path;
path.addRoundedRect(rectHandle, 6, 6);
@ -269,10 +276,12 @@ void SliderProxyStyle::drawNormalSlider(QPainter *painter, QRect rectGroove, QRe
}
// 绘制设计师定义的那种圆形滑块,黑色的滑条
void SliderProxyStyle::drawRoundSlider(QPainter *painter, QRect rectGroove, QRect rectHandle) const
void SliderProxyStyle::drawRoundSlider(QPainter *painter, QRect rectGroove, QRect rectHandle, const QWidget *wigdet) const
{
// 深色背景下,滑块和滑动条白色,浅色背景下,滑块和滑动条黑色
QBrush brush(DGuiApplicationHelper::DarkType == DGuiApplicationHelper::instance()->themeType() ? Qt::white : Qt::black);
QColor color = wigdet->isEnabled() ? (DGuiApplicationHelper::DarkType == DGuiApplicationHelper::instance()->themeType() ? Qt::white : Qt::black) : Qt::gray;
QBrush brush(color);
// 此处中绘制圆形滑动条,需要绘制圆角,圆角大小为其高度的一半
QPainterPath pathGroove;
int radius = rectGroove.height() / 2;

View File

@ -100,8 +100,8 @@ protected:
void drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = nullptr) const override;
private:
void drawNormalSlider(QPainter *painter, QRect rectGroove, QRect rectHandle, QWidget *wigdet) const;
void drawRoundSlider(QPainter *painter, QRect rectGroove, QRect rectHandle) const;
void drawNormalSlider(QPainter *painter, QRect rectGroove, QRect rectHandle, const QWidget *wigdet) const;
void drawRoundSlider(QPainter *painter, QRect rectGroove, QRect rectHandle, const QWidget *wigdet) const;
private:
StyleType m_drawSpecial;