diff --git a/src/core/interface.cpp b/src/core/interface.cpp index 19c694d..faa8e9e 100644 --- a/src/core/interface.cpp +++ b/src/core/interface.cpp @@ -17,6 +17,8 @@ #include "interface.h" #include "snoreserver.h" +#include + SnorePlugin::SnorePlugin ( QString name,SnoreServer *snore ) : _name ( name ), _snore ( snore ) @@ -42,6 +44,33 @@ const QString &SnorePlugin::name() const return _name; } +void SnorePlugin::startTimeout(uint id,int timeout){ + if(timeout==-1)//sticky + return; + if(timeouts.contains(id)){ + QTimer *t = timeouts.take(id); + t->stop(); + t->deleteLater(); + timeout_order.removeOne(id); + } + QTimer *timer= new QTimer(this); + timer->setInterval(timeout*1000); + timer->setSingleShot(true); + timeouts.insert(id,timer); + timeout_order.append(id); + connect(timer,SIGNAL(timeout()),this,SLOT(notificationTimedOut())); + timer->start(); +} + +void SnorePlugin::notificationTimedOut(){ + uint id = timeout_order.takeFirst(); + timeouts.remove(id); + if(activeNotifications.contains(id)){ + Notification n = activeNotifications.take(id); + snore()->closeNotification(n,NotificationEnums::CloseReasons::TIMED_OUT); + } +} + Notification_Backend::Notification_Backend ( QString name, SnoreServer *snore ) : SnorePlugin ( name,snore ) { diff --git a/src/core/interface.h b/src/core/interface.h index f2259b4..fc1d1f7 100644 --- a/src/core/interface.h +++ b/src/core/interface.h @@ -29,10 +29,19 @@ public: virtual void setSnore ( class SnoreServer* snore ); virtual class SnoreServer* snore(); const QString &name() const; + +protected: + QHash activeNotifications; + void startTimeout(uint id,int timeout); +private slots: + void notificationTimedOut(); + private: SnorePlugin() {} QString _name; class SnoreServer *_snore; + QHash timeouts; + QList timeout_order; }; @@ -49,8 +58,7 @@ public: virtual ~Notification_Backend(); virtual bool isPrimaryNotificationBackend() =0; -protected: - QHash activeNotifications; + public slots: virtual void registerApplication ( class Application *application ) =0; @@ -70,11 +78,10 @@ class SNORE_EXPORT Notification_Frontend:public SnorePlugin public: Notification_Frontend ( QString name,class SnoreServer *snore=0 ); virtual ~Notification_Frontend(); + +public slots: virtual void actionInvoked (Notification notification )=0; virtual void notificationClosed ( Notification notification )=0; - -protected: - QHash activeNotifications; }; diff --git a/src/core/notification/notification.cpp b/src/core/notification/notification.cpp index 2ed0bc3..8be9e81 100644 --- a/src/core/notification/notification.cpp +++ b/src/core/notification/notification.cpp @@ -29,16 +29,16 @@ static int metaid = qRegisterMetaType(); class Notification::NotificationData { public: - NotificationData ( uint id=0 ): - _id ( id ), + NotificationData ( uint id=0 ): + _id ( id ), _timeout ( 10 ), _source ( NULL ), _closeReason(NotificationEnums::CloseReasons::NONE), _priority(NotificationEnums::Prioritys::NORMAL) - {} + {} - NotificationData ( const QString &application,const QString &alert,const QString &title,const QString &text,const SnoreIcon &icon,int timeout,uint id,NotificationEnums::Prioritys::prioritys priority ): - _id ( id ), + NotificationData ( const QString &application,const QString &alert,const QString &title,const QString &text,const SnoreIcon &icon,int timeout,uint id,NotificationEnums::Prioritys::prioritys priority ): + _id ( id ), _timeout ( timeout ), _source ( NULL), _application ( application ), @@ -48,26 +48,26 @@ public: _icon ( icon ), _priority(priority), _closeReason(NotificationEnums::CloseReasons::NONE) - {} + {} - ~NotificationData(){ - //delete _actionInvoked; - } + ~NotificationData(){ + //delete _actionInvoked; + } - uint _id; - int _timeout; - Notification::Action *_actionInvoked; - Notification_Frontend *_source; - QString _application; - QString _alert; - QString _title; - QString _text; - SnoreIcon _icon; - NotificationEnums::Prioritys::prioritys _priority; - NotificationEnums::CloseReasons::closeReasons _closeReason; - QMap _actions; - QVariantHash _hints; + uint _id; + int _timeout; + Notification::Action *_actionInvoked; + Notification_Frontend *_source; + QString _application; + QString _alert; + QString _title; + QString _text; + SnoreIcon _icon; + NotificationEnums::Prioritys::prioritys _priority; + NotificationEnums::CloseReasons::closeReasons _closeReason; + QMap _actions; + QVariantHash _hints; }; @@ -75,23 +75,23 @@ int Notification::DefaultTimeout = 10; QString Notification::toPlainText ( const QString &string ) { - if( Qt::mightBeRichText(string)) - return QTextDocumentFragment::fromHtml(string).toPlainText(); - return QString(string); + if( Qt::mightBeRichText(string)) + return QTextDocumentFragment::fromHtml(string).toPlainText(); + return QString(string); } Notification::Notification ( uint id ) { - d = QSharedPointer(new NotificationData(id)); + d = QSharedPointer(new NotificationData(id)); } Notification::Notification ( const QString &application, const QString &alert, const QString &title, const QString &text, const SnoreIcon &icon, int timeout, uint id, NotificationEnums::Prioritys::prioritys priority ) { - d = QSharedPointer(new NotificationData(application,alert,title,text,icon,timeout,id,priority)); + d = QSharedPointer(new NotificationData(application,alert,title,text,icon,timeout,id,priority)); } Notification::Notification ( const Notification &other ): -d(other.d) + d(other.d) { } @@ -106,124 +106,135 @@ Notification &Notification::operator=(const Notification& other) QString Notification::toString() const { - return QString ( "Title: "+d->_title+"\nText: "+d->_text ); + return QString ( "Title: "+d->_title+"\nText: "+d->_text ); } const uint &Notification::id() const { - return d->_id; + return d->_id; } void Notification::setId(const uint &id) { - qDebug()<<"setting notification id:"<_id = id; + qDebug()<<"setting notification id:"<_id = id; } const SnoreIcon &Notification::icon() const { - return d->_icon; + return d->_icon; } const int &Notification::timeout() const { - return d->_timeout; + return d->_timeout; } const Notification::Action *Notification::actionInvoked() const { - return d->_actionInvoked; + return d->_actionInvoked; } void Notification::setActionInvoked ( Action *action ) { - d->_actionInvoked = action; + d->_actionInvoked = action; } void Notification::setActionInvoked ( const int &id) { - d->_actionInvoked = d->_actions[id]; + d->_actionInvoked = d->_actions[id]; } void Notification::setSource(Notification_Frontend *source) const{ - d->_source = source; + d->_source = source; } Notification_Frontend *Notification::source() const { - return d->_source; + return d->_source; } const QString &Notification::application() const { - return d->_application; + return d->_application; } const QString &Notification::title() const { - return d->_title; + return d->_title; } const QString &Notification::text() const { - return d->_text; + return d->_text; } const QString &Notification::alert() const { - return d->_alert; + return d->_alert; } +const bool Notification::sticky() const +{ + return d->_timeout == -1; +} + +void Notification::setSticky() +{ + d->_timeout = -1; +} + + const NotificationEnums::Prioritys::prioritys &Notification::priority() const { - return d->_priority; + return d->_priority; } void Notification::addAction(Notification::Action *a) { - qDebug()<<"Added notification"<id<name; - d->_actions.insert(a->id,a); + qDebug()<<"Added notification"<id<name; + d->_actions.insert(a->id,a); } const QMap &Notification::actions() const { - return d->_actions; + return d->_actions; } const NotificationEnums::CloseReasons::closeReasons &Notification::closeReason(){ - return d->_closeReason; + return d->_closeReason; } void Notification::setCloseReason(const NotificationEnums::CloseReasons::closeReasons &r){ - d->_closeReason = r; + d->_closeReason = r; } const QVariant Notification::hint ( const QString &key ) const { - return d->_hints.value ( key ); + return d->_hints.value ( key ); } bool Notification::hintExists ( const QString &key ) { - return d->_hints.contains ( key ); + return d->_hints.contains ( key ); } void Notification::insertHint ( const QString &key, const QVariant &val ) { - d->_hints.insert ( key,val ); + d->_hints.insert ( key,val ); } QDataStream & operator<< ( QDataStream &stream, const Notification ¬i ) { - stream< &actions() const; - void addAction(Action *a); - const NotificationEnums::CloseReasons::closeReasons &closeReason(); - void setCloseReason(const NotificationEnums::CloseReasons::closeReasons &r); - const QVariant hint ( const QString &key ) const; + void setSticky(); + const bool sticky() const; + const NotificationEnums::Prioritys::prioritys &priority() const; + const QMap &actions() const; + void addAction(Action *a); + const NotificationEnums::CloseReasons::closeReasons &closeReason(); + void setCloseReason(const NotificationEnums::CloseReasons::closeReasons &r); + const QVariant hint ( const QString &key ) const; bool hintExists ( const QString &key ); void insertHint ( const QString &key,const QVariant &val ); private: - class NotificationData; - QSharedPointer d; + class NotificationData; + QSharedPointer d; }; - Q_DECLARE_METATYPE(Notification) +Q_DECLARE_METATYPE(Notification) QDataStream & operator<< ( QDataStream & stream, const Notification & noti ); QDataStream & operator<< ( QDataStream & stream, const Notification::Action & action); diff --git a/src/core/snoreserver.cpp b/src/core/snoreserver.cpp index 744b857..d944612 100644 --- a/src/core/snoreserver.cpp +++ b/src/core/snoreserver.cpp @@ -103,6 +103,11 @@ void SnoreServer::publicatePlugin ( SnorePlugin *plugin ) connect ( this,SIGNAL ( closeNotify ( Notification ) ),nb,SLOT ( closeNotification ( Notification) ) ); connect ( this,SIGNAL ( applicationInitialized ( Application* ) ),nb,SLOT ( registerApplication ( Application* ) ) ); connect ( this,SIGNAL ( applicationRemoved ( Application* ) ),nb,SLOT ( unregisterApplication ( Application* ) ) ); + }else{ + Notification_Frontend * nf=qobject_cast ( plugin ); + if(nf != NULL){ + connect ( this,SIGNAL ( closeNotify ( Notification ) ),nf,SLOT ( notificationClosed( Notification) ) ); + } } } @@ -121,11 +126,6 @@ void SnoreServer::closeNotification ( Notification notification,const Notificati { notification.setCloseReason(reason); emit closeNotify ( notification ); - Notification_Frontend *nf= notification.source(); - if ( nf != NULL ) - { - nf->notificationClosed ( notification ); - } } void SnoreServer::notificationActionInvoked ( Notification notification ) diff --git a/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.cpp b/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.cpp index a81c4a3..c630f3b 100644 --- a/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.cpp +++ b/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.cpp @@ -89,7 +89,7 @@ uint FreedesktopNotification_Frontend::Notify(const QString &app_name, uint repl - Notification noti(app_name,"DBus Alert",summary,body,icon,timeout==-1?Notification::DefaultTimeout:timeout/1000,replaces_id,priotity); + Notification noti(app_name,"DBus Alert",summary,body,icon,timeout==-1?-1:timeout/1000,replaces_id,priotity); noti.setSource(this); qDebug()<<"Actions"<broadcastNotification(noti); activeNotifications[noti.id()] = noti; - timeout_notifications.append(noti.id()); - QTimer::singleShot(timeout==-1?Notification::DefaultTimeout*1000:timeout,this,SLOT(timeoutClose())); + startTimeout(noti.id(),noti.timeout()); return noti.id(); } @@ -132,14 +131,4 @@ QString FreedesktopNotification_Frontend::GetServerInformation(QString& vendor, return "Snore"; } -void FreedesktopNotification_Frontend::timeoutClose(){ - uint id = timeout_notifications.takeFirst(); - if(activeNotifications.contains(id)){ - Notification noti = activeNotifications[id]; - noti.setCloseReason(NotificationEnums::CloseReasons::TIMED_OUT); - notificationClosed(noti); - } -} - - #include "freedesktopnotificationfrontend.moc" diff --git a/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.h b/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.h index d1873dc..95c41bd 100644 --- a/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.h +++ b/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.h @@ -34,15 +34,10 @@ public: QStringList GetCapabilities(); QString GetServerInformation(QString& vendor, QString& version, QString& specVersion); -private: - QList timeout_notifications; - signals: void NotificationClosed( uint id, uint reason ); void ActionInvoked( uint id, const QString& actionKey ); -private slots: - void timeoutClose(); }; diff --git a/src/plugins/growl/growl_backend.cpp b/src/plugins/growl/growl_backend.cpp index e3c7ff0..c58b99c 100644 --- a/src/plugins/growl/growl_backend.cpp +++ b/src/plugins/growl/growl_backend.cpp @@ -71,21 +71,19 @@ void Growl_Backend::unregisterApplication(Application *application){ int Growl_Backend::notify(Notification notification){ gntp *growl = _applications.value(notification.application()); if(growl == NULL) - return -1; - uint id = ++_id; - - //qDebug()<<"Notify Growl:"<notify(notification.alert().toUtf8().constData(),id, + growl->notify(notification.alert().toUtf8().constData(),_id, Notification::toPlainText(notification.title()).toUtf8().constData(), Notification::toPlainText(notification.text()).toUtf8().constData(), notification.icon().localUrl().isEmpty()?NULL:notification.icon().localUrl().toUtf8().constData(),NULL,"1"); - activeNotifications.insert(id,notification); + activeNotifications.insert(_id,notification); }catch(const std::exception& e){ qDebug()<<"Growl:"<GetVersion(); - _defautSnarlinetrface = new SnarlInterface(); + winIDWidget = new SnarlWidget(this); + SnarlInterface *snarlInterface = new SnarlInterface(); + _applications.insert("SnoreNotify",snarlInterface); + qDebug()<<"Initiating Snarl Backend, Snarl version: "<GetVersion(); + _defautSnarlinetrface = new SnarlInterface(); } Snarl_Backend::~Snarl_Backend() { - foreach(Application *a,this->snore()->aplications().values()){ - unregisterApplication(a); - } - delete _defautSnarlinetrface; + foreach(Application *a,this->snore()->aplications().values()){ + unregisterApplication(a); + } + delete _defautSnarlinetrface; } void Snarl_Backend::registerApplication(Application *application){ - SnarlInterface *snarlInterface = NULL; - if(_applications.contains(application->name())){ - snarlInterface = _applications.value(application->name()); - }else{ - snarlInterface = new SnarlInterface(); - _applications.insert(application->name(),snarlInterface); - } - qDebug()<<"Register with Snarl"<name(); - QString appName = application->name(); - appName = appName.replace(" ","_");//app sig must not contain spaces - snarlInterface->Register(appName.toUtf8().constData(), - application->name().toUtf8().constData(), - application->icon().localUrl().toUtf8().constData(), - 0,winIDWidget->winId(),SNORENOTIFIER_MESSAGE_ID); + SnarlInterface *snarlInterface = NULL; + if(_applications.contains(application->name())){ + snarlInterface = _applications.value(application->name()); + }else{ + snarlInterface = new SnarlInterface(); + _applications.insert(application->name(),snarlInterface); + } + qDebug()<<"Register with Snarl"<name(); + QString appName = application->name(); + appName = appName.replace(" ","_");//app sig must not contain spaces + snarlInterface->Register(appName.toUtf8().constData(), + application->name().toUtf8().constData(), + application->icon().localUrl().toUtf8().constData(), + 0,winIDWidget->winId(),SNORENOTIFIER_MESSAGE_ID); - foreach(Alert *alert,application->alerts()){ - snarlInterface->AddClass(application->name().toUtf8().constData(), - alert->name().toUtf8().constData(), - 0,0,alert->icon().localUrl().toUtf8().constData()); - } + foreach(Alert *alert,application->alerts()){ + snarlInterface->AddClass(application->name().toUtf8().constData(), + alert->name().toUtf8().constData(), + 0,0,alert->icon().localUrl().toUtf8().constData()); + } } void Snarl_Backend::unregisterApplication(Application *application){ - SnarlInterface *snarlInterface = _applications.take(application->name()); - if(snarlInterface == NULL) - return; - snarlInterface->Unregister(application->name().toUtf8().constData()); - delete snarlInterface; + SnarlInterface *snarlInterface = _applications.take(application->name()); + if(snarlInterface == NULL) + return; + snarlInterface->Unregister(application->name().toUtf8().constData()); + delete snarlInterface; } int Snarl_Backend::notify(Notification notification){ - SnarlInterface *snarlInterface = _applications.value(notification.application()); - qDebug()<<"Snarl using the notification instance of:"<Notify(notification.alert().toUtf8().constData(), - Notification::toPlainText(notification.title()).toUtf8().constData(), - Notification::toPlainText(notification.text()).toUtf8().constData(), - notification.timeout(), - notification.icon().isLocalFile()?notification.icon().localUrl().toUtf8().constData():0, - !notification.icon().isLocalFile()?notification.icon().imageData().toBase64().constData():0, - notification.priority()); - - foreach(const Notification::Action *a, notification.actions()){ - snarlInterface->AddAction(id,a->name.toUtf8().constData(),QString("@").append(QString::number(a->id)).toUtf8().constData()); - } - //add ack stuff - activeNotifications[id] = notification; - }else{ - //update message - snarlInterface->Update(notification.id(), - notification.alert().toUtf8().constData(), - Notification::toPlainText(notification.title()).toUtf8().constData(), - Notification::toPlainText(notification.text()).toUtf8().constData(), - notification.timeout(), - notification.icon().isLocalFile()?notification.icon().localUrl().toUtf8().constData():0, - !notification.icon().isLocalFile()?notification.icon().imageData().toBase64().constData():0, - notification.priority()); - } - return id; + qDebug()<<"Snarl is localfile"<Notify(notification.alert().toUtf8().constData(), + Notification::toPlainText(notification.title()).toUtf8().constData(), + Notification::toPlainText(notification.text()).toUtf8().constData(), + notification.timeout()+1,//+1 make a sticke snarl sticky and doesnt matter for the rest + notification.icon().isLocalFile()?notification.icon().localUrl().toUtf8().constData():0, + !notification.icon().isLocalFile()?notification.icon().imageData().toBase64().constData():0, + notification.priority()); + + foreach(const Notification::Action *a, notification.actions()){ + snarlInterface->AddAction(id,a->name.toUtf8().constData(),QString("@").append(QString::number(a->id)).toUtf8().constData()); + } + //add ack stuff + if(!_away) + activeNotifications[id] = notification; + }else{ + //update message + snarlInterface->Update(notification.id(), + notification.alert().toUtf8().constData(), + Notification::toPlainText(notification.title()).toUtf8().constData(), + Notification::toPlainText(notification.text()).toUtf8().constData(), + notification.timeout()+1, + notification.icon().isLocalFile()?notification.icon().localUrl().toUtf8().constData():0, + !notification.icon().isLocalFile()?notification.icon().imageData().toBase64().constData():0, + notification.priority()); + } + startTimeout(id,notification.timeout()); + return id; } void Snarl_Backend::closeNotification(Notification notification){ - _defautSnarlinetrface->Hide(notification.id()); - activeNotifications.remove(notification.id()); + _defautSnarlinetrface->Hide(notification.id()); + activeNotifications.remove(notification.id()); } bool Snarl_Backend::isPrimaryNotificationBackend(){ - return true; + return true; } SnarlWidget::SnarlWidget(Snarl_Backend * snarl): -_snarl(snarl) + _snarl(snarl) { - SNARL_GLOBAL_MESSAGE = SnarlInterface::Broadcast(); + SNARL_GLOBAL_MESSAGE = SnarlInterface::Broadcast(); } bool SnarlWidget::winEvent(MSG * msg, long * result){ - if(msg->message == SNARL_GLOBAL_MESSAGE){ - int action = msg->wParam; - if(action == SnarlEnums::SnarlLaunched){ - foreach(Application *a,_snarl->snore()->aplications()){ - _snarl->registerApplication(a); - } - } + if(msg->message == SNARL_GLOBAL_MESSAGE){ + int action = msg->wParam; + if(action == SnarlEnums::SnarlLaunched){ + foreach(Application *a,_snarl->snore()->aplications()){ + _snarl->registerApplication(a); + } + } - }else if(msg->message == SNORENOTIFIER_MESSAGE_ID){ - int action = msg->wParam & 0xffff; - int data = (msg->wParam & 0xffffffff) >> 16; - uint notificationID = msg->lParam; - qDebug()<<_snarl->activeNotifications.keys(); - Notification notification(_snarl->activeNotifications[notificationID]); - qDebug()<<"recived a Snarl callback id:"<snore()->notificationActionInvoked(notification);"; - _snarl->snore()->notificationActionInvoked(notification); - break; - case SnarlEnums::CallbackClosed: - reason = NotificationEnums::CloseReasons::DISMISSED; - break; - case SnarlEnums::CallbackTimedOut: - reason = NotificationEnums::CloseReasons::TIMED_OUT; - break; - default: - qDebug()<<"Unknown snarl action found!!"; - return false; - } - _snarl->snore()->closeNotification(notification,reason); - return true; - } - return false; + }else if(msg->message == SNORENOTIFIER_MESSAGE_ID){ + int action = msg->wParam & 0xffff; + int data = (msg->wParam & 0xffffffff) >> 16; + uint notificationID = msg->lParam; + qDebug()<<"_snarl->activeNotifications"<<_snarl->activeNotifications.keys(); + Notification notification(_snarl->activeNotifications[notificationID]); + qDebug()<<"recived a Snarl callback id:"<snore()->notificationActionInvoked(notification); + break; + case SnarlEnums::CallbackClosed: + reason = NotificationEnums::CloseReasons::DISMISSED; + break; + case SnarlEnums::CallbackTimedOut: + reason = NotificationEnums::CloseReasons::TIMED_OUT; + break; + //away stuff + case SnarlEnums::SnarlUserAway: + qDebug()<<"Snalr user has gone away"; + _snarl->_away = true; + break; + case SnarlEnums::SnarlUserBack: + qDebug()<<"Snalr user has returned"; + _snarl->activeNotifications.clear(); + _snarl->_away = false; + break; + default: + qDebug()<<"Unknown snarl action found!!"; + return false; + } + _snarl->snore()->closeNotification(notification,reason); + return true; + } + return false; } diff --git a/src/plugins/snarl/snarl_backend.h b/src/plugins/snarl/snarl_backend.h index 59a9574..cae9271 100644 --- a/src/plugins/snarl/snarl_backend.h +++ b/src/plugins/snarl/snarl_backend.h @@ -27,17 +27,17 @@ class Snarl_Backend:public Notification_Backend { Q_OBJECT Q_INTERFACES(Notification_Backend) - friend class SnarlWidget; + friend class SnarlWidget; public: Snarl_Backend(class SnoreServer *snore=0); ~Snarl_Backend(); bool isPrimaryNotificationBackend(); private: - SnarlWidget* winIDWidget; - + SnarlWidget* winIDWidget; QHash _applications; Snarl::V42::SnarlInterface* _defautSnarlinetrface; + bool _away; public slots: void registerApplication(Application *application); @@ -49,14 +49,14 @@ public slots: class SnarlWidget:public QWidget { - Q_OBJECT + Q_OBJECT public: - SnarlWidget(Snarl_Backend* snarl); - bool winEvent( MSG * message, long * result ); + SnarlWidget(Snarl_Backend* snarl); + bool winEvent( MSG * message, long * result ); private: - uint SNARL_GLOBAL_MESSAGE; - Snarl_Backend* _snarl; + uint SNARL_GLOBAL_MESSAGE; + Snarl_Backend* _snarl; };