From 3b8a09263c836a4cd397b606edbb023b19cf46b5 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Fri, 23 Jul 2010 12:19:20 +0100
Subject: Generate a Notice if your nick is mentioned in a MUC.

Resolves: #471

diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 8117004..3012377 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -15,14 +15,15 @@
 #include "Swift/Controllers/UIInterfaces/ChatWindow.h"
 #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
 #include "Swift/Controllers/NickResolver.h"
+#include "Swift/Controllers/EventController.h"
 
 namespace Swift {
 	
 /**
  * The controller does not gain ownership of the stanzaChannel, nor the factory.
  */
-ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream)
-	: ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream) {
+ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController)
+	: ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController) {
 	isInMUC_ = isInMUC;
 	chatStateNotifier_ = new ChatStateNotifier();
 	chatStateMessageSender_ = new ChatStateMessageSender(chatStateNotifier_, stanzaChannel, contact);
@@ -58,7 +59,9 @@ bool ChatController::isIncomingMessageFromMe(boost::shared_ptr<Message>) {
 	return false;
 }
 
-void ChatController::preHandleIncomingMessage(boost::shared_ptr<Message> message) {
+void ChatController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent) {
+	eventController_->handleIncomingEvent(messageEvent);
+	boost::shared_ptr<Message> message = messageEvent->getStanza();
 	JID from = message->getFrom();
 	if (!from.equals(toJID_, JID::WithResource)) {
 		if (toJID_.equals(from, JID::WithoutResource)  && toJID_.isBare()){
diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h
index 61ab752..291a0d0 100644
--- a/Swift/Controllers/Chat/ChatController.h
+++ b/Swift/Controllers/Chat/ChatController.h
@@ -17,7 +17,7 @@ namespace Swift {
 	class NickResolver;
 	class ChatController : public ChatControllerBase {
 		public:
-			ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream);
+			ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController);
 			virtual ~ChatController();
 			virtual void setToJID(const JID& jid);
 
@@ -26,7 +26,7 @@ namespace Swift {
 			String getStatusChangeString(boost::shared_ptr<Presence> presence);
 			bool isIncomingMessageFromMe(boost::shared_ptr<Message> message);
 			void postSendMessage(const String &body);
-			void preHandleIncomingMessage(boost::shared_ptr<Message> message);
+			void preHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent);
 			void preSendMessageRequest(boost::shared_ptr<Message>);
 			String senderDisplayNameFromMessage(const JID& from);
 			virtual boost::optional<boost::posix_time::ptime> getMessageTimestamp(boost::shared_ptr<Message>) const;
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp
index 1650dbf..b86a993 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.cpp
+++ b/Swift/Controllers/Chat/ChatControllerBase.cpp
@@ -15,6 +15,7 @@
 #include "Swiften/Client/StanzaChannel.h"
 #include "Swiften/Elements/Delay.h"
 #include "Swiften/Base/foreach.h"
+#include "Swift/Controllers/EventController.h"
 #include "Swift/Controllers/UIInterfaces/ChatWindow.h"
 #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
 #include "Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h"
@@ -22,7 +23,7 @@
 
 namespace Swift {
 
-ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency)  {
+ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency), eventController_(eventController) {
 	chatWindow_ = chatWindowFactory_->createChatWindow(toJID, eventStream);
 	chatWindow_->onAllMessagesRead.connect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this));
 	chatWindow_->onSendMessageRequest.connect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1));
@@ -123,8 +124,9 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m
 	}
 	chatWindow_->setUnreadMessageCount(unreadMessages_.size());
 
+
+	preHandleIncomingMessage(messageEvent);	
 	boost::shared_ptr<Message> message = messageEvent->getStanza();
