feat: 将音乐播放功能提取为单独的插件

将dock中的音乐播放功能提取为音乐插件

Log:
Influence: 无
Task: https://pms.uniontech.com/task-view-220489.html
Change-Id: Ie58d1645fff08332a03398aa8ce9cb0e90f16ad2
This commit is contained in:
donghualin 2022-11-30 12:19:06 +08:00
parent 3edc83802b
commit 6d14fd1be7
8 changed files with 869 additions and 0 deletions

View File

@ -0,0 +1,51 @@
set(PLUGIN_NAME "media")
project(${PLUGIN_NAME})
generation_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/xml ${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/generation_dbus_interface)
# Sources files
file(GLOB_RECURSE SRCS "*.h" "*.cpp"
"../../widgets/*.h"
"../../widgets/*.cpp"
"../../frame/util/imageutil.h"
"../../frame/util/imageutil.cpp"
"../../frame/util/statebutton.h"
"../../frame/util/statebutton.cpp"
"../../frame/util/horizontalseperator.h"
"../../frame/util/horizontalseperator.cpp"
"../../frame/qtdbusextended/*.h"
"../../frame/qtdbusextended/*.cpp")
find_package(PkgConfig REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Svg REQUIRED)
find_package(Qt5DBus REQUIRED)
find_package(DtkWidget REQUIRED)
pkg_check_modules(XCB_EWMH REQUIRED xcb-ewmh x11 xcursor)
pkg_check_modules(QGSettings REQUIRED gsettings-qt)
add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN")
add_library(${PLUGIN_NAME} SHARED ${SRCS})
set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../quick-trays)
target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS}
${QGSettings_INCLUDE_DIRS}
../../interfaces
../../widgets
../../frame
../../frame/qtdbusextended
./dbusinterface/generation_dbus_interface
componments)
target_link_libraries(${PLUGIN_NAME} PRIVATE
${XCB_EWMH_LIBRARIES}
${DtkWidget_LIBRARIES}
${QGSettings_LIBRARIES}
${Qt5DBus_LIBRARIES}
${Qt5Widgets_LIBRARIES}
${Qt5Svg_LIBRARIES}
)
install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins/quick-trays)

3
plugins/media/media.json Normal file
View File

@ -0,0 +1,3 @@
{
"api": "2.0.0"
}

View File

