diff --git a/interfaces/org.freedesktop.Akonadi.NotificationManager.xml b/interfaces/org.freedesktop.Akonadi.NotificationManager.xml
index 84855b35..183befe1 100644
--- a/interfaces/org.freedesktop.Akonadi.NotificationManager.xml
+++ b/interfaces/org.freedesktop.Akonadi.NotificationManager.xml
@@ -1,34 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/server/src/notificationmanager.cpp b/server/src/notificationmanager.cpp
index ba222bbf..f876ed73 100644
--- a/server/src/notificationmanager.cpp
+++ b/server/src/notificationmanager.cpp
@@ -1,234 +1,262 @@
/*
Copyright (c) 2006 - 2007 Volker Krause
Copyright (c) 2010 Michael Jansen
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "notificationmanager.h"
#include
#include "notificationmanageradaptor.h"
#include "notificationsource.h"
#include "tracer.h"
#include "storage/datastore.h"
#include "clientcapabilityaggregator.h"
#include
#include
#include
#include
#include
using namespace Akonadi;
using namespace Akonadi::Server;
NotificationManager *NotificationManager::mSelf = 0;
NotificationManager::NotificationManager()
- : QObject( 0 )
+ : QObject( 0 ),
+ mNotificationCounter( 0 )
{
NotificationMessage::registerDBusTypes();
NotificationMessageV2::registerDBusTypes();
NotificationMessageV3::registerDBusTypes();
new NotificationManagerAdaptor( this );
QDBusConnection::sessionBus().registerObject( QLatin1String( "/notifications" ),
this, QDBusConnection::ExportAdaptors );
QDBusConnection::sessionBus().registerObject( QLatin1String( "/notifications/debug" ),
this, QDBusConnection::ExportScriptableSlots );
const QString serverConfigFile = AkStandardDirs::serverConfigFile( XdgBaseDirs::ReadWrite );
QSettings settings( serverConfigFile, QSettings::IniFormat );
mTimer.setInterval( settings.value( QLatin1String( "NotificationManager/Interval" ), 50 ).toInt() );
mTimer.setSingleShot( true );
connect( &mTimer, SIGNAL(timeout()), SLOT(emitPendingNotifications()) );
}
NotificationManager::~NotificationManager()
{
}
NotificationManager *NotificationManager::self()
{
if ( !mSelf ) {
mSelf = new NotificationManager();
}
return mSelf;
}
void NotificationManager::connectNotificationCollector( NotificationCollector *collector )
{
connect( collector, SIGNAL(notify(Akonadi::NotificationMessageV3::List)),
SLOT(slotNotify(Akonadi::NotificationMessageV3::List)) );
}
void NotificationManager::slotNotify( const Akonadi::NotificationMessageV3::List &msgs )
{
//akDebug() << Q_FUNC_INFO << "Appending" << msgs.count() << "notifications to current list of " << mNotifications.count() << "notifications";
+ mNotificationCounter += msgs.count();
+
Q_FOREACH ( const NotificationMessageV3 &msg, msgs )
NotificationMessageV3::appendAndCompress( mNotifications, msg );
//akDebug() << Q_FUNC_INFO << "We have" << mNotifications.count() << "notifications queued in total after appendAndCompress()";
if ( !mTimer.isActive() ) {
mTimer.start();
}
}
void NotificationManager::emitPendingNotifications()
{
if ( mNotifications.isEmpty() ) {
return;
}
NotificationMessage::List legacyNotifications;
Q_FOREACH ( const NotificationMessageV3 ¬ification, mNotifications ) {
Tracer::self()->signal( "NotificationManager::notify", notification.toString() );
if ( ClientCapabilityAggregator::minimumNotificationMessageVersion() < 2 ) {
const NotificationMessage::List tmp = notification.toNotificationV1().toList();
Q_FOREACH ( const NotificationMessage &legacyNotification, tmp ) {
bool appended = false;
NotificationMessage::appendAndCompress( legacyNotifications, legacyNotification, &appended );
if ( !appended ) {
legacyNotifications << legacyNotification;
}
}
}
}
if ( !legacyNotifications.isEmpty() ) {
Q_FOREACH ( NotificationSource *src, mNotificationSources ) {
src->emitNotification( legacyNotifications );
}
}
NotificationMessageV2::List v2List;
if ( ClientCapabilityAggregator::maximumNotificationMessageVersion() == 2 ) {
v2List = NotificationMessageV3::toV2List( mNotifications );
}
if ( ClientCapabilityAggregator::maximumNotificationMessageVersion() > 1 ) {
Q_FOREACH ( NotificationSource *source, mNotificationSources ) {
if ( !source->isServerSideMonitorEnabled() ) {
if ( ClientCapabilityAggregator::maximumNotificationMessageVersion() == 2 ) {
source->emitNotification( v2List );
} else {
source->emitNotification( mNotifications );
}
continue;
}
NotificationMessageV3::List acceptedNotifications;
Q_FOREACH ( const NotificationMessageV3 ¬ification, mNotifications ) {
if ( source->acceptsNotification( notification ) ) {
acceptedNotifications << notification;
}
}
if ( !acceptedNotifications.isEmpty() ) {
if ( ClientCapabilityAggregator::maximumNotificationMessageVersion() == 2 ) {
source->emitNotification( NotificationMessageV3::toV2List( acceptedNotifications ) );
} else {
source->emitNotification( acceptedNotifications );
}
}
}
}
// backward compatibility with the old non-subcription interface
// FIXME: Can we drop this already?
if ( !legacyNotifications.isEmpty() ) {
Q_EMIT notify( legacyNotifications );
}
mNotifications.clear();
}
QDBusObjectPath NotificationManager::subscribeV2( const QString &identifier, bool serverSideMonitor )
{
akDebug() << Q_FUNC_INFO << this << identifier << serverSideMonitor;
return subscribeV3( identifier, serverSideMonitor, false );
}
QDBusObjectPath NotificationManager::subscribeV3( const QString &identifier, bool serverSideMonitor, bool exclusive )
{
akDebug() << Q_FUNC_INFO << this << identifier << serverSideMonitor << exclusive;
NotificationSource *source = mNotificationSources.value( identifier );
if ( source ) {
akDebug() << "Known subscriber" << identifier << "subscribes again";
source->addClientServiceName( message().service() );
} else {
source = new NotificationSource( identifier, message().service(), this );
}
registerSource( source );
source->setServerSideMonitorEnabled( serverSideMonitor );
source->setExclusive( exclusive );
// The path is /subscriber/escaped_identifier. We want to extract
// the escaped_identifier and emit it in subscribed() instead of the original
// identifier
const QStringList paths = source->dbusPath().path().split( QLatin1Char( '/' ), QString::SkipEmptyParts );
// FIXME KF5: Emit the QDBusObjectPath instead of the identifier
Q_EMIT subscribed( paths.at( 1 ) );
-
+ mDebugMessages.append(QDateTime::currentDateTime().toString() + QLatin1String(" SUBSCRIBE ") + identifier);
return source->dbusPath();
}
void NotificationManager::registerSource( NotificationSource *source )
{
mNotificationSources.insert( source->identifier(), source );
}
QDBusObjectPath NotificationManager::subscribe( const QString &identifier )
{
akDebug() << Q_FUNC_INFO << this << identifier;
return subscribeV2( identifier, false );
}
void NotificationManager::unsubscribe( const QString &identifier )
{
+ mDebugMessages.append(QDateTime::currentDateTime().toString() + QLatin1String(" UNSUBSCRIBE ") + identifier);
NotificationSource *source = mNotificationSources.value( identifier );
if ( source ) {
unregisterSource( source );
const QStringList paths = source->dbusPath().path().split( QLatin1Char( '/' ), QString::SkipEmptyParts );
source->deleteLater();
Q_EMIT unsubscribed( paths.at( 1 ) );
} else {
akDebug() << "Attempt to unsubscribe unknown subscriber" << identifier;
}
}
void NotificationManager::unregisterSource( NotificationSource *source )
{
mNotificationSources.remove( source->identifier() );
}
QStringList NotificationManager::subscribers() const
{
QStringList identifiers;
Q_FOREACH ( NotificationSource *source, mNotificationSources ) {
identifiers << source->identifier();
}
return identifiers;
}
+
+int NotificationManager::notificationCounter() const
+{
+ return mNotificationCounter;
+}
+
+int NotificationManager::notificationCount() const
+{
+ return mNotifications.size();
+}
+
+QStringList NotificationManager::listNotifications() const
+{
+ QStringList list;
+ Q_FOREACH ( const NotificationMessageV3 &n, mNotifications ) {
+ list << n.toString();
+ }
+ return list;
+}
+
+QStringList NotificationManager::debugMessages() const
+{
+ return mDebugMessages;
+}
diff --git a/server/src/notificationmanager.h b/server/src/notificationmanager.h
index 3143cb06..617e6861 100644
--- a/server/src/notificationmanager.h
+++ b/server/src/notificationmanager.h
@@ -1,130 +1,137 @@
/*
Copyright (c) 2006 - 2007 Volker Krause
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_NOTIFICATIONMANAGER_H
#define AKONADI_NOTIFICATIONMANAGER_H
#include "../libs/notificationmessage_p.h"
#include "../libs/notificationmessagev3_p.h"
#include "storage/entity.h"
#include
#include
#include
#include
class NotificationManagerTest;
namespace Akonadi {
namespace Server {
class NotificationCollector;
class NotificationSource;
/**
Notification manager D-Bus interface.
*/
class NotificationManager : public QObject, protected QDBusContext
{
Q_OBJECT
Q_CLASSINFO( "D-Bus Interface", "org.freedesktop.Akonadi.NotificationManager" )
public:
static NotificationManager *self();
virtual ~NotificationManager();
void connectNotificationCollector( NotificationCollector *collector );
public Q_SLOTS:
Q_SCRIPTABLE void emitPendingNotifications();
/**
* Subscribe to notifications emitted by this manager.
*
* @param identifier Identifier to use of our subscription.
* @return The path we got assigned. Contains identifier.
*/
Q_SCRIPTABLE QDBusObjectPath subscribe( const QString &identifier );
/**
* Subscribe to notifications emitted by this manager.
*
* @param identifier Identifier to use for our subscription.
* @param serverSideMonitor Whether client supports server-side monitoring
* @return The path we got assigned. Contains identifier.
*/
Q_SCRIPTABLE QDBusObjectPath subscribeV2( const QString &identifier, bool serverSideMonitor );
/**
* Subscribe to notifications emitted by this manager.
*
* @param identifier Identifier to use for our subscription.
* @param serverSideMonitor Whether client supports server-side monitoring
* @param exclusive Exclusive subscribers also receive notifications on referenced collections
* @return The path we got assigned. Contains identifier.
*/
Q_SCRIPTABLE QDBusObjectPath subscribeV3( const QString &identifier, bool serverSideMonitor, bool exclusive );
/**
* Unsubscribe from this manager.
*
* This method is for your inconvenience only. It's advisable to use the unsubscribe method
* provided by the NotificationSource.
*
* @param identifier The identifier used for subscription.
*/
Q_SCRIPTABLE void unsubscribe( const QString &identifier );
/**
* Returns identifiers of currently subscribed sources
*/
Q_SCRIPTABLE QStringList subscribers() const;
+ Q_SCRIPTABLE int notificationCounter() const;
+ Q_SCRIPTABLE int notificationCount() const;
+ Q_SCRIPTABLE QStringList debugMessages() const;
+ Q_SCRIPTABLE QStringList listNotifications() const;
+
Q_SIGNALS:
Q_SCRIPTABLE void notify( const Akonadi::NotificationMessage::List &msgs );
Q_SCRIPTABLE void subscribed( const QString &identifier );
Q_SCRIPTABLE void unsubscribed( const QString &identifier );
private Q_SLOTS:
void slotNotify( const Akonadi::NotificationMessageV3::List &msgs );
private:
NotificationManager();
private:
void registerSource( NotificationSource *source );
void unregisterSource( NotificationSource *source );
static NotificationManager *mSelf;
NotificationMessageV3::List mNotifications;
QTimer mTimer;
//! One message source for each subscribed process
QHash mNotificationSources;
+ QList mDebugMessages;
+ int mNotificationCounter;
friend class NotificationSource;
friend class ::NotificationManagerTest;
};
} // namespace Server
} // namespace Akonadi
#endif