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

View File

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

View File

@ -66,6 +66,8 @@ void SoundPlugin::init(PluginProxyInterface *proxyInter)
proxyInter->requestSetAppletVisible(this, QUICK_ITEM_KEY, true); proxyInter->requestSetAppletVisible(this, QUICK_ITEM_KEY, true);
}); });
} }
connect(m_soundDeviceWidget.data(), &SoundDevicesWidget::enableChanged, m_soundWidget.data(), &SoundWidget::setEnabled);
} }
void SoundPlugin::pluginStateSwitched() 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 rectGroove = subControlRect(CC_Slider, sliderOption, SC_SliderGroove, widget);
QRect rectHandle = subControlRect(CC_Slider, sliderOption, SC_SliderHandle, widget); QRect rectHandle = subControlRect(CC_Slider, sliderOption, SC_SliderHandle, widget);
if (m_drawSpecial == RoundHandler) if (m_drawSpecial == RoundHandler)
drawRoundSlider(painter, rectGroove, rectHandle); drawRoundSlider(painter, rectGroove, rectHandle, widget);
else else
drawNormalSlider(painter, rectGroove, rectHandle, const_cast<QWidget *>(widget)); drawNormalSlider(painter, rectGroove, rectHandle, widget);
painter->restore(); 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); 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个像素 // 绘制上下的竖线一根竖线的宽度是2+4个像素刚好保证中间也是间隔2个像素
for (int i = rectGroove.x(); i < rectGroove.x() + rectGroove.width(); i = i + 4) { for (int i = rectGroove.x(); i < rectGroove.x() + rectGroove.width(); i = i + 4) {
if (i < rectHandle.x()) if (i < rectHandle.x())
painter->setPen(penLine); painter->setPen(penLine);
else 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->drawLine(i, rectGroove.y() + 2, i, rectGroove.y() + rectGroove.height() - 2);
} }
// 绘制滚动区域 // 绘制滚动区域
painter->setBrush(dpa.color(DPalette::Highlight)); painter->setBrush(color);
painter->setPen(Qt::NoPen); painter->setPen(Qt::NoPen);
QPainterPath path; QPainterPath path;
path.addRoundedRect(rectHandle, 6, 6); 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; QPainterPath pathGroove;
int radius = rectGroove.height() / 2; 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; void drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = nullptr) const override;
private: private:
void drawNormalSlider(QPainter *painter, QRect rectGroove, QRect rectHandle, QWidget *wigdet) const; void drawNormalSlider(QPainter *painter, QRect rectGroove, QRect rectHandle, const QWidget *wigdet) const;
void drawRoundSlider(QPainter *painter, QRect rectGroove, QRect rectHandle) const; void drawRoundSlider(QPainter *painter, QRect rectGroove, QRect rectHandle, const QWidget *wigdet) const;
private: private:
StyleType m_drawSpecial; StyleType m_drawSpecial;