@ -0,0 +1,252 @@
#include "mediaplayermodel.h"
#include <QDBusConnectionInterface>
#include <QDBusInterface>
#include <QDBusPendingCall>
#include <QDBusReply>
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMetaMethod>
#include <QDBusAbstractInterface>
MediaPlayerModel::MediaPlayerModel(QObject *parent)
: QObject(parent)
, m_isActived(false)
, m_mediaInter(nullptr)
{
initMediaPlayer();
}
MediaPlayerModel::~MediaPlayerModel()
{
}
bool MediaPlayerModel::isActived()
{
return m_isActived;
}
bool MediaPlayerModel::canGoNext()
{
return m_mediaInter ? m_mediaInter->canGoNext() : false;
}
bool MediaPlayerModel::canGoPrevious()
{
return m_mediaInter ? m_mediaInter->canGoPrevious() : false;
}
bool MediaPlayerModel::canPause()
{
return m_mediaInter ? m_mediaInter->canPause() : false;
}
MediaPlayerModel::PlayStatus MediaPlayerModel::status()
{
if (!m_isActived || !m_mediaInter)
return PlayStatus::Stop;
return convertStatus(m_mediaInter->playbackStatus());
}
const QString MediaPlayerModel::name()
{
if (m_mediaInter) {
Dict data = m_mediaInter->metadata();
return data["xesam:title"].toString();
}
return QString();
}
const QString MediaPlayerModel::iconUrl()
{
if (m_mediaInter) {
Dict data = m_mediaInter->metadata();
return data["mpris:artUrl"].toString();
}
return QString();
}
const QString MediaPlayerModel::album()
{
if (m_mediaInter) {
Dict data = m_mediaInter->metadata();
return data["xesam:album"].toString();
}
return QString();
}
const QString MediaPlayerModel::artist()
{
if (m_mediaInter) {
Dict data = m_mediaInter->metadata();
return data["xesam:artist"].toString();
}
return QString();
}
void MediaPlayerModel::setStatus(const MediaPlayerModel::PlayStatus &stat)
{
if (!m_mediaInter)
return;
switch (stat) {
case MediaPlayerModel::PlayStatus::Play: {
m_mediaInter->Play();
break;
}
case MediaPlayerModel::PlayStatus::Stop: {
m_mediaInter->Stop();
break;
}
case MediaPlayerModel::PlayStatus::Pause: {
m_mediaInter->Pause();
break;
}
default: break;
}
}
void MediaPlayerModel::playNext()
{
if (m_mediaInter)
m_mediaInter->Next();
}
void MediaPlayerModel::initMediaPlayer()
{
QDBusInterface dbusInter("org.freedesktop.DBus", "/", "org.freedesktop.DBus", QDBusConnection::sessionBus(), this);
QDBusPendingCall call = dbusInter.asyncCall("ListNames");
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
connect(watcher, &QDBusPendingCallWatcher::finished, [ = ] {
m_serviceName.clear();
if (call.isError())
return;
QDBusReply<QStringList> reply = call.reply();
const QStringList &serviceList = reply.value();
for (const QString &serv : serviceList) {
if (!serv.startsWith("org.mpris.MediaPlayer2"))
continue;
QDBusInterface serviceInterface(serv, "/org/mpris/MediaPlayer2",
"org.mpris.MediaPlayer2.Player", QDBusConnection::sessionBus(), this);
// 如果开启了谷歌浏览器的后台服务(org.mpris.MediaPlayer2.chromium.instance17352)
// 也符合名称要求,但是它不是音乐服务,此时需要判断是否存在这个属性
QVariant v = serviceInterface.property("CanPlay");
if (!v.isValid() || !v.value<bool>())
continue;
m_serviceName = serv;
break;
}
if (!m_serviceName.isEmpty()) {
m_isActived = true;
m_mediaInter = new MediaPlayerInterface(m_serviceName, "/org/mpris/MediaPlayer2", QDBusConnection::sessionBus(), this);
connect(m_mediaInter, &MediaPlayerInterface::PlaybackStatusChanged, this, [ this ] {
Q_EMIT statusChanged(convertStatus(m_mediaInter->playbackStatus()));
});
connect(m_mediaInter, &MediaPlayerInterface::MetadataChanged, this, &MediaPlayerModel::metadataChanged);
Dict v = m_mediaInter->metadata();
m_name = v.value("xesam:title").toString();
m_icon = v.value("mpris:artUrl").toString();
m_album = v.value("xesam:album").toString();
m_artist = v.value("xesam:artist").toString();
Q_EMIT startStop(m_isActived);
return;
}
QDBusConnectionInterface *dbusInterface = QDBusConnection::sessionBus().interface();
connect(dbusInterface, &QDBusConnectionInterface::serviceOwnerChanged, this,
[ = ](const QString &name, const QString &, const QString &newOwner) {
if (name.startsWith("org.mpris.MediaPlayer2")) {
// 启动了音乐播放
m_isActived = !newOwner.isEmpty();
if (m_isActived) {
m_serviceName = name;
m_mediaInter = new MediaPlayerInterface(m_serviceName, "/org/mpris/MediaPlayer2", QDBusConnection::sessionBus(), this);
connect(m_mediaInter, &MediaPlayerInterface::PlaybackStatusChanged, this, [ this ] {
Q_EMIT statusChanged(convertStatus(m_mediaInter->playbackStatus()));
});
connect(m_mediaInter, &MediaPlayerInterface::MetadataChanged, this, &MediaPlayerModel::metadataChanged);
Dict v = m_mediaInter->metadata();
m_name = v.value("xesam:title").toString();
m_icon = v.value("mpris:artUrl").toString();
m_album = v.value("xesam:album").toString();
m_artist = v.value("xesam:artist").toString();
} else {
if (!m_serviceName.isEmpty()) {
delete m_mediaInter;
m_mediaInter = nullptr;
}
m_serviceName.clear();
}
Q_EMIT startStop(m_isActived);
}
});
connect(dbusInterface, &QDBusConnectionInterface::serviceUnregistered, this,
[ = ](const QString &service) {
if (service.startsWith("org.mpris.MediaPlayer2")) {
// 启动了音乐播放
m_serviceName.clear();
m_isActived = false;
Q_EMIT startStop(m_isActived);
}
});
});
connect(watcher, &QDBusPendingCallWatcher::finished, watcher, &QDBusPendingCallWatcher::deleteLater);
}
MediaPlayerModel::PlayStatus MediaPlayerModel::convertStatus(const QString &stat)
{
if (stat == "Paused")
return PlayStatus::Pause;
if (stat == "Playing")
return PlayStatus::Play;
if (stat == "Stopped")
return PlayStatus::Stop;
return PlayStatus::Unknow;
}
MediaPlayerInterface::MediaPlayerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, "org.mpris.MediaPlayer2.Player", connection, parent)
{
QDBusConnection::sessionBus().connect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage &)));
}
MediaPlayerInterface::~MediaPlayerInterface()
{
QDBusConnection::sessionBus().disconnect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage &)));
}
void MediaPlayerInterface::onPropertyChanged(const QDBusMessage &msg)
{
QList<QVariant> arguments = msg.arguments();
if (3 != arguments.count())
return;
QString interfaceName = msg.arguments().at(0).toString();
if (interfaceName !="org.mpris.MediaPlayer2.Player")
return;
QVariantMap changedProps = qdbus_cast<QVariantMap>(arguments.at(1).value<QDBusArgument>());
QStringList keys = changedProps.keys();
foreach(const QString &prop, keys) {
const QMetaObject* self = metaObject();
for (int i = self->propertyOffset(); i < self->propertyCount(); ++i) {
QMetaProperty p = self->property(i);
if (p.name() == prop) {
Q_EMIT p.notifySignal().invoke(this);
}
}
}
}

