File indexing completed on 2025-01-05 04:29:55

0001 /**
0002  * SPDX-FileCopyrightText: 2023 Bart De Vries <bart@mogwai.be>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "systrayicon.h"
0008 
0009 #ifndef Q_OS_ANDROID
0010 #include <QCoreApplication>
0011 #include <QFile>
0012 #include <QMenu>
0013 
0014 #include <KLocalizedString>
0015 
0016 #include "audiomanager.h"
0017 #include "kmediasession.h"
0018 #include "settingsmanager.h"
0019 
0020 SystrayIcon::SystrayIcon(QObject *parent)
0021     : QSystemTrayIcon(parent)
0022 {
0023     setIconColor(intToIconColorEnum(SettingsManager::self()->trayIconType()));
0024     setToolTip(i18nc("@info:tooltip",
0025                      "Kasts\n"
0026                      "Middle-click to play/pause"));
0027 
0028     QMenu *menu = new QMenu();
0029 
0030     connect(this, &QSystemTrayIcon::activated, this, [this](QSystemTrayIcon::ActivationReason reason) {
0031         if (reason == QSystemTrayIcon::Trigger) {
0032             Q_EMIT raiseWindow();
0033         } else if (reason == QSystemTrayIcon::MiddleClick) {
0034             AudioManager::instance().playPause();
0035         }
0036     });
0037 
0038     connect(SettingsManager::self(), &SettingsManager::showTrayIconChanged, this, [this]() {
0039         if (SettingsManager::self()->showTrayIcon()) {
0040             show();
0041         } else {
0042             hide();
0043         }
0044     });
0045 
0046     connect(SettingsManager::self(), &SettingsManager::trayIconTypeChanged, this, [this]() {
0047         setIconColor(intToIconColorEnum(SettingsManager::self()->trayIconType()));
0048     });
0049 
0050     // Seek backward
0051     QAction *skipBackwardAction = new QAction(i18nc("@action:inmenu", "Seek Backward"), this);
0052     skipBackwardAction->setIcon(QIcon::fromTheme(QStringLiteral("media-seek-backward")));
0053     skipBackwardAction->setEnabled(AudioManager::instance().canSkipBackward());
0054 
0055     connect(skipBackwardAction, &QAction::triggered, &AudioManager::instance(), &AudioManager::skipBackward);
0056     menu->addAction(skipBackwardAction);
0057 
0058     connect(&AudioManager::instance(), &AudioManager::canSkipBackwardChanged, this, [skipBackwardAction]() {
0059         skipBackwardAction->setEnabled(AudioManager::instance().canSkipBackward());
0060     });
0061 
0062     // Play / Pause
0063     QAction *playAction = new QAction(i18nc("@action:inmenu", "Play"), this);
0064     playAction->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start")));
0065     playAction->setVisible(AudioManager::instance().playbackState() != KMediaSession::PlaybackState::PlayingState);
0066     playAction->setEnabled(AudioManager::instance().canPlay());
0067 
0068     connect(playAction, &QAction::triggered, &AudioManager::instance(), &AudioManager::play);
0069     menu->addAction(playAction);
0070 
0071     QAction *pauseAction = new QAction(i18nc("@action:inmenu", "Pause"), this);
0072     pauseAction->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-pause")));
0073     pauseAction->setVisible(AudioManager::instance().playbackState() == KMediaSession::PlaybackState::PlayingState);
0074     pauseAction->setEnabled(AudioManager::instance().canPlay());
0075 
0076     connect(pauseAction, &QAction::triggered, &AudioManager::instance(), &AudioManager::pause);
0077     menu->addAction(pauseAction);
0078 
0079     connect(&AudioManager::instance(), &AudioManager::playbackStateChanged, this, [playAction, pauseAction](KMediaSession::PlaybackState state) {
0080         playAction->setVisible(state != KMediaSession::PlaybackState::PlayingState);
0081         pauseAction->setVisible(state == KMediaSession::PlaybackState::PlayingState);
0082     });
0083 
0084     connect(&AudioManager::instance(), &AudioManager::canPlayChanged, this, [playAction, pauseAction]() {
0085         playAction->setEnabled(AudioManager::instance().canPlay());
0086         pauseAction->setEnabled(AudioManager::instance().canPlay());
0087     });
0088 
0089     // Seek forward
0090     QAction *skipForwardAction = new QAction(i18nc("@action:inmenu", "Seek Forward"), this);
0091     skipForwardAction->setIcon(QIcon::fromTheme(QStringLiteral("media-seek-forward")));
0092     skipForwardAction->setEnabled(AudioManager::instance().canSkipForward());
0093 
0094     connect(skipForwardAction, &QAction::triggered, &AudioManager::instance(), &AudioManager::skipForward);
0095     menu->addAction(skipForwardAction);
0096 
0097     connect(&AudioManager::instance(), &AudioManager::canSkipForwardChanged, this, [skipForwardAction]() {
0098         skipForwardAction->setEnabled(AudioManager::instance().canSkipForward());
0099     });
0100 
0101     // Skip forward
0102     QAction *nextAction = new QAction(i18nc("@action:inmenu", "Skip Forward"), this);
0103     nextAction->setIcon(QIcon::fromTheme(QStringLiteral("media-skip-forward")));
0104     nextAction->setEnabled(AudioManager::instance().canGoNext());
0105 
0106     connect(nextAction, &QAction::triggered, &AudioManager::instance(), &AudioManager::next);
0107     menu->addAction(nextAction);
0108 
0109     connect(&AudioManager::instance(), &AudioManager::canGoNextChanged, this, [nextAction]() {
0110         nextAction->setEnabled(AudioManager::instance().canGoNext());
0111     });
0112 
0113     // Separator
0114     menu->addSeparator();
0115 
0116     // Quit
0117     QAction *quitAction = new QAction(i18nc("@action:inmenu", "Quit"), this);
0118     quitAction->setIcon(QIcon::fromTheme(QStringLiteral("application-exit")));
0119 
0120     connect(quitAction, &QAction::triggered, QCoreApplication::instance(), QCoreApplication::quit);
0121     menu->addAction(quitAction);
0122 
0123     setContextMenu(menu);
0124 
0125     if (SettingsManager::self()->showTrayIcon()) {
0126         show();
0127     }
0128 }
0129 #else
0130 SystrayIcon::SystrayIcon(QObject *parent)
0131     : QObject(parent)
0132 {
0133 }
0134 #endif
0135 
0136 bool SystrayIcon::available() const
0137 {
0138 #ifndef Q_OS_ANDROID
0139     return QSystemTrayIcon::isSystemTrayAvailable();
0140 #else
0141     return false;
0142 #endif
0143 }
0144 
0145 void SystrayIcon::setIconColor(SystrayIcon::IconColor iconColor)
0146 {
0147 #ifndef Q_OS_ANDROID
0148     // do not specify svg-extension; icon will not be visible due to [QTBUG-53550]
0149     switch (iconColor) {
0150     case SystrayIcon::IconColor::Colorful:
0151         setIcon(QIcon(QStringLiteral(":/icons/kasts")));
0152         break;
0153     case SystrayIcon::IconColor::Light:
0154         setIcon(QIcon(QStringLiteral(":/icons/kasts-tray-light")));
0155         break;
0156     case SystrayIcon::IconColor::Dark:
0157         setIcon(QIcon(QStringLiteral(":/icons/kasts-tray-dark")));
0158         break;
0159     }
0160 #endif
0161 }
0162 
0163 int SystrayIcon::iconColorEnumToInt(SystrayIcon::IconColor iconColor)
0164 {
0165     switch (iconColor) {
0166     case SystrayIcon::IconColor::Light:
0167         return 1;
0168     case SystrayIcon::IconColor::Dark:
0169         return 2;
0170     case SystrayIcon::IconColor::Colorful:
0171     default:
0172         return 0;
0173     }
0174 }
0175 
0176 SystrayIcon::IconColor SystrayIcon::intToIconColorEnum(int iconColorCode)
0177 {
0178     switch (iconColorCode) {
0179     case 1:
0180         return SystrayIcon::IconColor::Light;
0181     case 2:
0182         return SystrayIcon::IconColor::Dark;
0183     case 0:
0184     default:
0185         return SystrayIcon::IconColor::Colorful;
0186     }
0187 }