Enable customizing the save statistics time interval
[qBittorrent.git] / src / gui / desktopintegration.cpp
blobb927633d92fac95d7643ec470e02bfca5a23dadb
1 /*
2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2022-2024 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 <QtEnvironmentVariables>
35 #include <QMenu>
36 #include <QTimer>
38 #ifndef Q_OS_MACOS
39 #include <QSystemTrayIcon>
40 #endif
42 #include "base/preferences.h"
43 #include "uithememanager.h"
45 #ifdef Q_OS_MACOS
46 #include "macutilities.h"
47 #endif
49 #ifdef QBT_USES_DBUS
50 #include "notifications/dbusnotifier.h"
51 #endif
53 namespace
55 #ifdef Q_OS_MACOS
56 DesktopIntegration *desktopIntegrationInstance = nullptr;
58 bool handleDockClicked([[maybe_unused]] id self, [[maybe_unused]] SEL cmd, ...)
60 Q_ASSERT(desktopIntegrationInstance);
61 emit desktopIntegrationInstance->activationRequested();
63 return true;
65 #endif
68 using namespace std::chrono_literals;
70 #define SETTINGS_KEY(name) u"GUI/" name
71 #define NOTIFICATIONS_SETTINGS_KEY(name) (SETTINGS_KEY(u"Notifications/"_s) name)
73 DesktopIntegration::DesktopIntegration(QObject *parent)
74 : QObject(parent)
75 , m_storeNotificationEnabled {NOTIFICATIONS_SETTINGS_KEY(u"Enabled"_s), true}
76 , m_menu {new QMenu}
77 #ifdef QBT_USES_DBUS
78 , m_storeNotificationTimeOut {NOTIFICATIONS_SETTINGS_KEY(u"Timeout"_s), -1}
79 #endif
81 #ifdef Q_OS_MACOS
82 desktopIntegrationInstance = this;
83 MacUtils::overrideDockClickHandler(handleDockClicked);
84 m_menu->setAsDockMenu();
85 #else
86 if (Preferences::instance()->systemTrayEnabled())
87 createTrayIcon();
89 #ifdef QBT_USES_DBUS
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 delete m_menu;
106 bool DesktopIntegration::isActive() const
108 #ifdef Q_OS_MACOS
109 return true;
110 #else
111 return m_systrayIcon && QSystemTrayIcon::isSystemTrayAvailable();
112 #endif
115 QString DesktopIntegration::toolTip() const
117 return m_toolTip;
120 void DesktopIntegration::setToolTip(const QString &toolTip)
122 if (m_toolTip == toolTip)
123 return;
125 m_toolTip = toolTip;
126 #ifndef Q_OS_MACOS
127 if (m_systrayIcon)
128 m_systrayIcon->setToolTip(m_toolTip);
129 #endif
132 QMenu *DesktopIntegration::menu() const
134 return m_menu;
137 bool DesktopIntegration::isNotificationsEnabled() const
139 return m_storeNotificationEnabled;
142 void DesktopIntegration::setNotificationsEnabled(const bool value)
144 if (m_storeNotificationEnabled == value)
145 return;
147 m_storeNotificationEnabled = value;
149 #ifdef QBT_USES_DBUS
150 if (value)
152 m_notifier = new DBusNotifier(this);
153 connect(m_notifier, &DBusNotifier::messageClicked, this, &DesktopIntegration::notificationClicked);
155 else
157 delete m_notifier;
158 m_notifier = nullptr;
160 #endif
163 int DesktopIntegration::notificationTimeout() const
165 #ifdef QBT_USES_DBUS
166 return m_storeNotificationTimeOut;
167 #else
168 return 5000;
169 #endif
172 #ifdef QBT_USES_DBUS
173 void DesktopIntegration::setNotificationTimeout(const int value)
175 m_storeNotificationTimeOut = value;
177 #endif
179 void DesktopIntegration::showNotification(const QString &title, const QString &msg) const
181 if (!isNotificationsEnabled())
182 return;
184 #ifdef Q_OS_MACOS
185 MacUtils::displayNotification(title, msg);
186 #else
187 #ifdef QBT_USES_DBUS
188 m_notifier->showMessage(title, msg, notificationTimeout());
189 #else
190 if (m_systrayIcon && QSystemTrayIcon::supportsMessages())
191 m_systrayIcon->showMessage(title, msg, QSystemTrayIcon::Information, notificationTimeout());
192 #endif
193 #endif
196 void DesktopIntegration::onPreferencesChanged()
198 #ifndef Q_OS_MACOS
199 if (Preferences::instance()->systemTrayEnabled())
201 if (m_systrayIcon)
203 // Reload systray icon
204 m_systrayIcon->setIcon(getSystrayIcon());
206 else
208 createTrayIcon();
211 else
213 delete m_systrayIcon;
214 m_systrayIcon = nullptr;
215 emit stateChanged();
217 #endif
220 #ifndef Q_OS_MACOS
221 void DesktopIntegration::createTrayIcon()
223 Q_ASSERT(!m_systrayIcon);
225 m_systrayIcon = new QSystemTrayIcon(getSystrayIcon(), this);
227 m_systrayIcon->setToolTip(m_toolTip);
229 if (m_menu)
230 m_systrayIcon->setContextMenu(m_menu);
232 connect(m_systrayIcon, &QSystemTrayIcon::activated, this
233 , [this](const QSystemTrayIcon::ActivationReason reason)
235 if (reason == QSystemTrayIcon::Trigger)
236 emit activationRequested();
238 #ifndef QBT_USES_DBUS
239 connect(m_systrayIcon, &QSystemTrayIcon::messageClicked, this, &DesktopIntegration::notificationClicked);
240 #endif
242 m_systrayIcon->show();
243 emit stateChanged();
246 QIcon DesktopIntegration::getSystrayIcon() const
248 const TrayIcon::Style style = Preferences::instance()->trayIconStyle();
249 QIcon icon;
250 switch (style)
252 default:
253 case TrayIcon::Style::Normal:
254 icon = UIThemeManager::instance()->getIcon(u"qbittorrent-tray"_s);
255 break;
256 case TrayIcon::Style::MonoDark:
257 icon = UIThemeManager::instance()->getIcon(u"qbittorrent-tray-dark"_s);
258 break;
259 case TrayIcon::Style::MonoLight:
260 icon = UIThemeManager::instance()->getIcon(u"qbittorrent-tray-light"_s);
261 break;
263 #ifdef Q_OS_UNIX
264 // Workaround for invisible tray icon in KDE, https://bugreports.qt.io/browse/QTBUG-53550
265 if (qEnvironmentVariable("XDG_CURRENT_DESKTOP").compare(u"KDE", Qt::CaseInsensitive) == 0)
266 return icon.pixmap(32);
267 #endif
268 return icon;
270 #endif // Q_OS_MACOS