View File

@ -0,0 +1,124 @@
#ifndef MEDIAPLAYERMODEL_H
#define MEDIAPLAYERMODEL_H
#include <QObject>
#include <QDBusAbstractInterface>
#include <QDBusPendingReply>
typedef QMap<QString, QVariant> Dict;
Q_DECLARE_METATYPE(Dict)
class QDBusMessage;
class QDBusConnection;
class MediaPlayerInterface;
class MediaPlayerModel : public QObject
{
Q_OBJECT
public:
enum PlayStatus {
Unknow = 0,
Play,
Pause,
Stop
};
public:
explicit MediaPlayerModel(QObject *parent = nullptr);
~MediaPlayerModel();
bool isActived();
bool canGoNext();
bool canGoPrevious();
bool canPause();
PlayStatus status();
const QString name();
const QString iconUrl();
const QString album();
const QString artist();
void setStatus(const PlayStatus &stat);
void playNext();
Q_SIGNALS:
void startStop(bool);
void statusChanged(const PlayStatus &);
void metadataChanged();
private:
void initMediaPlayer();
PlayStatus convertStatus(const QString &stat);
private:
bool m_isActived;
QString m_serviceName;
QString m_name;
QString m_icon;
QString m_album;
QString m_artist;
MediaPlayerInterface *m_mediaInter;
};
class MediaPlayerInterface : public QDBusAbstractInterface
{
Q_OBJECT
public:
MediaPlayerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~MediaPlayerInterface();
public:
inline QDBusPendingReply<> Play() {
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Play"), argumentList);
}
inline QDBusPendingReply<> Stop() {
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Stop"), argumentList);
}
inline QDBusPendingReply<> Pause() {
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Pause"), argumentList);
}
inline QDBusPendingReply<> Next() {
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Next"), argumentList);
}
Q_PROPERTY(Dict Metadata READ metadata NOTIFY MetadataChanged)
inline Dict metadata() const
{ return qvariant_cast<Dict>(property("Metadata")); }
Q_PROPERTY(bool CanGoNext READ canGoNext NOTIFY CanGoNextChanged)
inline bool canGoNext() const
{ return qvariant_cast< bool >(property("CanGoNext")); }
Q_PROPERTY(bool CanGoPrevious READ canGoPrevious NOTIFY CanGoPreviousChanged)
inline bool canGoPrevious() const
{ return qvariant_cast< bool >(property("CanGoPrevious")); }
Q_PROPERTY(bool CanPause READ canPause NOTIFY CanPauseChanged)
inline bool canPause() const
{ return qvariant_cast< bool >(property("CanPause")); }
Q_PROPERTY(QString PlaybackStatus READ playbackStatus NOTIFY PlaybackStatusChanged)
inline QString playbackStatus() const
{ return qvariant_cast< QString >(property("PlaybackStatus")); }
Q_SIGNALS:
void MetadataChanged();
void CanGoNextChanged();
void CanGoPreviousChanged();
void CanPauseChanged();
void PlaybackStatusChanged();
private Q_SLOTS:
void onPropertyChanged(const QDBusMessage &msg);
};
#endif // MEDIAPLAYERLISTENER_H

