File indexing completed on 2024-04-28 05:46:12

0001 /***************************************************************************
0002  *   Copyright © 2009 Harald Sitter <apachelogger@ubuntu.com>              *
0003  *   Copyright © 2009 Jonathan Thomas <echidnaman@kubuntu.org>             *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or         *
0006  *   modify it under the terms of the GNU General Public License as        *
0007  *   published by the Free Software Foundation; either version 2 of        *
0008  *   the License or (at your option) version 3 or any later version        *
0009  *   accepted by the membership of KDE e.V. (or its successor approved     *
0010  *   by the membership of KDE e.V.), which shall act as a proxy            *
0011  *   defined in Section 14 of version 3 of the license.                    *
0012  *                                                                         *
0013  *   This program is distributed in the hope that it will be useful,       *
0014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0016  *   GNU General Public License for more details.                          *
0017  *                                                                         *
0018  *   You should have received a copy of the GNU General Public License     *
0019  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
0020  ***************************************************************************/
0021 
0022 #include "event.h"
0023 
0024 #include <QIcon>
0025 #include <QMenu>
0026 #include <QStringBuilder>
0027 
0028 #include <KActionCollection>
0029 #include <KConfig>
0030 #include <KConfigGroup>
0031 #include <KNotification>
0032 #include <KStatusNotifierItem>
0033 
0034 Event::Event(QObject* parent, const QString &name)
0035         : QObject(parent)
0036         , m_name(name)
0037         , m_hidden(false)
0038         , m_active(false)
0039         , m_notifierItem(0)
0040 {
0041     m_hiddenCfgString = QString("hide" % m_name % "Notifier");
0042     m_hidden = readHiddenConfig();
0043     readNotifyConfig();
0044 }
0045 
0046 Event::~Event()
0047 {
0048 }
0049 
0050 bool Event::readHiddenConfig()
0051 {
0052     KConfig cfg("notificationhelper");
0053     KConfigGroup notifyGroup(&cfg, "Event");
0054     return notifyGroup.readEntry(m_hiddenCfgString, false);
0055 }
0056 
0057 void Event::writeHiddenConfig(bool value)
0058 {
0059     KConfig cfg("notificationhelper");
0060     KConfigGroup notifyGroup(&cfg, "Event");
0061     notifyGroup.writeEntry(m_hiddenCfgString, value);
0062     notifyGroup.config()->sync();
0063 }
0064 
0065 void Event::readNotifyConfig()
0066 {
0067     KConfig cfg("notificationhelper");
0068     KConfigGroup notifyTypeGroup(&cfg, "NotificationType");
0069     QString notifyType = notifyTypeGroup.readEntry("NotifyType", "Combo");
0070 
0071     if (notifyType == "Combo") {
0072         m_useKNotify = true;
0073         m_useTrayIcon = true;
0074     } else if (notifyType == "TrayOnly") {
0075         m_useKNotify = false;
0076         m_useTrayIcon = true;
0077     } else { // KNotifyOnly
0078         m_useKNotify = true;
0079         m_useTrayIcon = false;
0080     }
0081 }
0082 
0083 bool Event::isHidden() const
0084 {
0085     return m_hidden;
0086 }
0087 
0088 void Event::show(const QString &icon, const QString &text, const QStringList &actions)
0089 {
0090     if (m_active || m_hidden) {
0091         return;
0092     }
0093 
0094     // Only manually compose a notification if notifications are enabled AND
0095     // we don't have a tray icon, otherwise the tray icon will issue the notification.
0096     if (m_useKNotify && !m_useTrayIcon) {
0097         KNotification::NotificationFlag flag;
0098 
0099         if (!m_useTrayIcon) {
0100             // Tray icon not in use, so be persistent
0101             flag = KNotification::Persistent;
0102         }
0103 
0104         m_active = true;
0105         KNotification *notify = new KNotification(m_name, 0, flag);
0106         notify->setComponentName("notificationhelper");
0107         notify->setPixmap(QIcon::fromTheme(icon).pixmap(NOTIFICATION_ICON_SIZE));
0108         notify->setText(text);
0109 
0110         // Tray icon not in use to handle actions
0111         notify->setActions(actions);
0112         connect(notify, SIGNAL(action1Activated()), this, SLOT(run()));
0113         connect(notify, SIGNAL(action2Activated()), this, SLOT(ignore()));
0114         connect(notify, SIGNAL(action3Activated()), this, SLOT(hide()));
0115         connect(notify, SIGNAL(closed()), this, SLOT(notifyClosed()));
0116 
0117         notify->sendEvent();
0118     }
0119 
0120     if (m_useTrayIcon && !m_notifierItem) { // Only create item when there is none.
0121         m_notifierItem = new KStatusNotifierItem(this);
0122         m_notifierItem->setIconByName(icon);
0123         m_notifierItem->setToolTipIconByName(icon);
0124         m_notifierItem->setToolTipTitle(i18n("System Notification Helper"));
0125         m_notifierItem->setToolTipSubTitle(text);
0126         m_notifierItem->setStatus(KStatusNotifierItem::Active);
0127         m_notifierItem->setCategory(KStatusNotifierItem::SystemServices);
0128         m_notifierItem->setStandardActionsEnabled(false);
0129 
0130         QMenu *contextMenu = new QMenu(0);
0131         // FIXME: addtitle does a whole pile of madness, I am not sure that should
0132         //        be reused *at all* as the lack of frameworks continuity will
0133         //        make for shitty UX
0134 //         contextMenu->addTitle(QIcon::fromTheme("applications-system"), i18n("System Notification Helper"));
0135 
0136         QAction *runAction = contextMenu->addAction(actions.at(0));
0137         // FIXME: DBusmenu doesn't support pixmap icons yet. Change function to take QIcon::fromTheme
0138         runAction->setIcon(QIcon::fromTheme(icon));
0139         connect(runAction, SIGNAL(triggered()), this, SLOT(run()));
0140         contextMenu->addAction(runAction);
0141 
0142         QAction *ignoreForeverAction = contextMenu->addAction(actions.at(2));
0143         connect(ignoreForeverAction, SIGNAL(triggered()), this, SLOT(hide()));
0144         contextMenu->addAction(ignoreForeverAction);
0145 
0146         contextMenu->addSeparator();
0147 
0148         QAction *hideAction = contextMenu->addAction(i18n("Hide"));
0149         hideAction->setIcon(QIcon::fromTheme("application-exit"));
0150         connect(hideAction, SIGNAL(triggered()), this, SLOT(ignore()));
0151         contextMenu->addAction(hideAction);
0152 
0153         m_notifierItem->setContextMenu(contextMenu);
0154         m_notifierItem->setAssociatedWidget(NULL);
0155 
0156         connect(m_notifierItem, SIGNAL(activateRequested(bool, const QPoint &)), this, SLOT(run()));
0157     }
0158 
0159     // Ask the KSNI to show a notification whenver show() is called.
0160     if (m_useTrayIcon && m_notifierItem) {
0161         m_notifierItem->showMessage(i18nc("notification title", "System Notification Helper"),
0162                                     text, icon);
0163     }
0164 }
0165 
0166 void Event::run()
0167 {
0168     delete m_notifierItem;
0169     m_notifierItem = 0;
0170     notifyClosed();
0171 }
0172 
0173 void Event::ignore()
0174 {
0175     m_notifierItem->deleteLater();
0176     m_notifierItem = 0;
0177     notifyClosed();
0178 }
0179 
0180 void Event::hide()
0181 {
0182     notifyClosed();
0183     writeHiddenConfig(true);
0184     m_hidden = true;
0185 }
0186 
0187 void Event::notifyClosed()
0188 {
0189     m_active = false;
0190 }
0191 
0192 void Event::reloadConfig()
0193 {
0194     m_hidden = readHiddenConfig();
0195 }