-	preHandleIncomingMessage(message);	
 	String body = message->getBody();
 	if (message->isError()) {
 		String errorMessage = getErrorMessage(message->getPayload<ErrorPayload>());
diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h
index b851857..f0d4b7a 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.h
+++ b/Swift/Controllers/Chat/ChatControllerBase.h
@@ -31,6 +31,7 @@ namespace Swift {
 	class ChatWindowFactory;
 	class AvatarManager;
 	class UIEventStream;
+	class EventController;
 
 	class ChatControllerBase  {
 		public:
@@ -43,12 +44,12 @@ namespace Swift {
 			void setEnabled(bool enabled);
 			virtual void setToJID(const JID& jid) {toJID_ = jid;};
 		protected:
-			ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream);
+			ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController);
 
 			virtual void postSendMessage(const String&) {};
 			virtual String senderDisplayNameFromMessage(const JID& from) = 0;
 			virtual bool isIncomingMessageFromMe(boost::shared_ptr<Message>) = 0;
-			virtual void preHandleIncomingMessage(boost::shared_ptr<Message>) {};
+			virtual void preHandleIncomingMessage(boost::shared_ptr<MessageEvent>) {};
 			virtual void preSendMessageRequest(boost::shared_ptr<Message>) {};
 			virtual bool isFromContact(const JID& from);
 			virtual boost::optional<boost::posix_time::ptime> getMessageTimestamp(boost::shared_ptr<Message>) const = 0;
@@ -71,6 +72,7 @@ namespace Swift {
 			PresenceOracle* presenceOracle_;
 			AvatarManager* avatarManager_;
 			bool useDelayForLatency_;
+			EventController* eventController_;
 	};
 }
 
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index ea38f1f..2ed7051 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -168,7 +168,7 @@ ChatController* ChatsManager::getChatControllerOrFindAnother(const JID &contact)
 }
 
 ChatController* ChatsManager::createNewChatController(const JID& contact) {
-	ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_);
+	ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, eventController_);
 	chatControllers_[contact] = controller;
 	controller->setAvailableServerFeatures(serverDiscoInfo_);
 	return controller;
@@ -204,7 +204,7 @@ void ChatsManager::handleJoinMUCRequest(const JID &muc, const boost::optional<St
 		//FIXME: What's correct behaviour here?
 	} else {
 		String nick = nickMaybe ? nickMaybe.get() : "Swift user";
-		MUCController* controller = new MUCController(jid_, muc, nick, stanzaChannel_, presenceSender_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_);
+		MUCController* controller = new MUCController(jid_, muc, nick, stanzaChannel_, presenceSender_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_);
 		mucControllers_[muc] = controller;
 		controller->setAvailableServerFeatures(serverDiscoInfo_);
 		controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller));
@@ -233,7 +233,6 @@ void ChatsManager::handleIncomingMessage(boost::shared_ptr<Message> message) {
 	}
 	
 	//if not a mucroom
-	eventController_->handleIncomingEvent(event);
 	getChatControllerOrCreate(jid)->handleIncomingMessage(event);
 }
 
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 6029a14..1e790b7 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -12,6 +12,7 @@
 #include "Swiften/Network/TimerFactory.h"
 #include "SwifTools/TabComplete.h"
 #include "Swiften/Base/foreach.h"
+#include "Swift/Controllers/EventController.h"
 #include "Swift/Controllers/UIInterfaces/ChatWindow.h"
 #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
 #include "Swift/Controllers/UIEvents/UIEventStream.h"
@@ -23,6 +24,7 @@
 #include "Swiften/Roster/SetAvatar.h"
 #include "Swiften/Roster/SetPresence.h"
 
