UI(Windows): add task icon progress and buttons
This commit is contained in:
@ -58,6 +58,7 @@ set (PMUSIC_HEADER_FILES
|
|||||||
lyricsmanager.h
|
lyricsmanager.h
|
||||||
fftspectrum.h
|
fftspectrum.h
|
||||||
playbackprogressindicator.h
|
playbackprogressindicator.h
|
||||||
|
taskbarmanager.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set (PMUSIC_UI_FILES
|
set (PMUSIC_UI_FILES
|
||||||
@ -84,6 +85,9 @@ TS_FILES
|
|||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_sources(${EXE_NAME} PRIVATE assets/pineapple-music.rc)
|
target_sources(${EXE_NAME} PRIVATE assets/pineapple-music.rc)
|
||||||
|
target_sources(${EXE_NAME} PRIVATE taskbarmanager.cpp)
|
||||||
|
else ()
|
||||||
|
target_sources(${EXE_NAME} PRIVATE taskbarmanager_dummy.cpp)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (NOT TagLib_FOUND)
|
if (NOT TagLib_FOUND)
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "playlistmanager.h"
|
#include "playlistmanager.h"
|
||||||
#include "fftspectrum.h"
|
#include "fftspectrum.h"
|
||||||
#include "lrcbar.h"
|
#include "lrcbar.h"
|
||||||
|
#include "taskbarmanager.h"
|
||||||
|
|
||||||
// taglib
|
// taglib
|
||||||
#ifndef NO_TAGLIB
|
#ifndef NO_TAGLIB
|
||||||
@ -34,6 +35,7 @@
|
|||||||
#include <QStringBuilder>
|
#include <QStringBuilder>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QGraphicsDropShadowEffect>
|
#include <QGraphicsDropShadowEffect>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
constexpr QSize miniSize(490, 160);
|
constexpr QSize miniSize(490, 160);
|
||||||
constexpr QSize fullSize(490, 420);
|
constexpr QSize fullSize(490, 420);
|
||||||
@ -47,6 +49,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
, m_fftSpectrum(new FFTSpectrum(this))
|
, m_fftSpectrum(new FFTSpectrum(this))
|
||||||
, m_lrcbar(new LrcBar(nullptr))
|
, m_lrcbar(new LrcBar(nullptr))
|
||||||
, m_playlistManager(new PlaylistManager(this))
|
, m_playlistManager(new PlaylistManager(this))
|
||||||
|
, m_taskbarManager(new TaskBarManager(this))
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
m_playlistManager->setAutoLoadFilterSuffixes({
|
m_playlistManager->setAutoLoadFilterSuffixes({
|
||||||
@ -70,12 +73,21 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint);
|
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint);
|
||||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||||
|
|
||||||
|
m_taskbarManager->setCanTogglePlayback(true);
|
||||||
|
m_taskbarManager->setCanSkipBackward(true);
|
||||||
|
m_taskbarManager->setCanSkipForward(true);
|
||||||
|
m_taskbarManager->setShowProgress(true);
|
||||||
|
|
||||||
loadConfig();
|
loadConfig();
|
||||||
loadSkinData();
|
loadSkinData();
|
||||||
initConnections();
|
initConnections();
|
||||||
initUiAndAnimation();
|
initUiAndAnimation();
|
||||||
|
|
||||||
centerWindow();
|
centerWindow();
|
||||||
|
|
||||||
|
QTimer::singleShot(1000, [this](){
|
||||||
|
m_taskbarManager->setWinId(window()->winId());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
@ -492,6 +504,7 @@ void MainWindow::initConnections()
|
|||||||
ui->nowTimeLabel->setText(ms2str(pos));
|
ui->nowTimeLabel->setText(ms2str(pos));
|
||||||
if (m_mediaPlayer->duration() != 0) {
|
if (m_mediaPlayer->duration() != 0) {
|
||||||
ui->playbackProgressIndicator->setPosition(pos);
|
ui->playbackProgressIndicator->setPosition(pos);
|
||||||
|
m_taskbarManager->setProgressValue(pos);
|
||||||
}
|
}
|
||||||
m_lrcbar->playbackPositionChanged(pos, m_mediaPlayer->duration());
|
m_lrcbar->playbackPositionChanged(pos, m_mediaPlayer->duration());
|
||||||
});
|
});
|
||||||
@ -506,6 +519,7 @@ void MainWindow::initConnections()
|
|||||||
|
|
||||||
connect(m_mediaPlayer, &QMediaPlayer::durationChanged, this, [=](qint64 dua) {
|
connect(m_mediaPlayer, &QMediaPlayer::durationChanged, this, [=](qint64 dua) {
|
||||||
ui->playbackProgressIndicator->setDuration(dua);
|
ui->playbackProgressIndicator->setDuration(dua);
|
||||||
|
m_taskbarManager->setProgressMaximum(dua);
|
||||||
ui->totalTimeLabel->setText(ms2str(dua));
|
ui->totalTimeLabel->setText(ms2str(dua));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -519,6 +533,7 @@ void MainWindow::initConnections()
|
|||||||
ui->playBtn->setIcon(QIcon(":/icons/icons/media-playback-start.png"));
|
ui->playBtn->setIcon(QIcon(":/icons/icons/media-playback-start.png"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
m_taskbarManager->setPlaybackState(newState);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_audioOutput, &QAudioOutput::volumeChanged, this, [=](float vol) {
|
connect(m_audioOutput, &QAudioOutput::volumeChanged, this, [=](float vol) {
|
||||||
@ -559,6 +574,18 @@ void MainWindow::initConnections()
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(m_taskbarManager, &TaskBarManager::togglePlayback, this, [this](){
|
||||||
|
on_playBtn_clicked();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_taskbarManager, &TaskBarManager::skipBackward, this, [this](){
|
||||||
|
on_prevBtn_clicked();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_taskbarManager, &TaskBarManager::skipForward, this, [this](){
|
||||||
|
on_nextBtn_clicked();
|
||||||
|
});
|
||||||
|
|
||||||
connect(m_mediaPlayer, &QMediaPlayer::errorOccurred, this, [=](QMediaPlayer::Error error, const QString &errorString) {
|
connect(m_mediaPlayer, &QMediaPlayer::errorOccurred, this, [=](QMediaPlayer::Error error, const QString &errorString) {
|
||||||
qDebug() << error << errorString;
|
qDebug() << error << errorString;
|
||||||
});
|
});
|
||||||
|
@ -22,6 +22,7 @@ QT_END_NAMESPACE
|
|||||||
class FFTSpectrum;
|
class FFTSpectrum;
|
||||||
class LrcBar;
|
class LrcBar;
|
||||||
class PlaylistManager;
|
class PlaylistManager;
|
||||||
|
class TaskBarManager;
|
||||||
class MainWindow : public QMainWindow
|
class MainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -103,6 +104,7 @@ private:
|
|||||||
LrcBar *m_lrcbar;
|
LrcBar *m_lrcbar;
|
||||||
QPropertyAnimation *m_fadeOutAnimation;
|
QPropertyAnimation *m_fadeOutAnimation;
|
||||||
PlaylistManager *m_playlistManager;
|
PlaylistManager *m_playlistManager;
|
||||||
|
TaskBarManager *m_taskbarManager;
|
||||||
|
|
||||||
void initUiAndAnimation();
|
void initUiAndAnimation();
|
||||||
void initConnections();
|
void initConnections();
|
||||||
|
383
taskbarmanager.cpp
Normal file
383
taskbarmanager.cpp
Normal file
@ -0,0 +1,383 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 (c) Jack Hill <jackhill3103@gmail.com>
|
||||||
|
// SPDX-FileCopyrightText: 2025 (c) Gary Wang <opensource@blumia.net>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
//
|
||||||
|
// This file is modified based on Elisa's taskmanager.cpp implementation,
|
||||||
|
// with its Qt Quick usage removed.
|
||||||
|
|
||||||
|
#include "taskbarmanager.h"
|
||||||
|
|
||||||
|
#include <QAbstractEventDispatcher>
|
||||||
|
#include <QAbstractNativeEventFilter>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include <Shobjidl.h>
|
||||||
|
#include <WinDef.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
constexpr int numOfButtons = 3;
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
|
||||||
|
using namespace Qt::Literals::StringLiterals;
|
||||||
|
|
||||||
|
static HICON hiconFromTheme(const QString &iconName)
|
||||||
|
#else
|
||||||
|
static HICON hiconFromTheme(const QIcon::ThemeIcon iconName)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
const auto width = GetSystemMetrics(SM_CXSMICON);
|
||||||
|
const auto height = GetSystemMetrics(SM_CYSMICON);
|
||||||
|
return QIcon::fromTheme(iconName).pixmap(width, height).toImage().toHICON();
|
||||||
|
}
|
||||||
|
|
||||||
|
class TaskBarManagerPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ITaskbarList3 *taskBar = nullptr;
|
||||||
|
HWND hwnd = nullptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the toolbar has been added to the taskbar
|
||||||
|
*/
|
||||||
|
bool addedThumbButtons = false;
|
||||||
|
|
||||||
|
QMediaPlayer::PlaybackState playbackState = QMediaPlayer::StoppedState;
|
||||||
|
|
||||||
|
bool showProgress = false;
|
||||||
|
qlonglong progressMaximum = 0;
|
||||||
|
qlonglong progressValue = 0;
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
|
||||||
|
HICON skipBackwardIcon = hiconFromTheme(u"media-skip-backward"_s);
|
||||||
|
HICON skipForwardIcon = hiconFromTheme(u"media-skip-forward"_s);
|
||||||
|
HICON playIcon = hiconFromTheme(u"media-playback-start"_s);
|
||||||
|
HICON pauseIcon = hiconFromTheme(u"media-playback-pause"_s);
|
||||||
|
#else
|
||||||
|
HICON skipBackwardIcon = hiconFromTheme(QIcon::ThemeIcon::MediaSkipBackward);
|
||||||
|
HICON skipForwardIcon = hiconFromTheme(QIcon::ThemeIcon::MediaSkipForward);
|
||||||
|
HICON playIcon = hiconFromTheme(QIcon::ThemeIcon::MediaPlaybackStart);
|
||||||
|
HICON pauseIcon = hiconFromTheme(QIcon::ThemeIcon::MediaPlaybackPause);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the current state of each button
|
||||||
|
*/
|
||||||
|
struct ButtonData {
|
||||||
|
HICON icon = nullptr;
|
||||||
|
bool enabled = false;
|
||||||
|
};
|
||||||
|
std::array<ButtonData, numOfButtons> buttonData = {{
|
||||||
|
{skipBackwardIcon, false},
|
||||||
|
{playIcon, false},
|
||||||
|
{skipForwardIcon, false}
|
||||||
|
}};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For convenience when reading code
|
||||||
|
*/
|
||||||
|
enum ButtonID {
|
||||||
|
SkipBackward = 0,
|
||||||
|
TogglePlayback = 1,
|
||||||
|
SkipForward = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
TaskBarManagerPrivate()
|
||||||
|
{
|
||||||
|
HRESULT result = CoCreateInstance(CLSID_TaskbarList,
|
||||||
|
nullptr,
|
||||||
|
CLSCTX_INPROC_SERVER,
|
||||||
|
IID_PPV_ARGS(&taskBar));
|
||||||
|
if (FAILED(result)) {
|
||||||
|
taskBar = nullptr;
|
||||||
|
qWarning() << "Failed to create Windows taskbar instance";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~TaskBarManagerPrivate()
|
||||||
|
{
|
||||||
|
if (taskBar) {
|
||||||
|
taskBar->Release();
|
||||||
|
}
|
||||||
|
DestroyIcon(skipForwardIcon);
|
||||||
|
DestroyIcon(skipBackwardIcon);
|
||||||
|
DestroyIcon(pauseIcon);
|
||||||
|
DestroyIcon(playIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the native window handle for the taskbar instance
|
||||||
|
*/
|
||||||
|
void setHWND(HWND newHwnd)
|
||||||
|
{
|
||||||
|
if (hwnd == newHwnd) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hwnd = newHwnd;
|
||||||
|
addedThumbButtons = false;
|
||||||
|
if (hwnd) {
|
||||||
|
updateProgressFlags();
|
||||||
|
updateProgressValue();
|
||||||
|
setupTaskBarManagerButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the taskbar progress flags
|
||||||
|
*/
|
||||||
|
void updateProgressFlags()
|
||||||
|
{
|
||||||
|
if (taskBar && hwnd) {
|
||||||
|
taskBar->SetProgressState(hwnd, progressFlags());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the taskbar progress value, only if the taskbar is showing progress
|
||||||
|
*/
|
||||||
|
void updateProgressValue()
|
||||||
|
{
|
||||||
|
if (taskBar && hwnd && showProgress && playbackState != QMediaPlayer::StoppedState) {
|
||||||
|
taskBar->SetProgressValue(hwnd, progressValue, progressMaximum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the state of a single toolbutton
|
||||||
|
*/
|
||||||
|
void updateButton(const ButtonID buttonId)
|
||||||
|
{
|
||||||
|
if (!taskBar || !hwnd || !addedThumbButtons) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
THUMBBUTTON thumbButtons[1];
|
||||||
|
initThumbButton(thumbButtons, buttonId);
|
||||||
|
taskBar->ThumbBarUpdateButtons(hwnd, 1, thumbButtons);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Convert playbackState into windows taskbar flags
|
||||||
|
*/
|
||||||
|
TBPFLAG progressFlags() const
|
||||||
|
{
|
||||||
|
if (!showProgress) {
|
||||||
|
return TBPF_NOPROGRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (playbackState) {
|
||||||
|
case QMediaPlayer::StoppedState:
|
||||||
|
return TBPF_NOPROGRESS;
|
||||||
|
case QMediaPlayer::PlayingState:
|
||||||
|
return TBPF_NORMAL;
|
||||||
|
case QMediaPlayer::PausedState:
|
||||||
|
return TBPF_PAUSED;
|
||||||
|
default:
|
||||||
|
return TBPF_NOPROGRESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a single toolbutton
|
||||||
|
*/
|
||||||
|
void initThumbButton(THUMBBUTTON *button, const ButtonID id)
|
||||||
|
{
|
||||||
|
button->dwMask = THB_ICON | THB_FLAGS;
|
||||||
|
button->iId = id;
|
||||||
|
button->hIcon = buttonData.at(id).icon;
|
||||||
|
button->dwFlags = buttonData.at(id).enabled ? THBF_ENABLED : THBF_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the toolbar
|
||||||
|
*/
|
||||||
|
void setupTaskBarManagerButtons()
|
||||||
|
{
|
||||||
|
if (!taskBar || !hwnd || addedThumbButtons) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
THUMBBUTTON thumbButtons[numOfButtons];
|
||||||
|
THUMBBUTTON *currButton = thumbButtons;
|
||||||
|
for (int i = 0; i < numOfButtons; ++i) {
|
||||||
|
initThumbButton(currButton++, static_cast<ButtonID>(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// win32 api reference says we should pass &thumbButtons but this doesn't compile
|
||||||
|
HRESULT result = taskBar->ThumbBarAddButtons(hwnd, numOfButtons, thumbButtons);
|
||||||
|
if (FAILED(result)) {
|
||||||
|
qWarning() << "Failed to create Windows taskbar buttons";
|
||||||
|
} else {
|
||||||
|
addedThumbButtons = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TaskBarManager::TaskBarManager(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, d(std::make_unique<TaskBarManagerPrivate>())
|
||||||
|
{
|
||||||
|
QAbstractEventDispatcher::instance()->installNativeEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskBarManager::~TaskBarManager() = default;
|
||||||
|
|
||||||
|
bool TaskBarManager::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *)
|
||||||
|
{
|
||||||
|
if (eventType == "windows_generic_MSG") {
|
||||||
|
MSG *msg = static_cast<MSG *>(message);
|
||||||
|
if (msg->hwnd != d->hwnd || msg->message != WM_COMMAND || HIWORD(msg->wParam) != THBN_CLICKED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (LOWORD(msg->wParam)) {
|
||||||
|
case TaskBarManagerPrivate::SkipBackward:
|
||||||
|
Q_EMIT skipBackward();
|
||||||
|
return true;
|
||||||
|
case TaskBarManagerPrivate::TogglePlayback:
|
||||||
|
Q_EMIT togglePlayback();
|
||||||
|
return true;
|
||||||
|
case TaskBarManagerPrivate::SkipForward:
|
||||||
|
Q_EMIT skipForward();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMediaPlayer::PlaybackState TaskBarManager::playbackState() const
|
||||||
|
{
|
||||||
|
return d->playbackState;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskBarManager::showProgress() const
|
||||||
|
{
|
||||||
|
return d->showProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
qulonglong TaskBarManager::progressMaximum() const
|
||||||
|
{
|
||||||
|
return d->progressMaximum;
|
||||||
|
}
|
||||||
|
|
||||||
|
qulonglong TaskBarManager::progressValue() const
|
||||||
|
{
|
||||||
|
return d->progressValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskBarManager::canSkipBackward() const
|
||||||
|
{
|
||||||
|
return d->buttonData.at(TaskBarManagerPrivate::SkipBackward).enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskBarManager::canSkipForward() const
|
||||||
|
{
|
||||||
|
return d->buttonData.at(TaskBarManagerPrivate::SkipForward).enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskBarManager::canTogglePlayback() const
|
||||||
|
{
|
||||||
|
return d->buttonData.at(TaskBarManagerPrivate::TogglePlayback).enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setWinId(WId winId)
|
||||||
|
{
|
||||||
|
d->setHWND(reinterpret_cast<HWND>(winId));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setPlaybackState(const QMediaPlayer::PlaybackState newPlaybackState)
|
||||||
|
{
|
||||||
|
if (d->playbackState == newPlaybackState) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->playbackState = newPlaybackState;
|
||||||
|
Q_EMIT playbackStateChanged();
|
||||||
|
|
||||||
|
d->buttonData.at(TaskBarManagerPrivate::TogglePlayback).icon =
|
||||||
|
d->playbackState == QMediaPlayer::PlayingState ? d->pauseIcon : d->playIcon;
|
||||||
|
d->updateButton(TaskBarManagerPrivate::TogglePlayback);
|
||||||
|
d->updateProgressFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setShowProgress(const bool showProgress)
|
||||||
|
{
|
||||||
|
if (d->showProgress == showProgress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->showProgress = showProgress;
|
||||||
|
Q_EMIT showProgressChanged();
|
||||||
|
|
||||||
|
d->updateProgressFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setProgressMaximum(const qlonglong newMaximum)
|
||||||
|
{
|
||||||
|
if (d->progressMaximum == newMaximum) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->progressMaximum = newMaximum;
|
||||||
|
Q_EMIT progressMaximumChanged();
|
||||||
|
|
||||||
|
if (d->progressValue > d->progressMaximum) {
|
||||||
|
d->progressValue = d->progressMaximum;
|
||||||
|
Q_EMIT progressValueChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
d->updateProgressValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setProgressValue(const qlonglong newValue)
|
||||||
|
{
|
||||||
|
if (d->progressValue == newValue) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->progressValue = newValue < d->progressMaximum ? newValue : d->progressMaximum;
|
||||||
|
Q_EMIT progressValueChanged();
|
||||||
|
|
||||||
|
d->updateProgressValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setCanSkipBackward(const bool canSkip)
|
||||||
|
{
|
||||||
|
if (d->buttonData[TaskBarManagerPrivate::SkipBackward].enabled == canSkip) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->buttonData[TaskBarManagerPrivate::SkipBackward].enabled = canSkip;
|
||||||
|
Q_EMIT canSkipBackwardChanged();
|
||||||
|
|
||||||
|
d->updateButton(TaskBarManagerPrivate::SkipBackward);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setCanSkipForward(const bool canSkip)
|
||||||
|
{
|
||||||
|
if (d->buttonData[TaskBarManagerPrivate::SkipForward].enabled == canSkip) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->buttonData[TaskBarManagerPrivate::SkipForward].enabled = canSkip;
|
||||||
|
Q_EMIT canSkipForwardChanged();
|
||||||
|
|
||||||
|
d->updateButton(TaskBarManagerPrivate::SkipForward);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setCanTogglePlayback(const bool canToggle)
|
||||||
|
{
|
||||||
|
if (d->buttonData[TaskBarManagerPrivate::TogglePlayback].enabled == canToggle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->buttonData[TaskBarManagerPrivate::TogglePlayback].enabled = canToggle;
|
||||||
|
Q_EMIT canTogglePlaybackChanged();
|
||||||
|
|
||||||
|
d->updateButton(TaskBarManagerPrivate::TogglePlayback);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_taskbarmanager.cpp"
|
151
taskbarmanager.h
Normal file
151
taskbarmanager.h
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 (c) Jack Hill <jackhill3103@gmail.com>
|
||||||
|
// SPDX-FileCopyrightText: 2025 (c) Gary Wang <opensource@blumia.net>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
//
|
||||||
|
// This file is modified based on Elisa's taskmanager.cpp implementation,
|
||||||
|
// with its Qt Quick usage removed.
|
||||||
|
|
||||||
|
#ifndef TASKBAR_H
|
||||||
|
#define TASKBAR_H
|
||||||
|
|
||||||
|
#include <QAbstractNativeEventFilter>
|
||||||
|
#include <QMediaPlayer>
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class TaskBarManagerPrivate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Windows taskbar
|
||||||
|
*/
|
||||||
|
class TaskBarManager : public QObject, public QAbstractNativeEventFilter
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the media is playing, paused, or stopped
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(QMediaPlayer::PlaybackState playbackState
|
||||||
|
READ playbackState
|
||||||
|
WRITE setPlaybackState
|
||||||
|
NOTIFY playbackStateChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to show track progress on the taskbar
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(bool showProgress
|
||||||
|
READ showProgress
|
||||||
|
WRITE setShowProgress
|
||||||
|
NOTIFY showProgressChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum possible progress
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(qulonglong progressMaximum
|
||||||
|
READ progressMaximum
|
||||||
|
WRITE setProgressMaximum
|
||||||
|
NOTIFY progressMaximumChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current progress; this is always clamped to be in the range [0, progressMaximum]
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(qulonglong progressValue
|
||||||
|
READ progressValue
|
||||||
|
WRITE setProgressValue
|
||||||
|
NOTIFY progressValueChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the "Skip Backward" button is enabled
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(bool canSkipBackward
|
||||||
|
READ canSkipBackward
|
||||||
|
WRITE setCanSkipBackward
|
||||||
|
NOTIFY canSkipBackwardChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the "Skip Forward" button is enabled
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(bool canSkipForward
|
||||||
|
READ canSkipForward
|
||||||
|
WRITE setCanSkipForward
|
||||||
|
NOTIFY canSkipForwardChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the "Toggle Playback" button is enabled
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(bool canTogglePlayback
|
||||||
|
READ canTogglePlayback
|
||||||
|
WRITE setCanTogglePlayback
|
||||||
|
NOTIFY canTogglePlaybackChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit TaskBarManager(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
~TaskBarManager() override;
|
||||||
|
|
||||||
|
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;
|
||||||
|
|
||||||
|
[[nodiscard]] QMediaPlayer::PlaybackState playbackState() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool showProgress() const;
|
||||||
|
|
||||||
|
[[nodiscard]] qulonglong progressMaximum() const;
|
||||||
|
|
||||||
|
[[nodiscard]] qulonglong progressValue() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool canSkipBackward() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool canSkipForward() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool canTogglePlayback() const;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
|
||||||
|
void playbackStateChanged();
|
||||||
|
|
||||||
|
void showProgressChanged();
|
||||||
|
|
||||||
|
void progressMaximumChanged();
|
||||||
|
|
||||||
|
void progressValueChanged();
|
||||||
|
|
||||||
|
void canSkipBackwardChanged();
|
||||||
|
|
||||||
|
void canSkipForwardChanged();
|
||||||
|
|
||||||
|
void canTogglePlaybackChanged();
|
||||||
|
|
||||||
|
void skipBackward();
|
||||||
|
|
||||||
|
void skipForward();
|
||||||
|
|
||||||
|
void togglePlayback();
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
|
||||||
|
void setWinId(WId win);
|
||||||
|
|
||||||
|
void setPlaybackState(QMediaPlayer::PlaybackState newPlaybackState);
|
||||||
|
|
||||||
|
void setShowProgress(bool showProgress);
|
||||||
|
|
||||||
|
void setProgressMaximum(qlonglong newMaximum);
|
||||||
|
|
||||||
|
void setProgressValue(qlonglong newValue);
|
||||||
|
|
||||||
|
void setCanSkipBackward(bool canSkip);
|
||||||
|
|
||||||
|
void setCanSkipForward(bool canSkip);
|
||||||
|
|
||||||
|
void setCanTogglePlayback(bool canToggle);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::unique_ptr<TaskBarManagerPrivate> d;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TASKBAR_H
|
97
taskbarmanager_dummy.cpp
Normal file
97
taskbarmanager_dummy.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2025 Gary Wang <opensource@blumia.net>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "taskbarmanager.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
class TaskBarManagerPrivate {};
|
||||||
|
|
||||||
|
TaskBarManager::TaskBarManager(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskBarManager::~TaskBarManager() = default;
|
||||||
|
|
||||||
|
bool TaskBarManager::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMediaPlayer::PlaybackState TaskBarManager::playbackState() const
|
||||||
|
{
|
||||||
|
return QMediaPlayer::StoppedState;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskBarManager::showProgress() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qulonglong TaskBarManager::progressMaximum() const
|
||||||
|
{
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
qulonglong TaskBarManager::progressValue() const
|
||||||
|
{
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskBarManager::canSkipBackward() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskBarManager::canSkipForward() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskBarManager::canTogglePlayback() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setWinId(WId winId)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setPlaybackState(const QMediaPlayer::PlaybackState newPlaybackState)
|
||||||
|
{
|
||||||
|
Q_UNUSED(newPlaybackState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setShowProgress(const bool showProgress)
|
||||||
|
{
|
||||||
|
Q_UNUSED(showProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setProgressMaximum(const qlonglong newMaximum)
|
||||||
|
{
|
||||||
|
Q_UNUSED(newMaximum);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setProgressValue(const qlonglong newValue)
|
||||||
|
{
|
||||||
|
Q_UNUSED(newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setCanSkipBackward(const bool canSkip)
|
||||||
|
{
|
||||||
|
Q_UNUSED(canSkip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setCanSkipForward(const bool canSkip)
|
||||||
|
{
|
||||||
|
Q_UNUSED(canSkip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskBarManager::setCanTogglePlayback(const bool canToggle)
|
||||||
|
{
|
||||||
|
Q_UNUSED(canToggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_taskbarmanager.cpp"
|
Reference in New Issue
Block a user