1
0
mirror of https://github.com/clementine-player/Clementine synced 2025-02-01 11:56:45 +01:00

Refactor the system tray icon code a bit

This commit is contained in:
David Sansome 2010-06-22 11:52:55 +00:00
parent 74ec360ab5
commit b4add2a7be
9 changed files with 256 additions and 115 deletions

View File

@ -118,6 +118,7 @@ set(SOURCES
ui/globalshortcutsdialog.cpp
ui/iconloader.cpp
ui/mainwindow.cpp
ui/qtsystemtrayicon.cpp
ui/settingsdialog.cpp
ui/systemtrayicon.cpp
@ -219,6 +220,7 @@ set(HEADERS
ui/globalshortcutgrabber.h
ui/globalshortcutsdialog.h
ui/mainwindow.h
ui/qtsystemtrayicon.h
ui/settingsdialog.h
ui/systemtrayicon.h

View File

@ -50,6 +50,7 @@
#include "ui/equalizer.h"
#include "ui/globalshortcutsdialog.h"
#include "ui/iconloader.h"
#include "ui/qtsystemtrayicon.h"
#include "ui/settingsdialog.h"
#include "ui/systemtrayicon.h"
#include "widgets/errordialog.h"
@ -98,7 +99,7 @@ const char* MainWindow::kAllFilesFilterSpec =
MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidget *parent)
: QMainWindow(parent),
ui_(new Ui_MainWindow),
tray_icon_(new SystemTrayIcon(this)),
tray_icon_(new QtSystemTrayIcon(this)),
osd_(new OSD(tray_icon_, network, this)),
edit_tag_dialog_(new EditTagDialog),
about_dialog_(new About),
@ -142,8 +143,6 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
// Initialise the UI
ui_->setupUi(this);
tray_icon_->setIcon(windowIcon());
tray_icon_->setToolTip(QCoreApplication::applicationName());
ui_->volume->setValue(player_->GetVolume());
@ -387,17 +386,17 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
add_stream_dialog_.get(), SLOT(show()));
// Tray icon
QMenu* tray_menu = new QMenu(this);
tray_menu->addAction(ui_->action_previous_track);
tray_menu->addAction(ui_->action_play_pause);
tray_menu->addAction(ui_->action_stop);
tray_menu->addAction(ui_->action_stop_after_this_track);
tray_menu->addAction(ui_->action_next_track);
tray_menu->addSeparator();
tray_menu->addAction(ui_->action_love);
tray_menu->addAction(ui_->action_ban);
tray_menu->addSeparator();
tray_menu->addAction(ui_->action_quit);
tray_icon_->SetupMenu(ui_->action_previous_track,
ui_->action_play_pause,
ui_->action_stop,
ui_->action_stop_after_this_track,
ui_->action_next_track,
ui_->action_love,
ui_->action_ban,
ui_->action_quit);
connect(tray_icon_, SIGNAL(PlayPause()), player_, SLOT(PlayPause()));
connect(tray_icon_, SIGNAL(ShowHide()), SLOT(ToggleShowHide()));
connect(tray_icon_, SIGNAL(ChangeVolume(int)), SLOT(VolumeWheelEvent(int)));
#ifdef Q_OS_DARWIN
// Add check for updates item to application menu.
@ -417,10 +416,6 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
if (QSysInfo::MacintoshVersion != QSysInfo::MV_SNOWLEOPARD) {
ui_->action_configure_global_shortcuts->setEnabled(false);
}
#else
tray_icon_->setContextMenu(tray_menu);
connect(tray_icon_, SIGNAL(WheelEvent(int)), SLOT(VolumeWheelEvent(int)));
connect(tray_icon_, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), SLOT(TrayClicked(QSystemTrayIcon::ActivationReason)));
#endif
// Global shortcuts
@ -507,7 +502,7 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
}
// Force the window to show in case somehow the config has tray and window set to hide
if (hidden && !tray_icon_->isVisible()) {
if (hidden && !tray_icon_->IsVisible()) {
settings_.setValue("hidden", false);
show();
}
@ -534,7 +529,7 @@ void MainWindow::ReloadSettings() {
#ifndef Q_OS_DARWIN
bool show_tray = settings_.value("showtray", true).toBool();
tray_icon_->setVisible(show_tray);
tray_icon_->SetVisible(show_tray);
if (!show_tray && !isVisible())
show();
#endif
@ -732,34 +727,22 @@ void MainWindow::VolumeWheelEvent(int delta) {
ui_->volume->setValue(ui_->volume->value() + delta / 30);
}
void MainWindow::TrayClicked(QSystemTrayIcon::ActivationReason reason) {
switch (reason) {
case QSystemTrayIcon::DoubleClick:
case QSystemTrayIcon::Trigger:
if (settings_.value("hidden").toBool()) {
show();
SetHiddenInTray(false);
} else if (isActiveWindow()) {
hide();
setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
SetHiddenInTray(true);
} else if (isMinimized()) {
hide();
setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
SetHiddenInTray(false);
} else {
// Window is not hidden but does not have focus; bring it to front.
activateWindow();
raise();
}
break;
case QSystemTrayIcon::MiddleClick:
player_->PlayPause();
break;
default:
break;
void MainWindow::ToggleShowHide() {
if (settings_.value("hidden").toBool()) {
show();
SetHiddenInTray(false);
} else if (isActiveWindow()) {
hide();
setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
SetHiddenInTray(true);
} else if (isMinimized()) {
hide();
setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
SetHiddenInTray(false);
} else {
// Window is not hidden but does not have focus; bring it to front.
activateWindow();
raise();
}
}
@ -773,7 +756,7 @@ void MainWindow::StopAfterCurrent() {
*/
void MainWindow::closeEvent(QCloseEvent* event) {
#ifndef Q_OS_DARWIN
if (tray_icon_->isVisible() && event->spontaneous()) {
if (tray_icon_->IsVisible() && event->spontaneous()) {
event->ignore();
SetHiddenInTray(true);
} else {

View File

@ -123,7 +123,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
void LibrarySongsDoubleClicked(const SongList& songs);
void VolumeWheelEvent(int delta);
void TrayClicked(QSystemTrayIcon::ActivationReason reason);
void ToggleShowHide();
void UpdateTrackPosition();

109
src/ui/qtsystemtrayicon.cpp Normal file
View File

@ -0,0 +1,109 @@
/* This file is part of Clementine.
Clementine 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
(at your option) any later version.
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "qtsystemtrayicon.h"
#include <QCoreApplication>
#include <QMenu>
#include <QSystemTrayIcon>
#include <QWheelEvent>
QtSystemTrayIcon::QtSystemTrayIcon(QObject* parent)
: SystemTrayIcon(parent),
tray_(new QSystemTrayIcon(this)),
menu_(new QMenu)
{
QIcon icon(":icon.png");
orange_icon_ = icon.pixmap(48, QIcon::Normal);
grey_icon_ = icon.pixmap(48, QIcon::Disabled);
tray_->setIcon(orange_icon_);
tray_->setToolTip(QCoreApplication::applicationName());
tray_->installEventFilter(this);
connect(tray_, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
SLOT(Clicked(QSystemTrayIcon::ActivationReason)));
}
QtSystemTrayIcon::~QtSystemTrayIcon() {
delete menu_;
}
bool QtSystemTrayIcon::eventFilter(QObject* object, QEvent* event) {
if (QObject::eventFilter(object, event))
return true;
if (object != tray_)
return false;
if (event->type() == QEvent::Wheel) {
QWheelEvent* e = static_cast<QWheelEvent*>(event);
emit ChangeVolume(e->delta());
return true;
}
return false;
}
void QtSystemTrayIcon::SetupMenu(
QAction* previous, QAction* play, QAction* stop, QAction* stop_after,
QAction* next, QAction* love, QAction* ban, QAction* quit) {
menu_->addAction(previous);
menu_->addAction(play);
menu_->addAction(stop);
menu_->addAction(stop_after);
menu_->addAction(next);
menu_->addSeparator();
menu_->addAction(love);
menu_->addAction(ban);
menu_->addSeparator();
menu_->addAction(quit);
tray_->setContextMenu(menu_);
}
void QtSystemTrayIcon::Clicked(QSystemTrayIcon::ActivationReason reason) {
switch (reason) {
case QSystemTrayIcon::DoubleClick:
case QSystemTrayIcon::Trigger:
emit ShowHide();
break;
case QSystemTrayIcon::MiddleClick:
emit PlayPause();
break;
default:
break;
}
}
void QtSystemTrayIcon::ShowPopup(const QString &summary,
const QString &message, int timeout) {
tray_->showMessage(summary, message, QSystemTrayIcon::NoIcon, timeout);
}
void QtSystemTrayIcon::UpdateIcon() {
tray_->setIcon(CreateIcon(orange_icon_, grey_icon_));
}
bool QtSystemTrayIcon::IsVisible() const {
return tray_->isVisible();
}
void QtSystemTrayIcon::SetVisible(bool visible) {
tray_->setVisible(visible);
}

57
src/ui/qtsystemtrayicon.h Normal file
View File

@ -0,0 +1,57 @@
/* This file is part of Clementine.
Clementine 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
(at your option) any later version.
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QTSYSTEMTRAYICON_H
#define QTSYSTEMTRAYICON_H
#include "systemtrayicon.h"
#include <QSystemTrayIcon>
class QtSystemTrayIcon : public SystemTrayIcon {
Q_OBJECT
public:
QtSystemTrayIcon(QObject* parent = 0);
~QtSystemTrayIcon();
void SetupMenu(QAction* previous, QAction* play, QAction* stop,
QAction* stop_after, QAction* next, QAction* love,
QAction* ban, QAction* quit);
bool IsVisible() const;
void SetVisible(bool visible);
void ShowPopup(const QString &summary, const QString &message, int timeout);
protected:
// SystemTrayIcon
void UpdateIcon();
// QObject
bool eventFilter(QObject *, QEvent *);
private slots:
void Clicked(QSystemTrayIcon::ActivationReason);
private:
QSystemTrayIcon* tray_;
QMenu* menu_;
QPixmap orange_icon_;
QPixmap grey_icon_;
};
#endif // QTSYSTEMTRAYICON_H

View File

@ -26,50 +26,22 @@
#include <cmath>
SystemTrayIcon::SystemTrayIcon(QObject* parent)
: QSystemTrayIcon(parent),
: QObject(parent),
percentage_(0),
playing_icon_(":/tiny-start.png"),
paused_icon_(":/tiny-pause.png"),
percentage_(0)
paused_icon_(":/tiny-pause.png")
{
#ifdef Q_OS_DARWIN
hide();
#endif
}
bool SystemTrayIcon::event(QEvent* event) {
if (event->type() == QEvent::Wheel) {
emit WheelEvent(static_cast<QWheelEvent*>(event)->delta());
return true;
}
return QSystemTrayIcon::event(event);
}
void SystemTrayIcon::SetProgress(int percentage) {
percentage_ = percentage;
Update();
}
void SystemTrayIcon::Update() {
if (icon_.isNull()) {
#ifdef Q_OS_DARWIN
QIcon big_icon(":icon_large.png");
icon_ = big_icon.pixmap(128, 128, QIcon::Normal);
QIcon big_grey_icon(":icon_large_grey.png");
grey_icon_ = big_grey_icon.pixmap(128, 128, QIcon::Normal);
#else
icon_ = icon().pixmap(geometry().size(), QIcon::Normal);
grey_icon_ = icon().pixmap(geometry().size(), QIcon::Disabled);
#endif
if (icon_.isNull())
return;
}
QRect rect(icon_.rect());
QPixmap SystemTrayIcon::CreateIcon(const QPixmap& icon, const QPixmap& grey_icon) {
QRect rect(icon.rect());
// The angle of the line that's used to cover the icon.
// Centered on rect.topRight()
double angle = double(100 - percentage_) / 100.0 * M_PI_2 + M_PI;
double angle = double(100 - song_progress()) / 100.0 * M_PI_2 + M_PI;
double length = sqrt(pow(rect.width(), 2.0) + pow(rect.height(), 2.0));
QPolygon mask;
@ -78,24 +50,24 @@ void SystemTrayIcon::Update() {
length * sin(angle),
- length * cos(angle));
if (percentage_ > 50)
if (song_progress() > 50)
mask << rect.bottomLeft();
mask << rect.topLeft();
mask << rect.topRight();
QPixmap icon(icon_);
QPainter p(&icon);
QPixmap ret(icon);
QPainter p(&ret);
// Draw the grey bit over the orange icon
p.setClipRegion(mask);
p.drawPixmap(0, 0, grey_icon_);
p.drawPixmap(0, 0, grey_icon);
p.setClipping(false);
// Draw the playing or paused icon in the top-right
if (!current_state_icon_.isNull()) {
if (!current_state_icon().isNull()) {
int height = rect.height() / 2;
QPixmap scaled(current_state_icon_.scaledToHeight(height, Qt::SmoothTransformation));
QPixmap scaled(current_state_icon().scaledToHeight(height, Qt::SmoothTransformation));
QRect state_rect(rect.width() - scaled.width(), 0, scaled.width(), scaled.height());
p.drawPixmap(state_rect, scaled);
@ -103,25 +75,25 @@ void SystemTrayIcon::Update() {
p.end();
#ifdef Q_OS_DARWIN
// Setting main window icon.
QApplication::setWindowIcon(icon);
#else
setIcon(icon);
#endif
return ret;
}
void SystemTrayIcon::SetProgress(int percentage) {
percentage_ = percentage;
UpdateIcon();
}
void SystemTrayIcon::SetPaused() {
current_state_icon_ = paused_icon_;
Update();
UpdateIcon();
}
void SystemTrayIcon::SetPlaying() {
current_state_icon_ = playing_icon_;
Update();
UpdateIcon();
}
void SystemTrayIcon::SetStopped() {
current_state_icon_ = QPixmap();
Update();
UpdateIcon();
}

View File

@ -17,15 +17,28 @@
#ifndef SYSTEMTRAYICON_H
#define SYSTEMTRAYICON_H
#include <QSystemTrayIcon>
#include <QObject>
#include <QPixmap>
class SystemTrayIcon : public QSystemTrayIcon {
class QAction;
class SystemTrayIcon : public QObject {
Q_OBJECT
public:
SystemTrayIcon(QObject* parent = 0);
virtual bool event(QEvent* event);
// Called once to create the icon's context menu
virtual void SetupMenu(QAction* previous, QAction* play, QAction* stop,
QAction* stop_after, QAction* next, QAction* love,
QAction* ban, QAction* quit) = 0;
virtual bool IsVisible() const { return true; }
virtual void SetVisible(bool visible) {}
// Called by the OSD
virtual void ShowPopup(const QString& summary, const QString& message,
int timeout) {}
public slots:
void SetProgress(int percentage);
@ -34,17 +47,21 @@ class SystemTrayIcon : public QSystemTrayIcon {
void SetStopped();
signals:
void WheelEvent(int delta);
void ChangeVolume(int delta);
void ShowHide();
void PlayPause();
protected:
virtual void UpdateIcon() = 0;
QPixmap CreateIcon(const QPixmap& icon, const QPixmap& grey_icon);
int song_progress() const { return percentage_; }
QPixmap current_state_icon() const { return current_state_icon_; }
private:
void Update();
QPixmap icon_;
QPixmap grey_icon_;
int percentage_;
QPixmap playing_icon_;
QPixmap paused_icon_;
int percentage_;
QPixmap current_state_icon_;
};

View File

@ -16,6 +16,7 @@
#include "osd.h"
#include "osdpretty.h"
#include "ui/systemtrayicon.h"
#include <QCoreApplication>
#include <QtDebug>
@ -23,7 +24,7 @@
const char* OSD::kSettingsGroup = "OSD";
OSD::OSD(QSystemTrayIcon* tray_icon, NetworkAccessManager* network, QObject* parent)
OSD::OSD(SystemTrayIcon* tray_icon, NetworkAccessManager* network, QObject* parent)
: QObject(parent),
tray_icon_(tray_icon),
timeout_msec_(5000),
@ -167,7 +168,7 @@ void OSD::ShowMessage(const QString& summary,
#ifndef Q_OS_DARWIN
case TrayPopup:
tray_icon_->showMessage(summary, message, QSystemTrayIcon::NoIcon, timeout_msec_);
tray_icon_->ShowPopup(summary, message, timeout_msec_);
break;
#endif

View File

@ -19,15 +19,15 @@
#include <QImage>
#include <QObject>
#include <QSystemTrayIcon>
#include "engines/engine_fwd.h"
#include "core/albumcoverloader.h"
#include "core/backgroundthread.h"
#include "core/song.h"
class OSDPretty;
class NetworkAccessManager;
class OSDPretty;
class SystemTrayIcon;
class QDBusPendingCallWatcher;
@ -44,7 +44,7 @@ class OSD : public QObject {
Q_OBJECT
public:
OSD(QSystemTrayIcon* tray_icon, NetworkAccessManager* network, QObject* parent = 0);
OSD(SystemTrayIcon* tray_icon, NetworkAccessManager* network, QObject* parent = 0);
~OSD();
static const char* kSettingsGroup;
@ -97,7 +97,7 @@ class OSD : public QObject {
void AlbumArtLoaded(const WaitingForAlbumArt info, const QImage& image);
private:
QSystemTrayIcon* tray_icon_;
SystemTrayIcon* tray_icon_;
int timeout_msec_;
Behaviour behaviour_;
bool show_on_volume_change_;