Use tray icon from system theme only if option is set
[qBittorrent.git] / src / gui / desktopintegration.cpp
blob5ef14e7269b2daea5a805b4bf6943be792b17297
1 /*
2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2022 Vladimir Golovnev <glassez@yandex.ru>
4 * Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * In addition, as a special exception, the copyright holders give permission to
21 * link this program with the OpenSSL project's "OpenSSL" library (or with
22 * modified versions of it that use the same license as the "OpenSSL" library),
23 * and distribute the linked executables. You must obey the GNU General Public
24 * License in all respects for all of the code used other than "OpenSSL". If you
25 * modify file(s), you may extend this exception to your version of the file(s),
26 * but you are not obligated to do so. If you do not wish to do so, delete this
27 * exception statement from your version.
30 #include "desktopintegration.h"
32 #include <chrono>
34 #include <QMenu>
35 #include <QTimer>
37 #ifndef Q_OS_MACOS
38 #include <QSystemTrayIcon>
39 #endif
41 #include "base/preferences.h"
42 #include "uithememanager.h"
44 #ifdef Q_OS_MACOS
45 #include "macutilities.h"
46 #endif
48 #ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
49 #include "notifications/dbusnotifier.h"
50 #endif
52 namespace
54 #ifdef Q_OS_MACOS
55 DesktopIntegration *desktopIntegrationInstance = nullptr;
57 bool handleDockClicked(id self, SEL cmd, ...)
59 Q_UNUSED(self);
60 Q_UNUSED(cmd);
62 Q_ASSERT(desktopIntegrationInstance);
63 emit desktopIntegrationInstance->activationRequested();
65 return true;
67 #endif
70 using namespace std::chrono_literals;
72 #define SETTINGS_KEY(name) u"GUI/" name
73 #define NOTIFICATIONS_SETTINGS_KEY(name) (SETTINGS_KEY(u"Notifications/"_qs) name)
75 DesktopIntegration::DesktopIntegration(QObject *parent)
76 : QObject(parent)
77 , m_storeNotificationEnabled {NOTIFICATIONS_SETTINGS_KEY(u"Enabled"_qs), true}
78 #ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
79 , m_storeNotificationTimeOut {NOTIFICATIONS_SETTINGS_KEY(u"Timeout"_qs), -1}
80 #endif
82 #ifdef Q_OS_MACOS
83 desktopIntegrationInstance = this;
84 MacUtils::overrideDockClickHandler(handleDockClicked);
85 #else
86 if (Preferences::instance()->systemTrayEnabled())
87 createTrayIcon();
89 #ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
90 if (isNotificationsEnabled())
92 m_notifier = new DBusNotifier(this);
93 connect(m_notifier, &DBusNotifier::messageClicked, this, &DesktopIntegration::notificationClicked);
95 #endif
96 #endif
98 connect(Preferences::instance(), &Preferences::changed, this, &DesktopIntegration::onPreferencesChanged);
101 DesktopIntegration::~DesktopIntegration()
103 if (m_menu)
104 delete m_menu;
107 bool DesktopIntegration::isActive() const
109 #ifdef Q_OS_MACOS
110 return true;
111 #else
112 return m_systrayIcon && QSystemTrayIcon::isSystemTrayAvailable();
113 #endif
116 QString DesktopIntegration::toolTip() const
118 return m_toolTip;
121 void DesktopIntegration::setToolTip(const QString &toolTip)
123 if (m_toolTip == toolTip)
124 return;
126 m_toolTip = toolTip;
127 #ifndef Q_OS_MACOS
128 if (m_systrayIcon)
129 m_systrayIcon->setToolTip(m_toolTip);
130 #endif
133 QMenu *DesktopIntegration::menu() const
135 return m_menu;
138 void DesktopIntegration::setMenu(QMenu *menu)
140 if (menu == m_menu)
141 return;
143 #if defined Q_OS_MACOS
144 if (m_menu)
145 delete m_menu;
147 m_menu = menu;
149 if (m_menu)
150 m_menu->setAsDockMenu();
151 #elif defined Q_OS_UNIX
152 const bool systemTrayEnabled = m_systrayIcon;
153 if (m_menu)
155 if (m_systrayIcon)
157 delete m_systrayIcon;
158 m_systrayIcon = nullptr;
160 delete m_menu;
163 m_menu = menu;
165 if (systemTrayEnabled && !m_systrayIcon)
166 createTrayIcon();
167 #else
168 if (m_menu)
169 delete m_menu;
171 m_menu = menu;
173 if (m_systrayIcon)
174 m_systrayIcon->setContextMenu(m_menu);
175 #endif
178 bool DesktopIntegration::isNotificationsEnabled() const
180 return m_storeNotificationEnabled;
183 void DesktopIntegration::setNotificationsEnabled(const bool value)
185 if (m_storeNotificationEnabled == value)
186 return;
188 m_storeNotificationEnabled = value;
190 #ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
191 if (value)
193 m_notifier = new DBusNotifier(this);
194 connect(m_notifier, &DBusNotifier::messageClicked, this, &DesktopIntegration::notificationClicked);
196 else
198 delete m_notifier;
199 m_notifier = nullptr;
201 #endif
204 int DesktopIntegration::notificationTimeout() const
206 #ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
207 return m_storeNotificationTimeOut;
208 #else
209 return 5000;
210 #endif
213 #ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
214 void DesktopIntegration::setNotificationTimeout(const int value)
216 m_storeNotificationTimeOut = value;
218 #endif
220 void DesktopIntegration::showNotification(const QString &title, const QString &msg) const
222 if (!isNotificationsEnabled())
223 return;
225 #ifdef Q_OS_MACOS
226 MacUtils::displayNotification(title, msg);
227 #else
228 #ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
229 m_notifier->showMessage(title, msg, notificationTimeout());
230 #else
231 if (m_systrayIcon && QSystemTrayIcon::supportsMessages())
232 m_systrayIcon->showMessage(title, msg, QSystemTrayIcon::Information, notificationTimeout());
233 #endif
234 #endif
237 void DesktopIntegration::onPreferencesChanged()
239 #ifndef Q_OS_MACOS
240 if (Preferences::instance()->systemTrayEnabled())
242 if (m_systrayIcon)
244 // Reload systray icon
245 m_systrayIcon->setIcon(getSystrayIcon());
247 else
249 createTrayIcon();
252 else
254 delete m_systrayIcon;
255 m_systrayIcon = nullptr;
256 emit stateChanged();
258 #endif
261 #ifndef Q_OS_MACOS
262 void DesktopIntegration::createTrayIcon()
264 Q_ASSERT(!m_systrayIcon);
266 m_systrayIcon = new QSystemTrayIcon(getSystrayIcon(), this);
268 m_systrayIcon->setToolTip(m_toolTip);
270 if (m_menu)
271 m_systrayIcon->setContextMenu(m_menu);
273 connect(m_systrayIcon, &QSystemTrayIcon::activated, this
274 , [this](const QSystemTrayIcon::ActivationReason reason)
276 if (reason == QSystemTrayIcon::Trigger)
277 emit activationRequested();
279 #ifndef QBT_USES_CUSTOMDBUSNOTIFICATIONS
280 connect(m_systrayIcon, &QSystemTrayIcon::messageClicked, this, &DesktopIntegration::notificationClicked);
281 #endif
283 m_systrayIcon->show();
284 emit stateChanged();
287 QIcon DesktopIntegration::getSystrayIcon() const
289 const TrayIcon::Style style = Preferences::instance()->trayIconStyle();
290 switch (style)
292 default:
293 case TrayIcon::Style::Normal:
294 return UIThemeManager::instance()->getIcon(u"qbittorrent-tray"_qs);
296 case TrayIcon::Style::MonoDark:
297 return UIThemeManager::instance()->getIcon(u"qbittorrent-tray-dark"_qs);
299 case TrayIcon::Style::MonoLight:
300 return UIThemeManager::instance()->getIcon(u"qbittorrent-tray-light"_qs);
303 #endif // Q_OS_MACOS