File indexing completed on 2025-01-19 03:56:07
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2008-07-03 0007 * Description : A wrapper send desktop notifications 0008 * 0009 * SPDX-FileCopyrightText: 2009-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2009-2011 by Michael G. Hansen <mike at mghansen dot de> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "dnotificationwrapper.h" 0017 #include "digikam_config.h" 0018 0019 // Qt includes 0020 0021 #include <QProcess> 0022 #include <QApplication> 0023 #include <QStandardPaths> 0024 #include <QIcon> 0025 0026 #ifdef HAVE_DBUS 0027 # include <QDBusConnection> 0028 # include <QDBusConnectionInterface> 0029 #endif 0030 0031 // KDE includes 0032 0033 #ifdef HAVE_KNOTIFICATIONS 0034 # include <knotification.h> 0035 #endif 0036 0037 // Local includes 0038 0039 #include "digikam_debug.h" 0040 #include "digikam_globals.h" 0041 #include "dnotificationpopup.h" 0042 0043 namespace Digikam 0044 { 0045 0046 /** 0047 * Re-implementation of DNotificationPopup to move pop-up notification 0048 * window on the bottom right corner of parent window. The goal is to simulate 0049 * the position of KDE notifier pop-up from task bar if this one is not available, 0050 * as for ex under Windows, Gnome, or using a remote connection through ssh. 0051 */ 0052 class Q_DECL_HIDDEN NotificationPassivePopup : public DNotificationPopup 0053 { 0054 Q_OBJECT 0055 0056 public: 0057 0058 explicit NotificationPassivePopup(QWidget* const parent) 0059 : DNotificationPopup(parent), 0060 m_parent (parent) 0061 { 0062 } 0063 0064 void showNotification(const QString& caption, const QString& text, const QPixmap& icon) 0065 { 0066 setView(caption, text, icon); 0067 QPoint ppos = m_parent->pos(); 0068 QSize psize = m_parent->frameSize(); 0069 int offsetx = minimumSizeHint().width() + 30; 0070 int offsety = minimumSizeHint().height() + 30; 0071 show(QPoint(ppos.x() + psize.width() - offsetx, 0072 ppos.y() + psize.height() - offsety)); 0073 } 0074 0075 private: 0076 0077 QWidget* m_parent = nullptr; 0078 }; 0079 0080 // ---------------------------------------------------------------------------------------------- 0081 0082 #if defined HAVE_KNOTIFICATIONS && defined HAVE_DBUS 0083 0084 static inline bool detectKDEDesktopIsRunning() 0085 { 0086 const QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP"); 0087 0088 if (!xdgCurrentDesktop.isEmpty()) 0089 { 0090 return (xdgCurrentDesktop.toUpper() == "KDE"); 0091 } 0092 0093 // Classic fallbacks 0094 0095 if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION")) 0096 { 0097 return true; 0098 } 0099 0100 return false; 0101 } 0102 0103 #endif 0104 0105 // ---------------------------------------------------------------------------------------------- 0106 0107 void DNotificationWrapper(const QString& eventId, const QString& message, 0108 QWidget* const parent, const QString& windowTitle, 0109 const QPixmap& pixmap) 0110 { 0111 QPixmap logoPixmap = pixmap; 0112 0113 if (logoPixmap.isNull()) 0114 { 0115 if (QApplication::applicationName() == QLatin1String("digikam")) 0116 { 0117 logoPixmap = QIcon::fromTheme(QLatin1String("digikam")).pixmap(QSize(48,48)); 0118 } 0119 else 0120 { 0121 logoPixmap = QIcon::fromTheme(QLatin1String("showfoto")).pixmap(QSize(48,48)); 0122 } 0123 } 0124 0125 #if defined HAVE_KNOTIFICATIONS && defined HAVE_DBUS 0126 0127 // NOTE: This detection of KDE desktop is not perfect because KNotification service may never be started. 0128 // But in a regular KDE session, KNotification service should be running already. 0129 0130 if (detectKDEDesktopIsRunning() && 0131 QDBusConnection::sessionBus().interface()-> 0132 isServiceRegistered(QLatin1String("org.kde.StatusNotifierWatcher")).value()) 0133 { 0134 qCDebug(DIGIKAM_GENERAL_LOG) << "Event is dispatched to KDE desktop notifier"; 0135 0136 if (eventId.isEmpty()) 0137 { 0138 0139 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0140 0141 KNotification::event(KNotification::Notification, message, logoPixmap); 0142 0143 #else 0144 0145 KNotification::event(KNotification::Notification, message, logoPixmap, parent); 0146 0147 #endif 0148 0149 } 0150 else 0151 { 0152 0153 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0154 0155 KNotification::event(eventId, message, logoPixmap); 0156 0157 #else 0158 0159 KNotification::event(eventId, message, logoPixmap, parent); 0160 0161 #endif 0162 0163 } 0164 } 0165 else 0166 0167 #else 0168 0169 { 0170 Q_UNUSED(eventId); 0171 } 0172 0173 #endif 0174 0175 #ifdef Q_OS_DARWIN 0176 0177 // OSX support 0178 0179 if (MacNativeDispatchNotify(windowTitle, message)) 0180 { 0181 qCDebug(DIGIKAM_GENERAL_LOG) << "Event is dispatched to OSX desktop notifier"; 0182 0183 return; 0184 } 0185 else 0186 0187 #endif // Q_OS_DARWIN 0188 0189 { 0190 // Other Linux Desktops 0191 0192 QProcess proc; 0193 0194 proc.setProcessEnvironment(adjustedEnvironmentForAppImage()); 0195 proc.start(QLatin1String("notify-send"), 0196 QStringList() << windowTitle 0197 << message 0198 << QLatin1String("-a") 0199 << QApplication::applicationName()); 0200 0201 if (proc.waitForFinished() && proc.exitCode() == 0) 0202 { 0203 qCDebug(DIGIKAM_GENERAL_LOG) << "Event is dispatched to desktop notifier through DBUS"; 0204 0205 return; 0206 } 0207 else 0208 { 0209 if (!parent) 0210 { 0211 qCWarning(DIGIKAM_GENERAL_LOG) << "parent is null"; 0212 0213 return; 0214 } 0215 0216 qCDebug(DIGIKAM_GENERAL_LOG) << "Event is dispatched through a passive pop-up"; 0217 0218 NotificationPassivePopup* const popup = new NotificationPassivePopup(parent); 0219 popup->showNotification(windowTitle, message, logoPixmap); 0220 } 0221 } 0222 } 0223 0224 } // namespace Digikam 0225 0226 #include "dnotificationwrapper.moc"