From ddc0ef9f5520d1e1e18e134f1a8fbdb678bbbc94 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Tue, 14 Dec 2010 21:41:57 +0100
Subject: Added initial Growl for Windows notifier (GNTP).

The notifier doesn't handle callbacks yet.

Release-Notes: Replaced Snarl notifications with Growl for Windows notifications.

diff --git a/SwifTools/Notifier/GNTPNotifier.cpp b/SwifTools/Notifier/GNTPNotifier.cpp
new file mode 100644
index 0000000..f96f94b
--- /dev/null
+++ b/SwifTools/Notifier/GNTPNotifier.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "SwifTools/Notifier/GNTPNotifier.h"
+
+#include <cassert>
+#include <iostream>
+#include <boost/bind.hpp>
+#include <sstream>
+
+#include "Swiften/Base/foreach.h"
+#include "Swiften/Network/ConnectionFactory.h"
+
+namespace Swift {
+
+GNTPNotifier::GNTPNotifier(const 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://" << icon.string() << "\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());
+}
+
+GNTPNotifier::~GNTPNotifier() {
+}
+
+void GNTPNotifier::send(const std::string& message) {
+	std::cout << "Send " << currentConnection << std::endl;
+
+	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 String& subject, const String& description, const boost::filesystem::path& picture, boost::function<void()> callback) {
+	std::cout << "showMessage " << registered << std::endl;
+	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: " << picture.string() << "\r\n";
+		message << "\r\n";
+		send(message.str());
+	}
+}
+
+void GNTPNotifier::handleConnectFinished(bool error) {
+	if (!initialized) {
+		initialized = true;
+		registered = !error;
+	}
+	std::cout << "Connect: " << initialized << " " << registered << std::endl;
+
+	if (!error) {
+		std::cout << "Write data: " << currentMessage << std::endl;
+		currentConnection->write(currentMessage.c_str());
+	}
+}
+
+void GNTPNotifier::handleDataRead(const ByteArray& data) {
+	std::cout << "Data read: " << data.getData() << std::endl;
+	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
new file mode 100644
index 0000000..47b0c01
--- /dev/null
+++ b/SwifTools/Notifier/GNTPNotifier.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/filesystem.hpp>
+
+#include "SwifTools/Notifier/Notifier.h"
+#include "Swiften/Network/Connection.h"
+
+namespace Swift {
+	class ConnectionFactory;
+
+	class GNTPNotifier : public Notifier {
+		public:
+			GNTPNotifier(const String& name, const boost::filesystem::path& icon, ConnectionFactory* connectionFactory);
+			~GNTPNotifier();
+
+			virtual void showMessage(Type type, const String& subject, const 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:
+			String name;
+			boost::filesystem::path icon;
+			ConnectionFactory* connectionFactory;
+			bool initialized;
+			bool registered;
+			std::string currentMessage;
+			Connection::ref currentConnection;
+	};
+}
diff --git a/SwifTools/Notifier/SConscript b/SwifTools/Notifier/SConscript
index 9ad2fd7..7a991e8 100644
--- a/SwifTools/Notifier/SConscript
+++ b/SwifTools/Notifier/SConscript
@@ -4,6 +4,7 @@ myenv = swiftools_env.Clone()
 
 sources = [
 		"Notifier.cpp",
+		"GNTPNotifier.cpp",
 	]
 
 if swiftools_env.get("HAVE_GROWL", False) :
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 56ebb0c..de7009c 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -57,6 +57,7 @@
 #include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h"
 #include "Swift/Controllers/CertificateStorageFactory.h"
 #include "Swift/Controllers/CertificateStorageTrustChecker.h"
+#include "Swiften/Network/NetworkFactories.h"
 
 namespace Swift {
 
@@ -67,6 +68,7 @@ static const String SHOW_NOTIFICATIONS = "showNotifications";
 
 MainController::MainController(
 		EventLoop* eventLoop,
+		NetworkFactories* networkFactories,
 		ChatWindowFactory* chatWindowFactory,
 		MainWindowFactory *mainWindowFactory,
 		LoginWindowFactory *loginWindowFactory,
@@ -83,8 +85,8 @@ MainController::MainController(
 		Notifier* notifier,
 		bool useDelayForLatency) :
 			eventLoop_(eventLoop),
-			networkFactories_(eventLoop),
-			idleDetector_(&idleQuerier_, networkFactories_.getTimerFactory(), 100),
+			networkFactories_(networkFactories),
+			idleDetector_(&idleQuerier_, networkFactories_->getTimerFactory(), 100),
 			storagesFactory_(storagesFactory),
 			certificateStorageFactory_(certificateStorageFactory),
 			chatWindowFactory_(chatWindowFactory),
@@ -234,7 +236,7 @@ void MainController::handleConnected() {
 		rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2));
 		rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this));
 
-		chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, chatWindowFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, chatListWindowFactory_, useDelayForLatency_, networkFactories_.getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager());
+		chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, chatWindowFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, chatListWindowFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager());
 		client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1));
 		chatsManager_->setAvatarManager(client_->getAvatarManager());
 
