diff options
| author | Kevin Smith <git@kismith.co.uk> | 2010-02-16 09:05:37 (GMT) | 
|---|---|---|
| committer | Kevin Smith <git@kismith.co.uk> | 2010-02-17 08:05:08 (GMT) | 
| commit | 5a334fd9b676564a8915baad312d92bd86358eec (patch) | |
| tree | aaecbbccd9cddcb843c126b8c022f1d1e667efde | |
| parent | 231c2cb6d00061e70860626467107f4c63f359a0 (diff) | |
| download | swift-5a334fd9b676564a8915baad312d92bd86358eec.zip swift-5a334fd9b676564a8915baad312d92bd86358eec.tar.bz2 | |
Preliminary Chat State Notifications support.
Only covers Active and Composing (Which is very possibly all we care about).
28 files changed, 311 insertions, 21 deletions
| diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index e4031f2..8d63d99 100644 --- a/Swift/Controllers/Chat/ChatController.cpp +++ b/Swift/Controllers/Chat/ChatController.cpp @@ -3,6 +3,9 @@  #include <boost/bind.hpp>  #include "Swiften/Avatars/AvatarManager.h" +#include "Swiften/Chat/ChatStateNotifier.h" +#include "Swiften/Chat/ChatStateMessageSender.h" +#include "Swiften/Chat/ChatStateTracker.h"  #include "Swift/Controllers/UIInterfaces/ChatWindow.h"  #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"  #include "Swift/Controllers/NickResolver.h" @@ -14,9 +17,20 @@ namespace Swift {   */  ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager)   : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager) { +	chatStateNotifier_ = new ChatStateNotifier(); +	chatStateMessageSender_ = new ChatStateMessageSender(chatStateNotifier_, stanzaChannel, contact); +	chatStateTracker_ = new ChatStateTracker();  	nickResolver_ = nickResolver;  	presenceOracle_->onPresenceChange.connect(boost::bind(&ChatController::handlePresenceChange, this, _1, _2)); +	chatStateTracker_->onChatStateChange.connect(boost::bind(&ChatWindow::setContactChatState, chatWindow_, _1));  	chatWindow_->setName(nickResolver_->jidToNick(toJID_)); +	chatWindow_->onUserTyping.connect(boost::bind(&ChatStateNotifier::setUserIsTyping, chatStateNotifier_)); +	chatWindow_->onUserCancelsTyping.connect(boost::bind(&ChatStateNotifier::userCancelledNewMessage, chatStateNotifier_)); +} + +void ChatController::setToJID(const JID& jid) { +	chatStateMessageSender_->setContact(jid); +	ChatControllerBase::setToJID(jid);  }  bool ChatController::isIncomingMessageFromMe(boost::shared_ptr<Message>) { @@ -30,10 +44,19 @@ void ChatController::preHandleIncomingMessage(boost::shared_ptr<Message> message  			toJID_ = from;  		}  	} +	chatStateNotifier_->receivedMessageFromContact(message->getPayload<ChatState>()); +	chatStateTracker_->handleMessageReceived(message); +} + +void ChatController::preSendMessageRequest(boost::shared_ptr<Message> message) { +	if (chatStateNotifier_->contactShouldReceiveStates()) { +		message->addPayload(boost::shared_ptr<Payload>(new ChatState(ChatState::Active))); +	}  }  void ChatController::postSendMessage(const String& body) {  	addMessage(body, "me", true, labelsEnabled_ ? chatWindow_->getSelectedSecurityLabel() : boost::optional<SecurityLabel>(), String(avatarManager_->getAvatarPath(selfJID_).string())); +	chatStateNotifier_->userSentMessage();  }  String ChatController::senderDisplayNameFromMessage(const JID& from) { @@ -62,6 +85,7 @@ void ChatController::handlePresenceChange(boost::shared_ptr<Presence> newPresenc  	if (!(toJID_.isBare() && newPresence->getFrom().equals(toJID_, JID::WithoutResource)) && newPresence->getFrom() != toJID_) {  		return;  	} +	chatStateTracker_->handlePresenceChange(newPresence, previousPresence);  	String newStatusChangeString = getStatusChangeString(newPresence);  	if (!previousPresence || newStatusChangeString != getStatusChangeString(previousPresence)) {  		chatWindow_->addSystemMessage(newStatusChangeString); diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h index 58ea797..f2963fd 100644 --- a/Swift/Controllers/Chat/ChatController.h +++ b/Swift/Controllers/Chat/ChatController.h @@ -5,10 +5,14 @@  namespace Swift {  	class AvatarManager; +	class ChatStateNotifier; +	class ChatStateMessageSender; +	class ChatStateTracker;  	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*); +			virtual void setToJID(const JID& jid);  		private:  			void handlePresenceChange(boost::shared_ptr<Presence> newPresence, boost::shared_ptr<Presence> previousPresence); @@ -16,11 +20,15 @@ namespace Swift {  			bool isIncomingMessageFromMe(boost::shared_ptr<Message> message);  			void postSendMessage(const String &body);  			void preHandleIncomingMessage(boost::shared_ptr<Message> message); +			void preSendMessageRequest(boost::shared_ptr<Message>);  			String senderDisplayNameFromMessage(const JID& from);  		private:  			NickResolver* nickResolver_;  			JID contact_; +			ChatStateNotifier* chatStateNotifier_; +			ChatStateMessageSender* chatStateMessageSender_; +			ChatStateTracker* chatStateTracker_;  	};  }  #endif diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index 5f78795..6fe50d3 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -98,7 +98,9 @@ void ChatControllerBase::addMessage(const String& message, const String& senderN  }  void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent) { -	unreadMessages_.push_back(messageEvent); +	if (messageEvent->isReadable()) { +		unreadMessages_.push_back(messageEvent); +	}  	chatWindow_->setUnreadMessageCount(unreadMessages_.size());  	boost::shared_ptr<Message> message = messageEvent->getStanza(); @@ -109,6 +111,9 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m  		chatWindow_->addErrorMessage(errorMessage);  	}  	else { +		if (!messageEvent->isReadable()) { +			return; +		}  		showChatWindow();  		boost::shared_ptr<SecurityLabel> label = message->getPayload<SecurityLabel>();  		boost::optional<SecurityLabel> maybeLabel = label ? boost::optional<SecurityLabel>(*label) : boost::optional<SecurityLabel>(); diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h index abf0116..e0d6ac5 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.h +++ b/Swift/Controllers/Chat/ChatControllerBase.h @@ -32,7 +32,7 @@ namespace Swift {  			void handleIncomingMessage(boost::shared_ptr<MessageEvent> message);  			void addMessage(const String& message, const String& senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath);  			void setEnabled(bool enabled); -			void setToJID(const JID& jid) {toJID_ = jid;}; +			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); diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index 0efd3e1..9a72f1f 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -133,9 +133,9 @@ void ChatsManager::handleJoinMUCRequest(const JID &muc, const String &nick) {  void ChatsManager::handleIncomingMessage(boost::shared_ptr<Message> message) {  	JID jid = message->getFrom();  	boost::shared_ptr<MessageEvent> event(new MessageEvent(message)); -	if (!event->isReadable()) { -		return; -	} +	//if (!event->isReadable()) { +	//	return; +	//}  	// Try to deliver it to a MUC  	if (message->getType() == Message::Groupchat || message->getType() == Message::Error) { diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index 59c3152..5b38ba2 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.h @@ -8,6 +8,7 @@  #include "Swiften/Base/String.h"  #include "Swiften/Elements/SecurityLabel.h" +#include "Swiften/Elements/ChatState.h"  namespace Swift {  	class AvatarManager; @@ -23,6 +24,7 @@ namespace Swift {  			virtual void addSystemMessage(const String& message) = 0;  			virtual void addErrorMessage(const String& message) = 0; +			virtual void setContactChatState(ChatState::ChatStateType state) = 0;  			virtual void setName(const String& name) = 0;  			virtual void show() = 0;  			virtual void activate() = 0; @@ -38,6 +40,8 @@ namespace Swift {  			boost::signal<void ()> onClosed;  			boost::signal<void ()> onAllMessagesRead;  			boost::signal<void (const String&)> onSendMessageRequest; +			boost::signal<void ()> onUserTyping; +			boost::signal<void ()> onUserCancelsTyping;  	};  }  #endif diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h index dc744cd..b487f50 100644 --- a/Swift/Controllers/UnitTest/MockChatWindow.h +++ b/Swift/Controllers/UnitTest/MockChatWindow.h @@ -13,6 +13,7 @@ namespace Swift {  			virtual void addSystemMessage(const String& /*message*/) {};  			virtual void addErrorMessage(const String& /*message*/) {}; +			virtual void setContactChatState(ChatState::ChatStateType /*state*/) {};  			virtual void setName(const String& name) {name_ = name;};  			virtual void show() {};  			virtual void activate() {}; diff --git a/Swift/QtUI/QtChatTabs.cpp b/Swift/QtUI/QtChatTabs.cpp index 6e5c55d..53fa5ce 100644 --- a/Swift/QtUI/QtChatTabs.cpp +++ b/Swift/QtUI/QtChatTabs.cpp @@ -104,7 +104,13 @@ void QtChatTabs::handleTabTitleUpdated(QWidget* widget) {  		return;  	}  	tabs_->setTabText(index, widget->windowTitle()); -	tabs_->tabBar()->setTabTextColor(index, tabbable->isWidgetAlerting() ? QColor(255,0,0) : QColor(-1,-1,-1)); //invalid resets to default +	QColor tabTextColor; +	switch (tabbable->getWidgetAlertState()) { +	case QtTabbable::WaitingActivity : tabTextColor = QColor(255, 0, 0); break; +	case QtTabbable::ImpendingActivity : tabTextColor = QColor(0, 255, 0); break; +	default : tabTextColor = QColor(-1,-1,-1);//invalid resets to default +	} +	tabs_->tabBar()->setTabTextColor(index, tabTextColor);   	if (widget == tabs_->currentWidget()) {  		setWindowTitle(widget->windowTitle());  	} diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index e982b21..6765e8a 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -56,7 +56,11 @@ QtChatWindow::QtChatWindow(const QString &contact, QtTreeWidgetFactory *treeWidg  	input_->setAcceptRichText(false);  	layout->addWidget(input_); +	inputClearing_ = false; +	contactIsTyping_ = false; +  	connect(input_, SIGNAL(returnPressed()), this, SLOT(returnPressed())); +	connect(input_, SIGNAL(textChanged()), this, SLOT(handleInputChanged()));  	setFocusProxy(input_);  	connect(qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), this, SLOT(qAppFocusChanged(QWidget*, QWidget*))); @@ -134,8 +138,20 @@ void QtChatWindow::setUnreadMessageCount(int count) {  	updateTitleWithUnreadCount();  } -bool QtChatWindow::isWidgetAlerting() { -	return unreadCount_ > 0; +void QtChatWindow::setContactChatState(ChatState::ChatStateType state) { +	contactIsTyping_ = (state == ChatState::Composing); +	printf("Hay, composing %d, %d!\n", state, contactIsTyping_); +	emit titleUpdated(); +} + +QtTabbable::AlertType QtChatWindow::getWidgetAlertState() { +	if (contactIsTyping_) { +		return ImpendingActivity; +	}  +	if (unreadCount_ > 0) { +		return WaitingActivity; +	} +	return NoActivity;  }  void QtChatWindow::setName(const String& name) { @@ -205,7 +221,20 @@ void QtChatWindow::addSystemMessage(const String& message) {  void QtChatWindow::returnPressed() {  	onSendMessageRequest(Q2PSTRING(input_->toPlainText()));  	messageLog_->scrollToBottom(); +	inputClearing_ = true;  	input_->clear(); +	inputClearing_ = false; +} + +void QtChatWindow::handleInputChanged() { +	if (inputClearing_) { +		return; +	} +	if (input_->toPlainText().isEmpty()) { +		onUserCancelsTyping(); +	} else { +		onUserTyping(); +	}  }  void QtChatWindow::show() { diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h index e147fb8..bde91e1 100644 --- a/Swift/QtUI/QtChatWindow.h +++ b/Swift/QtUI/QtChatWindow.h @@ -35,7 +35,8 @@ namespace Swift {  			SecurityLabel getSelectedSecurityLabel();  			void setName(const String& name);  			void setInputEnabled(bool enabled); -			virtual bool isWidgetAlerting(); +			QtTabbable::AlertType getWidgetAlertState(); +			void setContactChatState(ChatState::ChatStateType state);  		protected slots:  			void qAppFocusChanged(QWidget* old, QWidget* now); @@ -45,11 +46,13 @@ namespace Swift {  			void showEvent(QShowEvent* event);  		private slots:  			void returnPressed(); +			void handleInputChanged();  		private:  			void updateTitleWithUnreadCount();  			int unreadCount_; +			bool contactIsTyping_;  			QString contact_;  			QtChatView *messageLog_;  			QtTextEdit* input_; @@ -59,6 +62,7 @@ namespace Swift {  			bool previousMessageWasSelf_;  			bool previousMessageWasSystem_;  			QString previousSenderName_; +			bool inputClearing_;  	};  } diff --git a/Swift/QtUI/QtTabbable.h b/Swift/QtUI/QtTabbable.h index be528ce..cce45db 100644 --- a/Swift/QtUI/QtTabbable.h +++ b/Swift/QtUI/QtTabbable.h @@ -7,9 +7,10 @@ namespace Swift {  	class QtTabbable : public QWidget {  		Q_OBJECT  		public: +			enum AlertType {NoActivity, WaitingActivity, ImpendingActivity};  			~QtTabbable();  			bool isWidgetSelected(); -			virtual bool isWidgetAlerting() {return false;}; +			virtual AlertType getWidgetAlertState() {return NoActivity;};  		protected:  			QtTabbable() : QWidget() {}; diff --git a/Swiften/Chat/ChatStateMessageSender.cpp b/Swiften/Chat/ChatStateMessageSender.cpp index d053cb5..ad1495f 100644 --- a/Swiften/Chat/ChatStateMessageSender.cpp +++ b/Swiften/Chat/ChatStateMessageSender.cpp @@ -1,5 +1,22 @@  #include "Swiften/Chat/ChatStateMessageSender.h" +#include <boost/bind.hpp> + +#include "Swiften/Client/StanzaChannel.h" +  namespace Swift { +ChatStateMessageSender::ChatStateMessageSender(ChatStateNotifier* notifier, StanzaChannel* stanzaChannel, const JID& contact) : contact_(contact) { +	notifier_ = notifier; +	stanzaChannel_ = stanzaChannel; +	notifier_->onChatStateChanged.connect(boost::bind(&ChatStateMessageSender::handleChatStateChanged, this, _1)); +} + +void ChatStateMessageSender::handleChatStateChanged(ChatState::ChatStateType state) { +	boost::shared_ptr<Message> message(new Message()); +	message->setTo(contact_); +	message->addPayload(boost::shared_ptr<Payload>(new ChatState(state))); +	stanzaChannel_->sendMessage(message); +} +  } diff --git a/Swiften/Chat/ChatStateMessageSender.h b/Swiften/Chat/ChatStateMessageSender.h index d27973d..aff0791 100644 --- a/Swiften/Chat/ChatStateMessageSender.h +++ b/Swiften/Chat/ChatStateMessageSender.h @@ -1,7 +1,20 @@  #pragma once +#include "Swiften/Chat/ChatStateNotifier.h" +#include "Swiften/Elements/ChatState.h" +#include "Swiften/JID/JID.h" +  namespace Swift { +	class StanzaChannel;  	class ChatStateMessageSender { -		 +		public: +			ChatStateMessageSender(ChatStateNotifier* notifier, StanzaChannel* stanzaChannel, const JID& contact); +			void setContact(const JID& contact) {contact_ = contact;}; + +		private: +			void handleChatStateChanged(ChatState::ChatStateType state); +			ChatStateNotifier* notifier_; +			StanzaChannel* stanzaChannel_; +			JID contact_;  	};  } diff --git a/Swiften/Chat/ChatStateNotifier.cpp b/Swiften/Chat/ChatStateNotifier.cpp index 432f708..7c6560f 100644 --- a/Swiften/Chat/ChatStateNotifier.cpp +++ b/Swiften/Chat/ChatStateNotifier.cpp @@ -16,7 +16,7 @@ void ChatStateNotifier::setContactHas85Caps(bool hasCaps) {  void ChatStateNotifier::setUserIsTyping() {  	if (contactShouldReceiveStates() && !userIsTyping_) {  		userIsTyping_ = true; -		onChatStateChanged(Composing); +		onChatStateChanged(ChatState::Composing);  	}  } @@ -27,7 +27,7 @@ void ChatStateNotifier::userSentMessage() {  void ChatStateNotifier::userCancelledNewMessage() {  	if (userIsTyping_) {  		userIsTyping_ = false; -		onChatStateChanged(Active); +		onChatStateChanged(ChatState::Active);  	}  } diff --git a/Swiften/Chat/ChatStateNotifier.h b/Swiften/Chat/ChatStateNotifier.h index 90228b7..0ef4255 100644 --- a/Swiften/Chat/ChatStateNotifier.h +++ b/Swiften/Chat/ChatStateNotifier.h @@ -3,10 +3,11 @@  #include <boost/signals.hpp>  #include <boost/shared_ptr.hpp> +#include "Swiften/Elements/ChatState.h" +  namespace Swift {  	class ChatStateNotifier {  		public: -			enum ChatState {Active, Composing, Paused, Inactive, Gone};  			ChatStateNotifier();  			void setContactHas85Caps(bool hasCaps);  			void setUserIsTyping(); @@ -15,7 +16,7 @@ namespace Swift {  			void receivedMessageFromContact(bool hasActiveElement);  			bool contactShouldReceiveStates(); -			boost::signal<void (ChatState)> onChatStateChanged; +			boost::signal<void (ChatState::ChatStateType)> onChatStateChanged;  		private:  			bool contactHas85Caps_;  			bool isInConversation_; diff --git a/Swiften/Chat/ChatStateTracker.cpp b/Swiften/Chat/ChatStateTracker.cpp index 553d2f4..94e01eb 100644 --- a/Swiften/Chat/ChatStateTracker.cpp +++ b/Swiften/Chat/ChatStateTracker.cpp @@ -1,5 +1,29 @@  #include "Swiften/Chat/ChatStateTracker.h"  namespace Swift { +ChatStateTracker::ChatStateTracker() { +	currentState_ = ChatState::Gone; +} + +void ChatStateTracker::handleMessageReceived(boost::shared_ptr<Message> message) { +	boost::shared_ptr<ChatState> statePayload = message->getPayload<ChatState>(); +	if (statePayload) { +		changeState(statePayload->getChatState());; +	} +} + +void ChatStateTracker::handlePresenceChange(boost::shared_ptr<Presence> newPresence, boost::shared_ptr<Presence>) { +	if (newPresence->getType() == Presence::Unavailable) { +		onChatStateChange(ChatState::Gone); +	} +} + +void ChatStateTracker::changeState(ChatState::ChatStateType state) { +	printf("Comparing state %d to old state %d\n", state, currentState_); +	if (state != currentState_) { +		currentState_ = state; +		onChatStateChange(state); +	} +}  } diff --git a/Swiften/Chat/ChatStateTracker.h b/Swiften/Chat/ChatStateTracker.h index 005c479..e612852 100644 --- a/Swiften/Chat/ChatStateTracker.h +++ b/Swiften/Chat/ChatStateTracker.h @@ -1,7 +1,21 @@  #pragma once +#include <boost/signal.hpp> +#include <boost/shared_ptr.hpp> + +#include "Swiften/Elements/Message.h" +#include "Swiften/Elements/Presence.h" +#include "Swiften/ELements/ChatState.h" +  namespace Swift {  	class ChatStateTracker { -		 +		public: +			ChatStateTracker(); +			void handleMessageReceived(boost::shared_ptr<Message> message); +			void handlePresenceChange(boost::shared_ptr<Presence> newPresence, boost::shared_ptr<Presence> oldPresence); +			boost::signal<void (ChatState::ChatStateType)> onChatStateChange; +		private: +			void changeState(ChatState::ChatStateType state); +			ChatState::ChatStateType currentState_;  	};  } diff --git a/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp index bacfc3a..44ec9d8 100644 --- a/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp +++ b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp @@ -18,15 +18,15 @@ public:  	int composingCallCount;  	int activeCallCount; -	ChatStateNotifier::ChatState currentState; +	ChatState::ChatStateType currentState;  private: -	void handleChatStateChanged(ChatStateNotifier::ChatState newState) { +	void handleChatStateChanged(ChatState::ChatStateType newState) {  		switch (newState) { -			case ChatStateNotifier::Composing: +			case ChatState::Composing:  				composingCallCount++;  				break; -			case ChatStateNotifier::Active: +			case ChatState::Active:  				activeCallCount++;  				break;  			default: @@ -86,7 +86,7 @@ public:  		notifier_->userCancelledNewMessage();  		CPPUNIT_ASSERT_EQUAL(1, monitor_->composingCallCount);  		CPPUNIT_ASSERT_EQUAL(1, monitor_->activeCallCount); -		CPPUNIT_ASSERT_EQUAL(ChatStateNotifier::Active, monitor_->currentState); +		CPPUNIT_ASSERT_EQUAL(ChatState::Active, monitor_->currentState);  	} diff --git a/Swiften/Elements/ChatState.h b/Swiften/Elements/ChatState.h new file mode 100644 index 0000000..3378cc3 --- /dev/null +++ b/Swiften/Elements/ChatState.h @@ -0,0 +1,20 @@ +#pragma once + +#include "Swiften/Base/String.h" +#include "Swiften/Elements/Payload.h" + +namespace Swift { +	class ChatState : public Payload { +		public: +			enum ChatStateType {Active, Composing, Paused, Inactive, Gone}; +			ChatState(ChatStateType state = Active) { +				state_ = state; +			} + +			ChatStateType getChatState() { return state_; } +			void setChatState(ChatStateType state) {state_ = state;} + +		private: +			ChatStateType state_; +	}; +} diff --git a/Swiften/Parser/PayloadParsers/ChatStateParser.cpp b/Swiften/Parser/PayloadParsers/ChatStateParser.cpp new file mode 100644 index 0000000..52d860a --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ChatStateParser.cpp @@ -0,0 +1,35 @@ +#include "Swiften/Parser/PayloadParsers/ChatStateParser.h" + +namespace Swift { + +ChatStateParser::ChatStateParser() : level_(0) { +} + +void ChatStateParser::handleStartElement(const String& element, const String&, const AttributeMap&) { +	if (level_ == 0) { +		ChatState::ChatStateType state = ChatState::Active; +		if (element == "active") { +			state = ChatState::Active; +		} else if (element == "composing") { +			state = ChatState::Composing; +		} else if (element == "inactive") { +			state = ChatState::Inactive; +		} else if (element == "paused") { +			state = ChatState::Paused; +		} else if (element == "gone") { +			state = ChatState::Gone; +		} +		getPayloadInternal()->setChatState(state); +	} +	++level_; +} + +void ChatStateParser::handleEndElement(const String&, const String&) { +	--level_; +} + +void ChatStateParser::handleCharacterData(const String&) { + +} + +} diff --git a/Swiften/Parser/PayloadParsers/ChatStateParser.h b/Swiften/Parser/PayloadParsers/ChatStateParser.h new file mode 100644 index 0000000..cd212c0 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ChatStateParser.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Swiften/Elements/ChatState.h" +#include "Swiften/Parser/GenericPayloadParser.h" + +namespace Swift { +	class ChatStateParser : public GenericPayloadParser<ChatState> { +		public: +			ChatStateParser(); + +			virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes); +			virtual void handleEndElement(const String& element, const String&); +			virtual void handleCharacterData(const String& data); + +		private: +			int level_; +	}; +} diff --git a/Swiften/Parser/PayloadParsers/ChatStateParserFactory.h b/Swiften/Parser/PayloadParsers/ChatStateParserFactory.h new file mode 100644 index 0000000..1582d09 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ChatStateParserFactory.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Swiften/Parser/PayloadParserFactory.h" +#include "Swiften/Parser/PayloadParsers/ChatStateParser.h" + +namespace Swift { +	class PayloadParserFactoryCollection; + +	class ChatStateParserFactory : public PayloadParserFactory { +		public: +			ChatStateParserFactory() { +			} + +			virtual bool canParse(const String& element, const String& ns, const AttributeMap&) const { +				return ns == "http://jabber.org/protocol/chatstates" &&  +					(element == "active" || element == "composing"  +					 || element == "paused" || element == "inactive" || element == "gone"); +			} + +			virtual PayloadParser* createPayloadParser() { +				return new ChatStateParser(); +			} + +	}; +} diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp index eb4cda0..0857f64 100644 --- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp @@ -4,6 +4,7 @@  #include "Swiften/Parser/PayloadParserFactory.h"  #include "Swiften/Parser/PayloadParsers/ErrorParserFactory.h"  #include "Swiften/Parser/PayloadParsers/BodyParserFactory.h" +#include "Swiften/Parser/PayloadParsers/ChatStateParserFactory.h"  #include "Swiften/Parser/PayloadParsers/PriorityParserFactory.h"  #include "Swiften/Parser/PayloadParsers/ResourceBindParserFactory.h"  #include "Swiften/Parser/PayloadParsers/StartSessionParserFactory.h" @@ -41,6 +42,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {  	factories_.push_back(shared_ptr<PayloadParserFactory>(new VCardUpdateParserFactory()));  	factories_.push_back(shared_ptr<PayloadParserFactory>(new VCardParserFactory()));  	factories_.push_back(shared_ptr<PayloadParserFactory>(new PrivateStorageParserFactory(this))); +	factories_.push_back(shared_ptr<PayloadParserFactory>(new ChatStateParserFactory()));  	foreach(shared_ptr<PayloadParserFactory> factory, factories_) {  		addFactory(factory.get());  	} diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript index 1e1dcd8..7d93d8b 100644 --- a/Swiften/Parser/SConscript +++ b/Swiften/Parser/SConscript @@ -18,6 +18,7 @@ sources = [  		"PayloadParserFactory.cpp",  		"PayloadParserFactoryCollection.cpp",  		"PayloadParsers/BodyParser.cpp", +		"PayloadParsers/ChatStateParser.cpp",  		"PayloadParsers/DiscoInfoParser.cpp",  		"PayloadParsers/ErrorParser.cpp",  		"PayloadParsers/FullPayloadParserFactoryCollection.cpp", diff --git a/Swiften/SConscript b/Swiften/SConscript index e31818c..3f82bfe 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -55,6 +55,7 @@ sources = [  		"Serializer/PayloadSerializer.cpp",  		"Serializer/PayloadSerializerCollection.cpp",  		"Serializer/PayloadSerializers/CapsInfoSerializer.cpp", +		"Serializer/PayloadSerializers/ChatStateSerializer.cpp",  		"Serializer/PayloadSerializers/DiscoInfoSerializer.cpp",  		"Serializer/PayloadSerializers/ErrorSerializer.cpp",  		"Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp", diff --git a/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.cpp b/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.cpp new file mode 100644 index 0000000..0507092 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.cpp @@ -0,0 +1,22 @@ +#include "Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h" + +namespace Swift { + +ChatStateSerializer::ChatStateSerializer() : GenericPayloadSerializer<ChatState>() { +} + +String ChatStateSerializer::serializePayload(boost::shared_ptr<ChatState> chatState)  const { +	String result("<"); +	switch (chatState->getChatState()) { +		case ChatState::Active: result += "active"; break; +		case ChatState::Composing: result += "composing"; break; +		case ChatState::Paused: result += "paused"; break; +		case ChatState::Inactive: result += "inactive"; break; +		case ChatState::Gone: result += "gone"; break; +		default: result += "gone"; break; +	} +	result += " xmlns=\"http://jabber.org/protocol/chatstates\"/>"; +	return result; +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h b/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h new file mode 100644 index 0000000..e99b8b6 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Swiften/Serializer/GenericPayloadSerializer.h" +#include "Swiften/Elements/ChatState.h" + +namespace Swift { +	class ChatStateSerializer : public GenericPayloadSerializer<ChatState> { +		public: +			ChatStateSerializer(); + +			virtual String serializePayload(boost::shared_ptr<ChatState> error)  const; +	}; +} diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp index fc20018..accf6c6 100644 --- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp +++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp @@ -2,6 +2,7 @@  #include "Swiften/Base/foreach.h"  #include "Swiften/Serializer/PayloadSerializer.h"  #include "Swiften/Serializer/PayloadSerializers/BodySerializer.h" +#include "Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h"  #include "Swiften/Serializer/PayloadSerializers/PrioritySerializer.h"  #include "Swiften/Serializer/PayloadSerializers/ErrorSerializer.h"  #include "Swiften/Serializer/PayloadSerializers/RosterSerializer.h" @@ -25,6 +26,7 @@ namespace Swift {  FullPayloadSerializerCollection::FullPayloadSerializerCollection() {  	serializers_.push_back(new BodySerializer()); +	serializers_.push_back(new ChatStateSerializer());  	serializers_.push_back(new PrioritySerializer());  	serializers_.push_back(new ErrorSerializer());  	serializers_.push_back(new RosterSerializer()); | 
 Swift
 Swift