File indexing completed on 2024-04-28 04:44:14
0001 /* 0002 SnoreNotify is a Notification Framework based on Qt 0003 Copyright (C) 2013-2015 Hannah von Reth <vonreth@kde.org> 0004 0005 SnoreNotify is free software: you can redistribute it and/or modify 0006 it under the terms of the GNU Lesser General Public License as published by 0007 the Free Software Foundation, either version 3 of the License, or 0008 (at your option) any later version. 0009 0010 SnoreNotify is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 GNU Lesser General Public License for more details. 0014 0015 You should have received a copy of the GNU Lesser General Public License 0016 along with SnoreNotify. If not, see <http://www.gnu.org/licenses/>. 0017 */ 0018 0019 #include "snore.h" 0020 #include "snore_p.h" 0021 #include "snoreconstants.h" 0022 #include "lambdahint.h" 0023 #include "notification/notification.h" 0024 #include "notification/notification_p.h" 0025 #include "plugins/plugincontainer.h" 0026 #include "plugins/plugins.h" 0027 #include "plugins/snorebackend.h" 0028 #include "plugins/snorefrontend.h" 0029 0030 #include "version.h" 0031 0032 #include <QGuiApplication> 0033 #include <QSettings> 0034 #include <QThread> 0035 0036 using namespace Snore; 0037 0038 SnoreCore::SnoreCore(QObject *parent): 0039 QObject(parent) 0040 { 0041 if (QThread::currentThread() != parent->thread()) { 0042 moveToThread(parent->thread()); 0043 } 0044 d_ptr = new SnoreCorePrivate(); 0045 Q_D(SnoreCore); 0046 d->q_ptr = this; 0047 } 0048 0049 SnoreCore &SnoreCore::instance() 0050 { 0051 static SnoreCore *instance = nullptr; 0052 if (!instance) { 0053 qRegisterMetaType<Application>(); 0054 qRegisterMetaType<LambdaHint>(); 0055 qRegisterMetaType<Notification>(); 0056 qRegisterMetaType<SnorePlugin::PluginTypes>(); 0057 qRegisterMetaTypeStreamOperators<SnorePlugin::PluginTypes>(); 0058 instance = new SnoreCore(qApp); 0059 SnoreCorePrivate::instance()->init(); 0060 } 0061 return *instance; 0062 } 0063 0064 SnoreCore::~SnoreCore() 0065 { 0066 Q_D(SnoreCore); 0067 d->deleteLater(); 0068 } 0069 0070 void SnoreCore::loadPlugins(SnorePlugin::PluginTypes types) 0071 { 0072 if (QThread::currentThread() != thread()) { 0073 qCDebug(SNORE) << "Delayed Plugin loading." << QThread::currentThread() << thread(); 0074 QMetaObject::invokeMethod(this, "loadPlugins", Qt::BlockingQueuedConnection, Q_ARG(Snore::SnorePlugin::PluginTypes, types)); 0075 return; 0076 } 0077 Q_D(SnoreCore); 0078 setSettingsValue(Constants::SettingsKeys::PluginTypes, QVariant::fromValue(types)); 0079 qCDebug(SNORE) << "Loading plugin types:" << types; 0080 foreach(const SnorePlugin::PluginTypes type, SnorePlugin::types()) { 0081 if (type != SnorePlugin::All && types & type) { 0082 foreach(PluginContainer * info, PluginContainer::pluginCache(type).values()) { 0083 SnorePlugin *plugin = info->load(); 0084 if (!plugin) { 0085 continue; 0086 } 0087 0088 switch (info->type()) { 0089 case SnorePlugin::Backend: 0090 break; 0091 case SnorePlugin::SecondaryBackend: 0092 case SnorePlugin::Frontend: 0093 case SnorePlugin::Plugin: 0094 case SnorePlugin::Settings: 0095 plugin->setEnabled(plugin->settingsValue(Constants::SettingsKeys::Enabled).toBool()); 0096 break; 0097 default: 0098 qCWarning(SNORE) << "Plugin Cache corrupted\n" << info->file() << info->type(); 0099 continue; 0100 } 0101 0102 qCDebug(SNORE) << info->name() << "is a" << info->type(); 0103 d->m_pluginNames[info->type()].append(info->name()); 0104 auto key = qMakePair(type, info->name()); 0105 Q_ASSERT_X(!d->m_plugins.contains(key), Q_FUNC_INFO, "Multiple plugins of the same type with the same name."); 0106 d->m_plugins.insert(key, plugin); 0107 } 0108 if (d->m_pluginNames.contains(type)) { 0109 qSort(d->m_pluginNames[type]); 0110 } 0111 } 0112 } 0113 d->slotInitPrimaryNotificationBackend(); 0114 qCDebug(SNORE) << "Loaded Plugins:" << d->m_pluginNames; 0115 } 0116 0117 void SnoreCore::broadcastNotification(Notification notification) 0118 { 0119 Q_D(SnoreCore); 0120 if (d->m_activeNotifications.size() >= d->maxNumberOfActiveNotifications()) { 0121 qCDebug(SNORE) << "queue size:" << d->m_notificationQue.size() << "active size:" << d->m_activeNotifications.size(); 0122 d->m_notificationQue.append(notification); 0123 return; 0124 } 0125 Q_ASSERT_X(!notification.data()->isBroadcasted(), Q_FUNC_INFO, "Notification was already broadcasted."); 0126 qCDebug(SNORE) << "Broadcasting" << notification << "timeout:" << notification.timeout(); 0127 if (d->m_notificationBackend != nullptr) { 0128 if (notification.isUpdate() && !d->m_notificationBackend->canUpdateNotification()) { 0129 requestCloseNotification(notification.old(), Notification::Replaced); 0130 } 0131 } 0132 notification.data()->setBroadcasted(); 0133 notification.addActiveIn(this); 0134 if (!d->m_notificationBackend) { 0135 d->startNotificationTimeoutTimer(notification); 0136 } 0137 emit d->notify(notification); 0138 } 0139 0140 void SnoreCore::registerApplication(const Application &application) 0141 { 0142 Q_D(SnoreCore); 0143 Q_ASSERT_X(!d->m_applications.contains(application.key()), Q_FUNC_INFO, 0144 "Applications mus be registered only once."); 0145 qCDebug(SNORE) << "Registering Application:" << application; 0146 d->m_applications.insert(application.key(), application); 0147 emit d->applicationRegistered(application); 0148 } 0149 0150 void SnoreCore::deregisterApplication(const Application &application) 0151 { 0152 Q_D(SnoreCore); 0153 emit d->applicationDeregistered(application); 0154 d->m_applications.take(application.key()); 0155 } 0156 0157 const QHash<QString, Application> &SnoreCore::aplications() const 0158 { 0159 Q_D(const SnoreCore); 0160 return d->m_applications; 0161 } 0162 0163 const QStringList SnoreCore::pluginNames(SnorePlugin::PluginTypes type) const 0164 { 0165 Q_D(const SnoreCore); 0166 QStringList out; 0167 for (auto t : SnorePlugin::types()) { 0168 if (t & type) { 0169 out.append(d->m_pluginNames.value(t)); 0170 } 0171 } 0172 return out; 0173 } 0174 0175 const QString SnoreCore::primaryNotificationBackend() const 0176 { 0177 Q_D(const SnoreCore); 0178 if (d->m_notificationBackend.isNull()) { 0179 return QString::null; 0180 } 0181 return d->m_notificationBackend->name(); 0182 } 0183 0184 bool SnoreCore::setPrimaryNotificationBackend(const QString &backend) 0185 { 0186 Q_D(SnoreCore); 0187 return d->setBackendIfAvailible(backend); 0188 } 0189 0190 void SnoreCore::requestCloseNotification(Notification n, Notification::CloseReasons r) 0191 { 0192 Q_D(SnoreCore); 0193 bool wasQued = d->m_notificationQue.removeOne(n); 0194 if (wasQued) { 0195 qCDebug(SNORE) << n << " was qued."; 0196 } 0197 if (!wasQued && d->m_notificationBackend) { 0198 d->m_notificationBackend->requestCloseNotification(n, r); 0199 } else { 0200 if (n.isValid()) { 0201 n.data()->setCloseReason(r); 0202 emit notificationClosed(n); 0203 } 0204 } 0205 } 0206 0207 void SnoreCore::setDefaultApplication(const Application app) 0208 { 0209 Q_D(SnoreCore); 0210 d->m_defaultApp = app; 0211 } 0212 0213 QVariant SnoreCore::settingsValue(const SettingsKey &key) const 0214 { 0215 Q_D(const SnoreCore); 0216 QString nk = d->normalizeSettingsKey(key.key, key.type); 0217 if (key.type == LocalSetting && !d->m_settings->contains(nk)) { 0218 nk = d->normalizeSettingsKey(key.key + QStringLiteral("-SnoreDefault"), key.type); 0219 } 0220 return d->m_settings->value(nk); 0221 } 0222 0223 void SnoreCore::setSettingsValue(const SettingsKey &key, const QVariant &value) 0224 { 0225 Q_D(SnoreCore); 0226 d->m_settings->setValue(d->normalizeSettingsKey(key.key, key.type), value); 0227 } 0228 0229 void SnoreCore::setDefaultSettingsValue(const SettingsKey &key, const QVariant &value) 0230 { 0231 Q_D(SnoreCore); 0232 QString nk = d->normalizeSettingsKey(key.key, key.type); 0233 if (!d->m_settings->contains(nk)) { 0234 qCDebug(SNORE) << "Set default value" << nk << value; 0235 d->m_settings->setValue(nk, value); 0236 } 0237 } 0238 0239 Notification SnoreCore::getActiveNotificationByID(uint id) const 0240 { 0241 Q_D(const SnoreCore); 0242 return d->m_activeNotifications.value(id); 0243 } 0244 0245 void SnoreCore::displayExampleNotification() 0246 { 0247 Application app = SnoreCorePrivate::instance()->defaultApplication(); 0248 QString text = QLatin1String("<i>") + tr("This is %1").arg(app.name()) + QLatin1String("</i><br>" 0249 "<b>") + tr("Everything is awesome!") + QLatin1String("</b><br>"); 0250 if (!app.constHints().value("use-markup").toBool()) { 0251 text = Utils::normalizeMarkup(text, Utils::NoMarkup); 0252 } 0253 Notification noti(app, app.defaultAlert(), tr("Hello There!"), text, app.icon()); 0254 noti.addAction(Action(1, tr("Awesome Action!"))); 0255 broadcastNotification(noti); 0256 }