@@ -369,7 +371,7 @@ void MainController::performLoginFromCachedCredentials() {
 		storages_ = storagesFactory_->createStorages(jid_.toBare());
 		certificateStorage_ = certificateStorageFactory_->createCertificateStorage(jid_.toBare());
 		certificateTrustChecker_ = new CertificateStorageTrustChecker(certificateStorage_);
-		client_ = new Swift::Client(eventLoop_, &networkFactories_, clientJID, password_, storages_);
+		client_ = new Swift::Client(eventLoop_, networkFactories_, clientJID, password_, storages_);
 		client_->setCertificateTrustChecker(certificateTrustChecker_);
 		// FIXME: Remove this line to activate the trust checker
 		//client_->setAlwaysTrustCertificates();
@@ -381,7 +383,7 @@ void MainController::performLoginFromCachedCredentials() {
 		client_->setSoftwareVersion(CLIENT_NAME, buildVersion);
 
 		client_->getVCardManager()->onVCardChanged.connect(boost::bind(&MainController::handleVCardReceived, this, _1, _2));
-		presenceNotifier_ = new PresenceNotifier(client_->getStanzaChannel(), notifier_, client_->getMUCRegistry(), client_->getAvatarManager(), client_->getNickResolver(), client_->getPresenceOracle(), networkFactories_.getTimerFactory());
+		presenceNotifier_ = new PresenceNotifier(client_->getStanzaChannel(), notifier_, client_->getMUCRegistry(), client_->getAvatarManager(), client_->getNickResolver(), client_->getPresenceOracle(), networkFactories_->getTimerFactory());
 		presenceNotifier_->onNotificationActivated.connect(boost::bind(&MainController::handleNotificationClicked, this, _1));
 		eventNotifier_ = new EventNotifier(eventController_, notifier_, client_->getAvatarManager(), client_->getNickResolver());
 		eventNotifier_->onNotificationActivated.connect(boost::bind(&MainController::handleNotificationClicked, this, _1));
@@ -486,7 +488,7 @@ void MainController::setReconnectTimer() {
 	if (reconnectTimer_) {
 		reconnectTimer_->stop();
 	}
-	reconnectTimer_ = networkFactories_.getTimerFactory()->createTimer(timeBeforeNextReconnect_ * 1000);
+	reconnectTimer_ = networkFactories_->getTimerFactory()->createTimer(timeBeforeNextReconnect_ * 1000);
 	reconnectTimer_->onTick.connect(boost::bind(&MainController::reconnectAfterError, this));
 	reconnectTimer_->start();
 }
diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h
index 1256345..0427307 100644
--- a/Swift/Controllers/MainController.h
+++ b/Swift/Controllers/MainController.h
@@ -10,7 +10,6 @@
 #include <boost/shared_ptr.hpp>
 #include <vector>
 
-#include "Swiften/Network/BoostNetworkFactories.h"
 #include "Swiften/Network/Timer.h"
 #include "SwifTools/Idle/PlatformIdleQuerier.h"
 #include "SwifTools/Idle/ActualIdleDetector.h"
@@ -64,11 +63,13 @@ namespace Swift {
 	class Dock;
 	class Storages;
 	class StoragesFactory;
+	class NetworkFactories;
 
 	class MainController {
 		public:
 			MainController(
 					EventLoop* eventLoop,
+					NetworkFactories* networkFactories,
 					ChatWindowFactory* chatWindowFactory,
 					MainWindowFactory *mainWindowFactory,
 					LoginWindowFactory *loginWindowFactory,
@@ -114,7 +115,7 @@ namespace Swift {
 
 		private:
 			EventLoop* eventLoop_;
-			BoostNetworkFactories networkFactories_;
+			NetworkFactories* networkFactories_;
 			PlatformIdleQuerier idleQuerier_;
 			ActualIdleDetector idleDetector_;
 			StoragesFactory* storagesFactory_;
diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp
index 04b9d02..65eb534 100644
--- a/Swift/QtUI/QtSwift.cpp
+++ b/Swift/QtUI/QtSwift.cpp
@@ -42,7 +42,7 @@
 #include "SwifTools/Notifier/GrowlNotifier.h"
 #elif defined(HAVE_SNARL)
 #include "QtWin32NotifierWindow.h"
-#include "SwifTools/Notifier/SnarlNotifier.h"
+#include "SwifTools/Notifier/GNTPNotifier.h"
 #elif defined(SWIFTEN_PLATFORM_LINUX)
 #include "FreeDesktopNotifier.h"
 #else
@@ -76,7 +76,7 @@ po::options_description QtSwift::getOptionsDescription() {
 }
 
 
-QtSwift::QtSwift(po::variables_map options) : autoUpdater_(NULL) {
+QtSwift::QtSwift(po::variables_map options) : networkFactories_(&clientMainThreadCaller_), autoUpdater_(NULL) {
 	if (options.count("netbook-mode")) {
 		splitter_ = new QSplitter();
 	} else {
@@ -109,8 +109,7 @@ QtSwift::QtSwift(po::variables_map options) : autoUpdater_(NULL) {
 #if defined(HAVE_GROWL)
 	notifier_ = new GrowlNotifier(SWIFT_APPLICATION_NAME);
 #elif defined(HAVE_SNARL)
-	notifierWindow_ = new QtWin32NotifierWindow();
-	notifier_ = new SnarlNotifier(SWIFT_APPLICATION_NAME, notifierWindow_, applicationPathProvider_->getResourcePath("/images/logo-icon-32.png"));
+	notifier_ = new GNTPNotifier(SWIFT_APPLICATION_NAME, applicationPathProvider_->getResourcePath("/images/logo-icon-128.png"), networkFactories_.getConnectionFactory());
 #elif defined(SWIFTEN_PLATFORM_LINUX)
 	notifier_ = new FreeDesktopNotifier(SWIFT_APPLICATION_NAME);
 #else
@@ -144,6 +143,7 @@ QtSwift::QtSwift(po::variables_map options) : autoUpdater_(NULL) {
 		mucSearchWindowFactories_.push_back(mucSearchWindowFactory);
 		MainController* mainController = new MainController(
 				&clientMainThreadCaller_,
+				&networkFactories_,
 				chatWindowFactory_,
 				rosterWindowFactory,
 				loginWindowFactory,
diff --git a/Swift/QtUI/QtSwift.h b/Swift/QtUI/QtSwift.h
index a41e2d1..68933dd 100644
--- a/Swift/QtUI/QtSwift.h
+++ b/Swift/QtUI/QtSwift.h
@@ -10,6 +10,7 @@
 #include <boost/program_options/options_description.hpp>
 
 #include <Swiften/TLS/PlatformTLSFactories.h>
+#include <Swiften/Network/BoostNetworkFactories.h>
 #include "Swiften/Base/String.h"
 #include "Swiften/Base/Platform.h"
 #include "Swiften/EventLoop/Qt/QtEventLoop.h"
@@ -56,7 +57,9 @@ namespace Swift {
 			static po::options_description getOptionsDescription();
 			~QtSwift();
 		private:
+			QtEventLoop clientMainThreadCaller_;
 			PlatformTLSFactories tlsFactories_;
+			BoostNetworkFactories networkFactories_;
 			std::vector<MainController*> mainControllers_;
 			QtChatWindowFactory *chatWindowFactory_;
 			std::vector<QtMainWindowFactory*> rosterWindowFactories_;
@@ -66,7 +69,6 @@ namespace Swift {
 			std::vector<QtSystemTray*> systemTrays_;
 			std::vector<QtChatListWindowFactory*> chatListWindowFactories_;
 			std::vector<QtMUCSearchWindowFactory*> mucSearchWindowFactories_;
-			QtEventLoop clientMainThreadCaller_;
 			QtSettingsProvider *settings_;
 			QSplitter* splitter_;
 			QtSoundPlayer* soundPlayer_;
@@ -80,8 +82,5 @@ namespace Swift {
 #if defined(SWIFTEN_PLATFORM_MACOSX)
 			CocoaApplication cocoaApplication_;
 #endif
-#if defined(HAVE_SNARL)
-			Win32NotifierWindow* notifierWindow_;
-#endif
 	};
 }
diff --git a/Swiften/Network/Connection.h b/Swiften/Network/Connection.h
index 8c30ad7..712f145 100644
--- a/Swiften/Network/Connection.h
+++ b/Swiften/Network/Connection.h
@@ -6,8 +6,9 @@
 
 #pragma once
 
-#include "Swiften/Base/boost_bsignals.h"
+#include <boost/shared_ptr.hpp>
 
+#include "Swiften/Base/boost_bsignals.h"
 #include "Swiften/Base/ByteArray.h"
 #include "Swiften/Base/String.h"
 #include "Swiften/Network/HostAddressPort.h"
@@ -15,6 +16,8 @@
 namespace Swift {
 	class Connection {
 		public:
+			typedef boost::shared_ptr<Connection> ref;
+
 			enum Error {
 				ReadError,
 				WriteError
-- 
cgit v0.10.2-6-g49f6