+
 #define MUC_JOIN_WARNING_TIMEOUT_MILLISECONDS 60000
 
 namespace Swift {
@@ -42,8 +44,9 @@ MUCController::MUCController (
 		AvatarManager* avatarManager,
 		UIEventStream* uiEventStream,
 		bool useDelayForLatency,
-		TimerFactory* timerFactory) :
-	ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc, presenceOracle, avatarManager, useDelayForLatency, uiEventStream),
+		TimerFactory* timerFactory,
+		EventController* eventController) :
+	ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc, presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController),
 			muc_(new MUC(stanzaChannel, presenceSender, muc)), 
 	nick_(nick) {
 	parting_ = false;
@@ -185,7 +188,15 @@ JID MUCController::nickToJID(const String& nick) {
 	return JID(toJID_.getNode(), toJID_.getDomain(), nick);
 }
 
-void MUCController::preHandleIncomingMessage(boost::shared_ptr<Message> message) {
+bool MUCController::messageTargetsMe(boost::shared_ptr<Message> message) {
+	return message->getBody().contains(nick_);
+}
+
+void MUCController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent) {
+	boost::shared_ptr<Message> message = messageEvent->getStanza();
+	if (messageTargetsMe(message)) {
+		eventController_->handleIncomingEvent(messageEvent);
+	}
 	String nick = message->getFrom().getResource();
 	if (nick != nick_) {
 		completer_->removeWord(nick);
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index e93af1e..65ef84c 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -32,7 +32,7 @@ namespace Swift {
 
 	class MUCController : public ChatControllerBase {
 		public:
-			MUCController(const JID& self, const JID &muc, const String &nick, StanzaChannel* stanzaChannel, PresenceSender* presenceSender, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory);
+			MUCController(const JID& self, const JID &muc, const String &nick, StanzaChannel* stanzaChannel, PresenceSender* presenceSender, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController);
 			~MUCController();
 			boost::signal<void ()> onUserLeft;
 		
@@ -41,6 +41,7 @@ namespace Swift {
 			bool isIncomingMessageFromMe(boost::shared_ptr<Message> message);
 			String senderDisplayNameFromMessage(const JID& from);
 			boost::optional<boost::posix_time::ptime> getMessageTimestamp(boost::shared_ptr<Message> message) const;
+			void preHandleIncomingMessage(boost::shared_ptr<MessageEvent>);
 
 		private:
 			void handleWindowClosed();
@@ -56,7 +57,7 @@ namespace Swift {
 			JID nickToJID(const String& nick);
 			String roleToFriendlyName(MUCOccupant::Role role);
 			void receivedActivity();
-			void preHandleIncomingMessage(boost::shared_ptr<Message>);
+			bool messageTargetsMe(boost::shared_ptr<Message> message);
 		private:
 			MUC* muc_;
 			UIEventStream* events_;
diff --git a/Swift/QtUI/EventViewer/QtEventWindow.cpp b/Swift/QtUI/EventViewer/QtEventWindow.cpp
index 6abfd66..03050f5 100644
--- a/Swift/QtUI/EventViewer/QtEventWindow.cpp
+++ b/Swift/QtUI/EventViewer/QtEventWindow.cpp
@@ -16,6 +16,7 @@
 #include "Swift/QtUI/QtSubscriptionRequestWindow.h"
 #include "Swiften/Events/SubscriptionRequestEvent.h"
 #include "Swift/Controllers/UIEvents/RequestChatUIEvent.h"
+#include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h"
 
 
 #include "Swiften/Base/Platform.h"
@@ -76,7 +77,11 @@ void QtEventWindow::handleItemActivated(const QModelIndex& item) {
 	boost::shared_ptr<ErrorEvent> errorEvent = boost::dynamic_pointer_cast<ErrorEvent>(event->getEvent());
 	
 	if (messageEvent) {
-		eventStream_->send(boost::shared_ptr<UIEvent>(new RequestChatUIEvent(messageEvent->getStanza()->getFrom())));
+		if (messageEvent->getStanza()->getType() == Message::Groupchat) {
+			eventStream_->send(boost::shared_ptr<UIEvent>(new JoinMUCUIEvent(messageEvent->getStanza()->getFrom().toBare(), messageEvent->getStanza()->getTo().getResource())));
+		} else {
+			eventStream_->send(boost::shared_ptr<UIEvent>(new RequestChatUIEvent(messageEvent->getStanza()->getFrom())));
+		}
 	} else if (subscriptionEvent) {
 		QtSubscriptionRequestWindow* window = QtSubscriptionRequestWindow::getWindow(subscriptionEvent, this);
 		window->show();
-- 
cgit v0.10.2-6-g49f6