View File

@ -0,0 +1,87 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@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 "mediaplugin.h"
#include "mediawidget.h"
#include "mediaplayermodel.h"
MediaPlugin::MediaPlugin(QObject *parent)
: QObject(parent)
, m_mediaWidget(nullptr)
, m_model(nullptr)
{
}
const QString MediaPlugin::pluginName() const
{
return "media";
}
const QString MediaPlugin::pluginDisplayName() const
{
return tr("media");
}
void MediaPlugin::init(PluginProxyInterface *proxyInter)
{
if (m_proxyInter == proxyInter)
return;
m_proxyInter = proxyInter;
m_model.reset(new MediaPlayerModel);
m_mediaWidget.reset(new MediaWidget(m_model.data()));
m_mediaWidget->setFixedHeight(60);
m_mediaWidget->setVisible(m_model->isActived());
if (m_model->isActived())
m_proxyInter->itemAdded(this, pluginName());
connect(m_model.data(), &MediaPlayerModel::startStop, this, [ this ](bool visible) {
if (visible)
m_proxyInter->itemAdded(this, pluginName());
else
m_proxyInter->itemRemoved(this, pluginName());
});
}
QWidget *MediaPlugin::itemWidget(const QString &itemKey)
{
if (itemKey == QUICK_ITEM_KEY)
return m_mediaWidget.data();
return nullptr;
}
QWidget *MediaPlugin::itemTipsWidget(const QString &itemKey)
{
return nullptr;
}
QWidget *MediaPlugin::itemPopupApplet(const QString &itemKey)
{
return nullptr;
}
PluginFlags MediaPlugin::flags() const
{
return PluginFlag::Type_Common | PluginFlag::Quick_Full;
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@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/>.
*/
#ifndef MEDIAPLUGIN_H
#define MEDIAPLUGIN_H
#include "pluginsiteminterface.h"
namespace Dock{
class TipsWidget;
}
class MediaWidget;
class MediaPlayerModel;
class MediaPlugin : public QObject, PluginsItemInterface
{
Q_OBJECT
Q_INTERFACES(PluginsItemInterface)
Q_PLUGIN_METADATA(IID "com.deepin.dock.PluginsItemInterface" FILE "media.json")
public:
explicit MediaPlugin(QObject *parent = nullptr);
const QString pluginName() const override;
const QString pluginDisplayName() const override;
void init(PluginProxyInterface *proxyInter) override;
QWidget *itemWidget(const QString &itemKey) override;
QWidget *itemTipsWidget(const QString &itemKey) override;
QWidget *itemPopupApplet(const QString &itemKey) override;
PluginFlags flags() const override;
private:
QScopedPointer<MediaWidget> m_mediaWidget;
QScopedPointer<MediaPlayerModel> m_model;
};
#endif // DATETIMEPLUGIN_H

View File

@ -0,0 +1,203 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@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 "mediawidget.h"
#include <DFontSizeManager>
#include <QLabel>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QEvent>
#include <QPainter>
#include <QDebug>
#include <QPainterPath>
DWIDGET_USE_NAMESPACE
#define PAUSEHEIGHT 21
#define PLAYHEIGHT 18
MediaWidget::MediaWidget(MediaPlayerModel *model, QWidget *parent)
: QWidget(parent)
, m_model(model)
, m_musicIcon(new QLabel(this))
, m_musicName(new QLabel(this))
, m_musicSinger(new QLabel(this))
, m_pausePlayButton(new MusicButton(this))
, m_nextButton(new MusicButton(this))
{
initUi();
initConnection();
}
MediaWidget::~MediaWidget()
{
}
void MediaWidget::statusChanged(const MediaPlayerModel::PlayStatus &newStatus)
{
switch (newStatus) {
case MediaPlayerModel::PlayStatus::Play: {
m_pausePlayButton->setButtonType(MusicButton::ButtonType::Pause);
break;
}
case MediaPlayerModel::PlayStatus::Stop:
case MediaPlayerModel::PlayStatus::Pause: {
m_pausePlayButton->setButtonType(MusicButton::ButtonType::Playing);
break;
}
default: break;
}
}
void MediaWidget::onPlayClicked()
{
// 设置当前的播放状态
if (m_model->status() == MediaPlayerModel::PlayStatus::Play)
m_model->setStatus(MediaPlayerModel::PlayStatus::Pause);
else
m_model->setStatus(MediaPlayerModel::PlayStatus::Play);
}
void MediaWidget::onNext()
{
// 播放下一曲
m_model->playNext();
}
void MediaWidget::initUi()
{
m_pausePlayButton->setFixedWidth(20);
m_nextButton->setFixedWidth(20);
QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->setContentsMargins(20, 0, 20, 0);
mainLayout->addWidget(m_musicIcon);
QWidget *infoWidget = new QWidget(this);
QVBoxLayout *infoLayout = new QVBoxLayout(infoWidget);
infoLayout->addWidget(m_musicName);
infoLayout->addWidget(m_musicSinger);
mainLayout->addWidget(infoWidget);
mainLayout->addStretch();
mainLayout->addWidget(m_pausePlayButton);
mainLayout->addSpacing(25);
mainLayout->addWidget(m_nextButton);
m_musicIcon->setFixedSize(32, 32);
m_musicName->setFont(DFontSizeManager::instance()->t8());
m_musicSinger->setFont(DFontSizeManager::instance()->t10());
}
void MediaWidget::initConnection()
{
connect(m_model, &MediaPlayerModel::startStop, this, [ this ](bool startOrStop) {
m_nextButton->setEnabled(m_model->canGoNext());
onUpdateMediaInfo();
statusChanged(m_model->status());
});
connect(m_model, &MediaPlayerModel::metadataChanged, this, &MediaWidget::onUpdateMediaInfo);
connect(m_model, &MediaPlayerModel::statusChanged, this, &MediaWidget::statusChanged);
connect(m_pausePlayButton, &MusicButton::clicked, this, &MediaWidget::onPlayClicked);
connect(m_nextButton, &MusicButton::clicked, this, &MediaWidget::onNext);
m_pausePlayButton->setButtonType(m_model->status() == MediaPlayerModel::PlayStatus::Play ?
MusicButton::ButtonType::Pause : MusicButton::ButtonType::Playing);
m_nextButton->setButtonType(MusicButton::ButtonType::Next);
}
void MediaWidget::onUpdateMediaInfo()
{
m_musicName->setText(m_model->name());
QString file = m_model->iconUrl();
if (file.startsWith("file:///"))
file.replace("file:///", "/");
m_musicIcon->setPixmap(QPixmap(file).scaled(m_musicIcon->size()));
m_musicSinger->setText(m_model->artist());
}
/**
* @brief
* @param parent
*/
MusicButton::MusicButton(QWidget *parent)
: QWidget(parent)
{
installEventFilter(this);
}
MusicButton::~MusicButton()
{
}
int MusicButton::getIconHeight() const
{
switch (m_buttonType) {
case ButtonType::Pause:
return PAUSEHEIGHT;
case ButtonType::Next:
case ButtonType::Playing:
return PLAYHEIGHT;
}
return PLAYHEIGHT;
}
void MusicButton::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
#define ICOMMARGIN 6
#define ICONSPACE 2
int ctrlHeight = getIconHeight();
int width = this->width();
int height = this->height();
int startX = 2;
int startY = (height - ctrlHeight) / 2;
QPainter painter(this);
painter.save();
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::black);
painter.setBrush(Qt::black);
if (m_buttonType == ButtonType::Pause) {
painter.drawRect(QRect(startX, startY, ICOMMARGIN, ctrlHeight));
painter.drawRect(QRect(width - ICOMMARGIN - ICONSPACE, startY, ICOMMARGIN, ctrlHeight));
} else {
QPainterPath trianglePath;
trianglePath.moveTo(startX, startY);
trianglePath.lineTo(width - ICOMMARGIN, height / 2);
trianglePath.lineTo(startX, startY + ctrlHeight);
trianglePath.lineTo(startX, startY);
painter.drawPath(trianglePath);
if (m_buttonType == ButtonType::Next)
painter.drawRect(width - ICOMMARGIN, startY, 2, ctrlHeight);
}
painter.restore();
}
void MusicButton::mouseReleaseEvent(QMouseEvent *event)
{
Q_UNUSED(event);
Q_EMIT clicked();
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@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/>.
*/
#ifndef MEDIAWIDGET_H
#define MEDIAWIDGET_H
#include "mediaplayermodel.h"
#include <DBlurEffectWidget>
class QLabel;
class MusicButton;
class MediaPlayerModel;
DWIDGET_USE_NAMESPACE
class MediaWidget : public QWidget
{
Q_OBJECT
public:
explicit MediaWidget(MediaPlayerModel *model, QWidget *parent = nullptr);
~MediaWidget() override;
private Q_SLOTS:
void statusChanged(const MediaPlayerModel::PlayStatus &newStatus);
void onPlayClicked();
void onNext();
void onUpdateMediaInfo();
private:
void initUi();
void initConnection();
private:
MediaPlayerModel *m_model;
QLabel *m_musicIcon;
QLabel *m_musicName;
QLabel *m_musicSinger;
MusicButton *m_pausePlayButton;
MusicButton *m_nextButton;
};
// 音乐播放按钮
class MusicButton : public QWidget
{
Q_OBJECT
Q_SIGNALS:
void clicked();
public:
enum ButtonType { Playing = 0, Pause, Next };
public:
MusicButton(QWidget *parent = Q_NULLPTR);
~MusicButton() override;
inline void setButtonType(const ButtonType &bt) {
m_buttonType = bt;
update();
}
protected:
void paintEvent(QPaintEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private:
int getIconHeight() const;
private:
ButtonType m_buttonType;
};
#endif // MEDIAWIDGER_H