diff options
Diffstat (limited to 'SwifTools/Notifier')
-rw-r--r-- | SwifTools/Notifier/GNTPNotifier.cpp | 88 | ||||
-rw-r--r-- | SwifTools/Notifier/GNTPNotifier.h | 46 | ||||
-rw-r--r-- | SwifTools/Notifier/GrowlNotifier.h | 54 | ||||
-rw-r--r-- | SwifTools/Notifier/GrowlNotifier.mm | 130 | ||||
-rw-r--r-- | SwifTools/Notifier/GrowlNotifierDelegate.h | 8 | ||||
-rw-r--r-- | SwifTools/Notifier/GrowlNotifierDelegate.mm | 8 | ||||
-rw-r--r-- | SwifTools/Notifier/LoggingNotifier.h | 32 | ||||
-rw-r--r-- | SwifTools/Notifier/NotificationCenterNotifier.h | 22 | ||||
-rw-r--r-- | SwifTools/Notifier/NotificationCenterNotifier.mm | 98 | ||||
-rw-r--r-- | SwifTools/Notifier/NotificationCenterNotifierDelegate.h | 2 | ||||
-rw-r--r-- | SwifTools/Notifier/NotificationCenterNotifierDelegate.mm | 6 | ||||
-rw-r--r-- | SwifTools/Notifier/Notifier.cpp | 40 | ||||
-rw-r--r-- | SwifTools/Notifier/Notifier.h | 70 | ||||
-rw-r--r-- | SwifTools/Notifier/NullNotifier.h | 14 | ||||
-rw-r--r-- | SwifTools/Notifier/SnarlNotifier.cpp | 74 | ||||
-rw-r--r-- | SwifTools/Notifier/SnarlNotifier.h | 48 | ||||
-rw-r--r-- | SwifTools/Notifier/TogglableNotifier.h | 100 | ||||
-rw-r--r-- | SwifTools/Notifier/Win32NotifierWindow.h | 12 |
18 files changed, 426 insertions, 426 deletions
diff --git a/SwifTools/Notifier/GNTPNotifier.cpp b/SwifTools/Notifier/GNTPNotifier.cpp index 01e8726..62203b4 100644 --- a/SwifTools/Notifier/GNTPNotifier.cpp +++ b/SwifTools/Notifier/GNTPNotifier.cpp @@ -21,67 +21,67 @@ namespace Swift { GNTPNotifier::GNTPNotifier(const std::string& name, const boost::filesystem::path& icon, ConnectionFactory* connectionFactory) : name(name), icon(icon), connectionFactory(connectionFactory), initialized(false), registered(false) { - // Registration message - std::ostringstream message; - message << "GNTP/1.0 REGISTER NONE\r\n"; - message << "Application-Name: " << name << "\r\n"; - message << "Application-Icon: file://" << pathToString(icon) << "\r\n"; - message << "Notifications-Count: " << getAllTypes().size() << "\r\n"; - std::vector<Notifier::Type> defaultTypes = getDefaultTypes(); - std::vector<Notifier::Type> allTypes = getAllTypes(); - foreach(Notifier::Type type, allTypes) { - message << "\r\n"; - message << "Notification-Name: " << typeToString(type) << "\r\n"; - message << "Notification-Enabled: " << (std::find(defaultTypes.begin(), defaultTypes.end(), type) == defaultTypes.end() ? "false" : "true") << "\r\n"; - } - message << "\r\n"; + // Registration message + std::ostringstream message; + message << "GNTP/1.0 REGISTER NONE\r\n"; + message << "Application-Name: " << name << "\r\n"; + message << "Application-Icon: file://" << pathToString(icon) << "\r\n"; + message << "Notifications-Count: " << getAllTypes().size() << "\r\n"; + std::vector<Notifier::Type> defaultTypes = getDefaultTypes(); + std::vector<Notifier::Type> allTypes = getAllTypes(); + foreach(Notifier::Type type, allTypes) { + message << "\r\n"; + message << "Notification-Name: " << typeToString(type) << "\r\n"; + message << "Notification-Enabled: " << (std::find(defaultTypes.begin(), defaultTypes.end(), type) == defaultTypes.end() ? "false" : "true") << "\r\n"; + } + message << "\r\n"; - send(message.str()); + send(message.str()); } GNTPNotifier::~GNTPNotifier() { } void GNTPNotifier::send(const std::string& message) { - if (currentConnection) { - return; - } - currentMessage = message; - currentConnection = connectionFactory->createConnection(); - currentConnection->onConnectFinished.connect(boost::bind(&GNTPNotifier::handleConnectFinished, this, _1)); - currentConnection->onDataRead.connect(boost::bind(&GNTPNotifier::handleDataRead, this, _1)); - currentConnection->connect(HostAddressPort(HostAddress("127.0.0.1"), 23053)); + if (currentConnection) { + return; + } + currentMessage = message; + currentConnection = connectionFactory->createConnection(); + currentConnection->onConnectFinished.connect(boost::bind(&GNTPNotifier::handleConnectFinished, this, _1)); + currentConnection->onDataRead.connect(boost::bind(&GNTPNotifier::handleDataRead, this, _1)); + currentConnection->connect(HostAddressPort(HostAddress("127.0.0.1"), 23053)); } void GNTPNotifier::showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()>) { - if (registered) { - std::ostringstream message; - message << "GNTP/1.0 NOTIFY NONE\r\n"; - message << "Application-Name: " << name << "\r\n"; - message << "Notification-Name: " << typeToString(type) << "\r\n"; - message << "Notification-Title: " << subject << "\r\n"; - message << "Notification-Text: " << description << "\r\n"; - message << "Notification-Icon: " << pathToString(picture) << "\r\n"; - message << "\r\n"; - send(message.str()); - } + if (registered) { + std::ostringstream message; + message << "GNTP/1.0 NOTIFY NONE\r\n"; + message << "Application-Name: " << name << "\r\n"; + message << "Notification-Name: " << typeToString(type) << "\r\n"; + message << "Notification-Title: " << subject << "\r\n"; + message << "Notification-Text: " << description << "\r\n"; + message << "Notification-Icon: " << pathToString(picture) << "\r\n"; + message << "\r\n"; + send(message.str()); + } } void GNTPNotifier::handleConnectFinished(bool error) { - if (!initialized) { - initialized = true; - registered = !error; - } + if (!initialized) { + initialized = true; + registered = !error; + } - if (!error) { - currentConnection->write(currentMessage.c_str()); - } + if (!error) { + currentConnection->write(currentMessage.c_str()); + } } void GNTPNotifier::handleDataRead(const ByteArray&) { - currentConnection->onDataRead.disconnect(boost::bind(&GNTPNotifier::handleDataRead, this, _1)); - currentConnection->onConnectFinished.disconnect(boost::bind(&GNTPNotifier::handleConnectFinished, this, _1)); - currentConnection.reset(); + currentConnection->onDataRead.disconnect(boost::bind(&GNTPNotifier::handleDataRead, this, _1)); + currentConnection->onConnectFinished.disconnect(boost::bind(&GNTPNotifier::handleConnectFinished, this, _1)); + currentConnection.reset(); } } diff --git a/SwifTools/Notifier/GNTPNotifier.h b/SwifTools/Notifier/GNTPNotifier.h index 92ff5a3..44811e7 100644 --- a/SwifTools/Notifier/GNTPNotifier.h +++ b/SwifTools/Notifier/GNTPNotifier.h @@ -13,27 +13,27 @@ #include <SwifTools/Notifier/Notifier.h> namespace Swift { - class ConnectionFactory; - - class GNTPNotifier : public Notifier { - public: - GNTPNotifier(const std::string& name, const boost::filesystem::path& icon, ConnectionFactory* connectionFactory); - ~GNTPNotifier(); - - virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback); - - private: - void handleConnectFinished(bool error); - void handleDataRead(const ByteArray& data); - void send(const std::string& message); - - private: - std::string name; - boost::filesystem::path icon; - ConnectionFactory* connectionFactory; - bool initialized; - bool registered; - std::string currentMessage; - Connection::ref currentConnection; - }; + class ConnectionFactory; + + class GNTPNotifier : public Notifier { + public: + GNTPNotifier(const std::string& name, const boost::filesystem::path& icon, ConnectionFactory* connectionFactory); + ~GNTPNotifier(); + + virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback); + + private: + void handleConnectFinished(bool error); + void handleDataRead(const ByteArray& data); + void send(const std::string& message); + + private: + std::string name; + boost::filesystem::path icon; + ConnectionFactory* connectionFactory; + bool initialized; + bool registered; + std::string currentMessage; + Connection::ref currentConnection; + }; } diff --git a/SwifTools/Notifier/GrowlNotifier.h b/SwifTools/Notifier/GrowlNotifier.h index 9c90471..b4c4eba 100644 --- a/SwifTools/Notifier/GrowlNotifier.h +++ b/SwifTools/Notifier/GrowlNotifier.h @@ -11,31 +11,31 @@ #include <SwifTools/Notifier/Notifier.h> namespace Swift { - /** - * Preconditions for using growlnotifier: - * - Must be part a bundle. - * - The Carbon/Cocoa application loop must be running (e.g. through QApplication) - * such that notifications are coming through. - */ - class GrowlNotifier : public Notifier { - public: - GrowlNotifier(const std::string& name); - ~GrowlNotifier(); - - virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback); - virtual bool isExternallyConfigured() const; - - // Called by the delegate. Don't call. - void handleNotificationClicked(void* data); - void handleNotificationTimedOut(void* data); - - virtual void purgeCallbacks(); - - private: - void clearPendingNotifications(); - - private: - class Private; - boost::shared_ptr<Private> p; - }; + /** + * Preconditions for using growlnotifier: + * - Must be part a bundle. + * - The Carbon/Cocoa application loop must be running (e.g. through QApplication) + * such that notifications are coming through. + */ + class GrowlNotifier : public Notifier { + public: + GrowlNotifier(const std::string& name); + ~GrowlNotifier(); + + virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback); + virtual bool isExternallyConfigured() const; + + // Called by the delegate. Don't call. + void handleNotificationClicked(void* data); + void handleNotificationTimedOut(void* data); + + virtual void purgeCallbacks(); + + private: + void clearPendingNotifications(); + + private: + class Private; + boost::shared_ptr<Private> p; + }; } diff --git a/SwifTools/Notifier/GrowlNotifier.mm b/SwifTools/Notifier/GrowlNotifier.mm index d5bdf6f..e9ffff7 100644 --- a/SwifTools/Notifier/GrowlNotifier.mm +++ b/SwifTools/Notifier/GrowlNotifier.mm @@ -17,101 +17,101 @@ #pragma GCC diagnostic ignored "-Wold-style-cast" namespace { - struct Context { - Context(const boost::function<void()>& callback) : callback(new boost::function<void()>(callback)) {} + struct Context { + Context(const boost::function<void()>& callback) : callback(new boost::function<void()>(callback)) {} - boost::function<void()>* callback; - }; + boost::function<void()>* callback; + }; } namespace Swift { class GrowlNotifier::Private { - public: - std::set<Context*> pendingNotifications; - boost::intrusive_ptr<GrowlNotifierDelegate> delegate; + public: + std::set<Context*> pendingNotifications; + boost::intrusive_ptr<GrowlNotifierDelegate> delegate; }; GrowlNotifier::GrowlNotifier(const std::string& name) { - p = boost::make_shared<Private>(); - p->delegate = boost::intrusive_ptr<GrowlNotifierDelegate>([[GrowlNotifierDelegate alloc] init], false); - p->delegate.get().notifier = this; - p->delegate.get().name = std2NSString(name); - - NSMutableArray* allNotifications = [[NSMutableArray alloc] init]; - foreach(Type type, getAllTypes()) { - [allNotifications addObject: std2NSString(typeToString(type))]; - } - - NSMutableArray* defaultNotifications = [[NSMutableArray alloc] init]; - foreach(Type type, getDefaultTypes()) { - [defaultNotifications addObject: std2NSString(typeToString(type))]; - } - - p->delegate.get().registrationDictionary = [[[NSDictionary alloc] - initWithObjects: [NSArray arrayWithObjects: allNotifications, defaultNotifications, nil] - forKeys: [NSArray arrayWithObjects: GROWL_NOTIFICATIONS_ALL, GROWL_NOTIFICATIONS_DEFAULT, nil]] autorelease]; - - [allNotifications release]; - [defaultNotifications release]; - - [GrowlApplicationBridge setGrowlDelegate: p->delegate.get()]; + p = boost::make_shared<Private>(); + p->delegate = boost::intrusive_ptr<GrowlNotifierDelegate>([[GrowlNotifierDelegate alloc] init], false); + p->delegate.get().notifier = this; + p->delegate.get().name = std2NSString(name); + + NSMutableArray* allNotifications = [[NSMutableArray alloc] init]; + foreach(Type type, getAllTypes()) { + [allNotifications addObject: std2NSString(typeToString(type))]; + } + + NSMutableArray* defaultNotifications = [[NSMutableArray alloc] init]; + foreach(Type type, getDefaultTypes()) { + [defaultNotifications addObject: std2NSString(typeToString(type))]; + } + + p->delegate.get().registrationDictionary = [[[NSDictionary alloc] + initWithObjects: [NSArray arrayWithObjects: allNotifications, defaultNotifications, nil] + forKeys: [NSArray arrayWithObjects: GROWL_NOTIFICATIONS_ALL, GROWL_NOTIFICATIONS_DEFAULT, nil]] autorelease]; + + [allNotifications release]; + [defaultNotifications release]; + + [GrowlApplicationBridge setGrowlDelegate: p->delegate.get()]; } GrowlNotifier::~GrowlNotifier() { - [GrowlApplicationBridge setGrowlDelegate: nil]; - clearPendingNotifications(); + [GrowlApplicationBridge setGrowlDelegate: nil]; + clearPendingNotifications(); } void GrowlNotifier::showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picturePath, boost::function<void()> callback) { - ByteArray picture; - readByteArrayFromFile(picture, picturePath); - - Context* context = new Context(callback); - // Growl sometimes sends timeout notifications twice for the same message. We therefore need - // to keep track of which ones have already been processed. - p->pendingNotifications.insert(context); - - [GrowlApplicationBridge - notifyWithTitle: std2NSString(subject) - description: std2NSString(description) - notificationName: std2NSString(typeToString(type)) - iconData: [NSData dataWithBytes: vecptr(picture) length: picture.size()] - priority: 0 - isSticky: NO - clickContext: [NSData dataWithBytes: &context length: sizeof(context)]]; + ByteArray picture; + readByteArrayFromFile(picture, picturePath); + + Context* context = new Context(callback); + // Growl sometimes sends timeout notifications twice for the same message. We therefore need + // to keep track of which ones have already been processed. + p->pendingNotifications.insert(context); + + [GrowlApplicationBridge + notifyWithTitle: std2NSString(subject) + description: std2NSString(description) + notificationName: std2NSString(typeToString(type)) + iconData: [NSData dataWithBytes: vecptr(picture) length: picture.size()] + priority: 0 + isSticky: NO + clickContext: [NSData dataWithBytes: &context length: sizeof(context)]]; } void GrowlNotifier::handleNotificationClicked(void* rawData) { - Context* context = *(Context**) [((NSData*) rawData) bytes]; - if (p->pendingNotifications.erase(context) > 0) { - if (!context->callback->empty()) { - (*context->callback)(); - } - delete context; - } + Context* context = *(Context**) [((NSData*) rawData) bytes]; + if (p->pendingNotifications.erase(context) > 0) { + if (!context->callback->empty()) { + (*context->callback)(); + } + delete context; + } } void GrowlNotifier::handleNotificationTimedOut(void* rawData) { - Context* context = *(Context**) [((NSData*) rawData) bytes]; - if (p->pendingNotifications.erase(context) > 0) { - delete context; - } + Context* context = *(Context**) [((NSData*) rawData) bytes]; + if (p->pendingNotifications.erase(context) > 0) { + delete context; + } } bool GrowlNotifier::isExternallyConfigured() const { - return ![GrowlApplicationBridge isMistEnabled]; + return ![GrowlApplicationBridge isMistEnabled]; } void GrowlNotifier::purgeCallbacks() { - clearPendingNotifications(); + clearPendingNotifications(); } void GrowlNotifier::clearPendingNotifications() { - foreach (Context* context, p->pendingNotifications) { - delete context; - } - p->pendingNotifications.clear(); + foreach (Context* context, p->pendingNotifications) { + delete context; + } + p->pendingNotifications.clear(); } } diff --git a/SwifTools/Notifier/GrowlNotifierDelegate.h b/SwifTools/Notifier/GrowlNotifierDelegate.h index 0640ff7..f4ce132 100644 --- a/SwifTools/Notifier/GrowlNotifierDelegate.h +++ b/SwifTools/Notifier/GrowlNotifierDelegate.h @@ -7,13 +7,13 @@ #import <Growl/Growl.h> namespace Swift { - class GrowlNotifier; + class GrowlNotifier; } @interface GrowlNotifierDelegate : NSObject<GrowlApplicationBridgeDelegate> { - Swift::GrowlNotifier* notifier; - NSString* name; - NSDictionary* registrationDictionary; + Swift::GrowlNotifier* notifier; + NSString* name; + NSDictionary* registrationDictionary; } @property (nonatomic, retain) NSDictionary* registrationDictionary; diff --git a/SwifTools/Notifier/GrowlNotifierDelegate.mm b/SwifTools/Notifier/GrowlNotifierDelegate.mm index 1d934ad..77df3ab 100644 --- a/SwifTools/Notifier/GrowlNotifierDelegate.mm +++ b/SwifTools/Notifier/GrowlNotifierDelegate.mm @@ -17,19 +17,19 @@ using namespace Swift; - (NSString *) applicationNameForGrowl { - return name; + return name; } - (NSDictionary*) registrationDictionaryForGrowl { - return registrationDictionary; + return registrationDictionary; } - (void) growlNotificationWasClicked: (id) clickContext { - notifier->handleNotificationClicked(clickContext); + notifier->handleNotificationClicked(clickContext); } - (void) growlNotificationTimedOut: (id) clickContext { - notifier->handleNotificationTimedOut(clickContext); + notifier->handleNotificationTimedOut(clickContext); } @end diff --git a/SwifTools/Notifier/LoggingNotifier.h b/SwifTools/Notifier/LoggingNotifier.h index d50cb2d..e12500b 100644 --- a/SwifTools/Notifier/LoggingNotifier.h +++ b/SwifTools/Notifier/LoggingNotifier.h @@ -11,23 +11,23 @@ #include <SwifTools/Notifier/Notifier.h> namespace Swift { - class LoggingNotifier : public Notifier { - public: - virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback) { - notifications.push_back(Notification(type, subject, description, picture, callback)); - } + class LoggingNotifier : public Notifier { + public: + virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback) { + notifications.push_back(Notification(type, subject, description, picture, callback)); + } - struct Notification { - Notification(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback) : type(type), subject(subject), description(description), picture(picture), callback(callback) {} - Type type; - std::string subject; - std::string description; - boost::filesystem::path picture; - boost::function<void()> callback; - }; + struct Notification { + Notification(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback) : type(type), subject(subject), description(description), picture(picture), callback(callback) {} + Type type; + std::string subject; + std::string description; + boost::filesystem::path picture; + boost::function<void()> callback; + }; - virtual void purgeCallbacks() {} + virtual void purgeCallbacks() {} - std::vector<Notification> notifications; - }; + std::vector<Notification> notifications; + }; } diff --git a/SwifTools/Notifier/NotificationCenterNotifier.h b/SwifTools/Notifier/NotificationCenterNotifier.h index 0d43c5b..75b4df7 100644 --- a/SwifTools/Notifier/NotificationCenterNotifier.h +++ b/SwifTools/Notifier/NotificationCenterNotifier.h @@ -18,21 +18,21 @@ namespace Swift { */ class NotificationCenterNotifier : public Notifier { public: - NotificationCenterNotifier(); - virtual ~NotificationCenterNotifier(); + NotificationCenterNotifier(); + virtual ~NotificationCenterNotifier(); - virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void ()> callback); - virtual void purgeCallbacks(); + virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void ()> callback); + virtual void purgeCallbacks(); - /** - * @brief The handleUserNotificationActivated is called by the delegate, when a user activates/clicks on a notification. - * @param identifier The std::string UUID identifiying the notification. - */ - void handleUserNotificationActivated(const std::string& identifier); + /** + * @brief The handleUserNotificationActivated is called by the delegate, when a user activates/clicks on a notification. + * @param identifier The std::string UUID identifiying the notification. + */ + void handleUserNotificationActivated(const std::string& identifier); private: - class Private; - boost::shared_ptr<Private> p; + class Private; + boost::shared_ptr<Private> p; }; } diff --git a/SwifTools/Notifier/NotificationCenterNotifier.mm b/SwifTools/Notifier/NotificationCenterNotifier.mm index 01e6368..57b9a4b 100644 --- a/SwifTools/Notifier/NotificationCenterNotifier.mm +++ b/SwifTools/Notifier/NotificationCenterNotifier.mm @@ -19,78 +19,78 @@ #include <SwifTools/Cocoa/CocoaUtil.h> namespace { - struct Context { - Context(const boost::function<void()>& callback) : callback(new boost::function<void()>(callback)) { - } + struct Context { + Context(const boost::function<void()>& callback) : callback(new boost::function<void()>(callback)) { + } - ~Context() { - delete callback; - } + ~Context() { + delete callback; + } - boost::function<void()>* callback; - }; + boost::function<void()>* callback; + }; } namespace Swift { class NotificationCenterNotifier::Private { - public: - std::map<std::string, boost::shared_ptr<Context> > callbacksForNotifications; - boost::intrusive_ptr<NotificationCenterNotifierDelegate> delegate; + public: + std::map<std::string, boost::shared_ptr<Context> > callbacksForNotifications; + boost::intrusive_ptr<NotificationCenterNotifierDelegate> delegate; }; NotificationCenterNotifier::NotificationCenterNotifier() { - p = boost::make_shared<Private>(); - p->delegate = boost::intrusive_ptr<NotificationCenterNotifierDelegate>([[NotificationCenterNotifierDelegate alloc] init], false); - [p->delegate.get() setNotifier: this]; + p = boost::make_shared<Private>(); + p->delegate = boost::intrusive_ptr<NotificationCenterNotifierDelegate>([[NotificationCenterNotifierDelegate alloc] init], false); + [p->delegate.get() setNotifier: this]; - [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate: p->delegate.get()]; + [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate: p->delegate.get()]; } NotificationCenterNotifier::~NotificationCenterNotifier() { - [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate: nil]; - p->callbacksForNotifications.clear(); + [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate: nil]; + p->callbacksForNotifications.clear(); } void NotificationCenterNotifier::showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void ()> callback) { - std::vector<Notifier::Type> defaultTypes = getDefaultTypes(); - if (std::find(defaultTypes.begin(), defaultTypes.end(), type) == defaultTypes.end()) { - return; - } - NSImage* image = [[NSImage alloc] initWithContentsOfFile: std2NSString(picture.string())]; - NSUserNotification* notification = [[NSUserNotification alloc] init]; - [notification setTitle:std2NSString(typeToString(type))]; - [notification setSubtitle:std2NSString(subject)]; - [notification setInformativeText:std2NSString(description)]; - [notification setContentImage: image]; - [image release]; - - // The OS X Notification Center API does not allow to attach custom data, like a pointer to a callback function, - // to the NSUserNotification object. Therefore we maintain a mapping from a NSUserNotification instance's identification - // to their respective callbacks. - [notification setIdentifier:[[NSUUID UUID] UUIDString]]; - - /// \todo Currently the elements are only removed on application exit. Ideally the notifications not required anymore - /// are removed from the map; e.g. when visiting a chat view, all notifications from that view can be removed from - /// the map and the NSUserNotificationCenter. - p->callbacksForNotifications[ns2StdString(notification.identifier)] = boost::make_shared<Context>(callback); - [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification]; - [notification release]; + std::vector<Notifier::Type> defaultTypes = getDefaultTypes(); + if (std::find(defaultTypes.begin(), defaultTypes.end(), type) == defaultTypes.end()) { + return; + } + NSImage* image = [[NSImage alloc] initWithContentsOfFile: std2NSString(picture.string())]; + NSUserNotification* notification = [[NSUserNotification alloc] init]; + [notification setTitle:std2NSString(typeToString(type))]; + [notification setSubtitle:std2NSString(subject)]; + [notification setInformativeText:std2NSString(description)]; + [notification setContentImage: image]; + [image release]; + + // The OS X Notification Center API does not allow to attach custom data, like a pointer to a callback function, + // to the NSUserNotification object. Therefore we maintain a mapping from a NSUserNotification instance's identification + // to their respective callbacks. + [notification setIdentifier:[[NSUUID UUID] UUIDString]]; + + /// \todo Currently the elements are only removed on application exit. Ideally the notifications not required anymore + /// are removed from the map; e.g. when visiting a chat view, all notifications from that view can be removed from + /// the map and the NSUserNotificationCenter. + p->callbacksForNotifications[ns2StdString(notification.identifier)] = boost::make_shared<Context>(callback); + [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification]; + [notification release]; } void NotificationCenterNotifier::purgeCallbacks() { - p->callbacksForNotifications.clear(); + p->callbacksForNotifications.clear(); } void NotificationCenterNotifier::handleUserNotificationActivated(const std::string& identifier) { - if (p->callbacksForNotifications.find(identifier) != p->callbacksForNotifications.end()) { - if (!(*p->callbacksForNotifications[identifier]->callback).empty()) { - (*p->callbacksForNotifications[identifier]->callback)(); - } - } - else { - SWIFT_LOG(warning) << "Missing callback entry for activated notification. The activate notification may come from another instance." << std::endl; - } + if (p->callbacksForNotifications.find(identifier) != p->callbacksForNotifications.end()) { + if (!(*p->callbacksForNotifications[identifier]->callback).empty()) { + (*p->callbacksForNotifications[identifier]->callback)(); + } + } + else { + SWIFT_LOG(warning) << "Missing callback entry for activated notification. The activate notification may come from another instance." << std::endl; + } } } diff --git a/SwifTools/Notifier/NotificationCenterNotifierDelegate.h b/SwifTools/Notifier/NotificationCenterNotifierDelegate.h index ea8fae0..f09c09f 100644 --- a/SwifTools/Notifier/NotificationCenterNotifierDelegate.h +++ b/SwifTools/Notifier/NotificationCenterNotifierDelegate.h @@ -9,7 +9,7 @@ #import <Cocoa/Cocoa.h> namespace Swift { - class NotificationCenterNotifier; + class NotificationCenterNotifier; } @interface NotificationCenterNotifierDelegate : NSObject<NSUserNotificationCenterDelegate> { diff --git a/SwifTools/Notifier/NotificationCenterNotifierDelegate.mm b/SwifTools/Notifier/NotificationCenterNotifierDelegate.mm index 2b1c2a4..84ec943 100644 --- a/SwifTools/Notifier/NotificationCenterNotifierDelegate.mm +++ b/SwifTools/Notifier/NotificationCenterNotifierDelegate.mm @@ -18,9 +18,9 @@ using namespace Swift; @synthesize notifier; - (void)userNotificationCenter:(NSUserNotificationCenter *) center didActivateNotification:(NSUserNotification *)notification { - (void)center; - std::string identifier = ns2StdString(notification.identifier); - notifier->handleUserNotificationActivated(identifier); + (void)center; + std::string identifier = ns2StdString(notification.identifier); + notifier->handleUserNotificationActivated(identifier); } @end diff --git a/SwifTools/Notifier/Notifier.cpp b/SwifTools/Notifier/Notifier.cpp index b8fd1a0..314d39c 100644 --- a/SwifTools/Notifier/Notifier.cpp +++ b/SwifTools/Notifier/Notifier.cpp @@ -15,32 +15,32 @@ Notifier::~Notifier() { } std::string Notifier::typeToString(Type type) { - switch (type) { - case ContactAvailable: return "Contact Becomes Available"; - case ContactUnavailable: return "Contact Becomes Unavailable"; - case ContactStatusChange: return "Contact Changes Status"; - case IncomingMessage: return "Incoming Message"; - case SystemMessage: return "System Message"; - } - assert(false); - return ""; + switch (type) { + case ContactAvailable: return "Contact Becomes Available"; + case ContactUnavailable: return "Contact Becomes Unavailable"; + case ContactStatusChange: return "Contact Changes Status"; + case IncomingMessage: return "Incoming Message"; + case SystemMessage: return "System Message"; + } + assert(false); + return ""; } std::vector<Notifier::Type> Notifier::getAllTypes() { - std::vector<Type> result; - result.push_back(ContactAvailable); - result.push_back(ContactUnavailable); - result.push_back(ContactStatusChange); - result.push_back(IncomingMessage); - result.push_back(SystemMessage); - return result; + std::vector<Type> result; + result.push_back(ContactAvailable); + result.push_back(ContactUnavailable); + result.push_back(ContactStatusChange); + result.push_back(IncomingMessage); + result.push_back(SystemMessage); + return result; } std::vector<Notifier::Type> Notifier::getDefaultTypes() { - std::vector<Type> result; - result.push_back(IncomingMessage); - result.push_back(SystemMessage); - return result; + std::vector<Type> result; + result.push_back(IncomingMessage); + result.push_back(SystemMessage); + return result; } } diff --git a/SwifTools/Notifier/Notifier.h b/SwifTools/Notifier/Notifier.h index b099701..afd596b 100644 --- a/SwifTools/Notifier/Notifier.h +++ b/SwifTools/Notifier/Notifier.h @@ -13,39 +13,39 @@ #include <boost/function.hpp> namespace Swift { - class Notifier { - public: - virtual ~Notifier(); - - enum Type { ContactAvailable, ContactUnavailable, ContactStatusChange, IncomingMessage, SystemMessage }; - - /** - * Picture is a PNG image. - */ - virtual void showMessage( - Type type, - const std::string& subject, - const std::string& description, - const boost::filesystem::path& picture, - boost::function<void()> callback) = 0; - - virtual bool isAvailable() const { - return true; - } - - virtual bool isExternallyConfigured() const { - return false; - } - - /** Remove any pending callbacks. */ - virtual void purgeCallbacks() = 0; - - protected: - std::string typeToString(Type type); - static std::vector<Type> getAllTypes(); - static std::vector<Type> getDefaultTypes(); - - static const int DEFAULT_STATUS_NOTIFICATION_TIMEOUT_SECONDS; - static const int DEFAULT_MESSAGE_NOTIFICATION_TIMEOUT_SECONDS; - }; + class Notifier { + public: + virtual ~Notifier(); + + enum Type { ContactAvailable, ContactUnavailable, ContactStatusChange, IncomingMessage, SystemMessage }; + + /** + * Picture is a PNG image. + */ + virtual void showMessage( + Type type, + const std::string& subject, + const std::string& description, + const boost::filesystem::path& picture, + boost::function<void()> callback) = 0; + + virtual bool isAvailable() const { + return true; + } + + virtual bool isExternallyConfigured() const { + return false; + } + + /** Remove any pending callbacks. */ + virtual void purgeCallbacks() = 0; + + protected: + std::string typeToString(Type type); + static std::vector<Type> getAllTypes(); + static std::vector<Type> getDefaultTypes(); + + static const int DEFAULT_STATUS_NOTIFICATION_TIMEOUT_SECONDS; + static const int DEFAULT_MESSAGE_NOTIFICATION_TIMEOUT_SECONDS; + }; } diff --git a/SwifTools/Notifier/NullNotifier.h b/SwifTools/Notifier/NullNotifier.h index 1f6d7d9..8945a53 100644 --- a/SwifTools/Notifier/NullNotifier.h +++ b/SwifTools/Notifier/NullNotifier.h @@ -9,11 +9,11 @@ #include <SwifTools/Notifier/Notifier.h> namespace Swift { - class NullNotifier : public Notifier { - public: - virtual void showMessage(Type, const std::string&, const std::string&, const boost::filesystem::path&, boost::function<void()>) { - } - virtual void purgeCallbacks() { - } - }; + class NullNotifier : public Notifier { + public: + virtual void showMessage(Type, const std::string&, const std::string&, const boost::filesystem::path&, boost::function<void()>) { + } + virtual void purgeCallbacks() { + } + }; } diff --git a/SwifTools/Notifier/SnarlNotifier.cpp b/SwifTools/Notifier/SnarlNotifier.cpp index b4e5ef3..e3977a7 100644 --- a/SwifTools/Notifier/SnarlNotifier.cpp +++ b/SwifTools/Notifier/SnarlNotifier.cpp @@ -18,56 +18,56 @@ namespace Swift { SnarlNotifier::SnarlNotifier(const std::string& name, Win32NotifierWindow* window, const boost::filesystem::path& icon) : window(window), available(false) { - window->onMessageReceived.connect(boost::bind(&SnarlNotifier::handleMessageReceived, this, _1)); - available = snarl.RegisterApp(name.c_str(), name.c_str(), icon.string().c_str(), window->getID(), SWIFT_SNARLNOTIFIER_MESSAGE_ID); - foreach(Notifier::Type type, getAllTypes()) { - snarl.AddClass(typeToString(type).c_str(), typeToString(type).c_str()); - } + window->onMessageReceived.connect(boost::bind(&SnarlNotifier::handleMessageReceived, this, _1)); + available = snarl.RegisterApp(name.c_str(), name.c_str(), icon.string().c_str(), window->getID(), SWIFT_SNARLNOTIFIER_MESSAGE_ID); + foreach(Notifier::Type type, getAllTypes()) { + snarl.AddClass(typeToString(type).c_str(), typeToString(type).c_str()); + } } SnarlNotifier::~SnarlNotifier() { - snarl.UnregisterApp(); - window->onMessageReceived.disconnect(boost::bind(&SnarlNotifier::handleMessageReceived, this, _1)); - if (!notifications.empty()) { - std::cerr << "Warning: " << notifications.size() << " Snarl notifications pending" << std::endl; - } + snarl.UnregisterApp(); + window->onMessageReceived.disconnect(boost::bind(&SnarlNotifier::handleMessageReceived, this, _1)); + if (!notifications.empty()) { + std::cerr << "Warning: " << notifications.size() << " Snarl notifications pending" << std::endl; + } } bool SnarlNotifier::isAvailable() const { - return available; + return available; } void SnarlNotifier::showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback) { - int timeout = (type == IncomingMessage || type == SystemMessage) ? DEFAULT_MESSAGE_NOTIFICATION_TIMEOUT_SECONDS : DEFAULT_STATUS_NOTIFICATION_TIMEOUT_SECONDS; - int notificationID = snarl.EZNotify( - typeToString(type).c_str(), - subject.c_str(), - description.c_str(), - timeout, - picture.string().c_str()); - if (notificationID > 0) { - notifications.insert(std::make_pair(notificationID, callback)); - } + int timeout = (type == IncomingMessage || type == SystemMessage) ? DEFAULT_MESSAGE_NOTIFICATION_TIMEOUT_SECONDS : DEFAULT_STATUS_NOTIFICATION_TIMEOUT_SECONDS; + int notificationID = snarl.EZNotify( + typeToString(type).c_str(), + subject.c_str(), + description.c_str(), + timeout, + picture.string().c_str()); + if (notificationID > 0) { + notifications.insert(std::make_pair(notificationID, callback)); + } } void SnarlNotifier::handleMessageReceived(MSG* message) { - if (message->message == SWIFT_SNARLNOTIFIER_MESSAGE_ID) { - int action = message->wParam; - if (action == Snarl::V41::SnarlEnums::NotificationTimedOut || action == Snarl::V41::SnarlEnums::NotificationAck || action == Snarl::V41::SnarlEnums::NotificationClosed) { - int notificationID = message->lParam; - NotificationsMap::iterator i = notifications.find(notificationID); - if (i != notifications.end()) { - if (action == Snarl::V41::SnarlEnums::NotificationAck && !i->second.empty()) { - i->second(); - } - notifications.erase(i); - } - else { - std::cerr << "Warning: Orphaned Snarl notification received"; - } - } - } + if (message->message == SWIFT_SNARLNOTIFIER_MESSAGE_ID) { + int action = message->wParam; + if (action == Snarl::V41::SnarlEnums::NotificationTimedOut || action == Snarl::V41::SnarlEnums::NotificationAck || action == Snarl::V41::SnarlEnums::NotificationClosed) { + int notificationID = message->lParam; + NotificationsMap::iterator i = notifications.find(notificationID); + if (i != notifications.end()) { + if (action == Snarl::V41::SnarlEnums::NotificationAck && !i->second.empty()) { + i->second(); + } + notifications.erase(i); + } + else { + std::cerr << "Warning: Orphaned Snarl notification received"; + } + } + } } } diff --git a/SwifTools/Notifier/SnarlNotifier.h b/SwifTools/Notifier/SnarlNotifier.h index b8b9a48..5006185 100644 --- a/SwifTools/Notifier/SnarlNotifier.h +++ b/SwifTools/Notifier/SnarlNotifier.h @@ -13,28 +13,28 @@ #include <SwifTools/Notifier/Notifier.h> namespace Swift { - class Win32NotifierWindow; - - class SnarlNotifier : public Notifier { - public: - SnarlNotifier(const std::string& name, Win32NotifierWindow* window, const boost::filesystem::path& icon); - ~SnarlNotifier(); - - virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback); - virtual bool isAvailable() const; - - virtual void purgeCallbacks() { - notifications.clear(); - } - - private: - void handleMessageReceived(MSG* message); - - private: - Snarl::V41::SnarlInterface snarl; - Win32NotifierWindow* window; - bool available; - typedef std::map<int, boost::function<void()> > NotificationsMap; - NotificationsMap notifications; - }; + class Win32NotifierWindow; + + class SnarlNotifier : public Notifier { + public: + SnarlNotifier(const std::string& name, Win32NotifierWindow* window, const boost::filesystem::path& icon); + ~SnarlNotifier(); + + virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback); + virtual bool isAvailable() const; + + virtual void purgeCallbacks() { + notifications.clear(); + } + + private: + void handleMessageReceived(MSG* message); + + private: + Snarl::V41::SnarlInterface snarl; + Win32NotifierWindow* window; + bool available; + typedef std::map<int, boost::function<void()> > NotificationsMap; + NotificationsMap notifications; + }; } diff --git a/SwifTools/Notifier/TogglableNotifier.h b/SwifTools/Notifier/TogglableNotifier.h index 5580322..c537a6f 100644 --- a/SwifTools/Notifier/TogglableNotifier.h +++ b/SwifTools/Notifier/TogglableNotifier.h @@ -9,54 +9,54 @@ #include <SwifTools/Notifier/Notifier.h> namespace Swift { - class TogglableNotifier : public Notifier { - public: - TogglableNotifier(Notifier* notifier) : notifier(notifier), persistentEnabled(true), temporarilyDisabled(false) { - } - - /** - * Set a long-term (usually user-set) enabled. - * This may be temporarily overriden by the application, e.g. if the - * user is marked DND. - */ - void setPersistentEnabled(bool b) { - persistentEnabled = b; - } - - /** - * Set a temporary override to stop notifications without changing the - * long-term state. e.g. if the user goes DND, but the persistent - * enabled shouldn't be lost when they become available again. - */ - void setTemporarilyDisabled(bool b) { - temporarilyDisabled = b; - } - - /** - * Get the result of applying the temporary override to the persistent - * enabledness. - */ - bool getCurrentlyEnabled() const { - return persistentEnabled && !temporarilyDisabled; - } - - virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback) { - if (getCurrentlyEnabled() || notifier->isExternallyConfigured()) { - notifier->showMessage(type, subject, description, picture, callback); - } - } - - virtual bool isExternallyConfigured() const { - return notifier->isExternallyConfigured(); - } - - virtual void purgeCallbacks() { - notifier->purgeCallbacks(); - } - - private: - Notifier* notifier; - bool persistentEnabled; - bool temporarilyDisabled; - }; + class TogglableNotifier : public Notifier { + public: + TogglableNotifier(Notifier* notifier) : notifier(notifier), persistentEnabled(true), temporarilyDisabled(false) { + } + + /** + * Set a long-term (usually user-set) enabled. + * This may be temporarily overriden by the application, e.g. if the + * user is marked DND. + */ + void setPersistentEnabled(bool b) { + persistentEnabled = b; + } + + /** + * Set a temporary override to stop notifications without changing the + * long-term state. e.g. if the user goes DND, but the persistent + * enabled shouldn't be lost when they become available again. + */ + void setTemporarilyDisabled(bool b) { + temporarilyDisabled = b; + } + + /** + * Get the result of applying the temporary override to the persistent + * enabledness. + */ + bool getCurrentlyEnabled() const { + return persistentEnabled && !temporarilyDisabled; + } + + virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback) { + if (getCurrentlyEnabled() || notifier->isExternallyConfigured()) { + notifier->showMessage(type, subject, description, picture, callback); + } + } + + virtual bool isExternallyConfigured() const { + return notifier->isExternallyConfigured(); + } + + virtual void purgeCallbacks() { + notifier->purgeCallbacks(); + } + + private: + Notifier* notifier; + bool persistentEnabled; + bool temporarilyDisabled; + }; } diff --git a/SwifTools/Notifier/Win32NotifierWindow.h b/SwifTools/Notifier/Win32NotifierWindow.h index 8e67146..3f03825 100644 --- a/SwifTools/Notifier/Win32NotifierWindow.h +++ b/SwifTools/Notifier/Win32NotifierWindow.h @@ -11,12 +11,12 @@ #include <Swiften/Base/boost_bsignals.h> namespace Swift { - class Win32NotifierWindow { - public: - virtual ~Win32NotifierWindow() {} + class Win32NotifierWindow { + public: + virtual ~Win32NotifierWindow() {} - virtual HWND getID() const = 0; + virtual HWND getID() const = 0; - boost::signal<void (MSG*)> onMessageReceived; - }; + boost::signal<void (MSG*)> onMessageReceived; + }; } |