diff options
| -rw-r--r-- | Swift/Controllers/Chat/ChatController.cpp | 5 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatController.h | 4 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.cpp | 4 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.h | 2 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatsManager.cpp | 56 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatsManager.h | 4 | ||||
| -rw-r--r-- | Swift/Controllers/UIInterfaces/ChatListWindow.h | 7 | ||||
| -rw-r--r-- | Swift/Controllers/UIInterfaces/ChatWindow.h | 1 | ||||
| -rw-r--r-- | Swift/Controllers/UnitTest/MockChatWindow.h | 1 | ||||
| -rw-r--r-- | Swift/QtUI/QtChatWindow.cpp | 4 | ||||
| -rw-r--r-- | Swift/QtUI/QtChatWindow.h | 1 | 
11 files changed, 70 insertions, 19 deletions
| diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index 9df7708..9b65c9f 100644 --- a/Swift/Controllers/Chat/ChatController.cpp +++ b/Swift/Controllers/Chat/ChatController.cpp @@ -95,6 +95,7 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ  	chatWindow_->onBlockUserRequest.connect(boost::bind(&ChatController::handleBlockUserRequest, this));  	chatWindow_->onUnblockUserRequest.connect(boost::bind(&ChatController::handleUnblockUserRequest, this));  	chatWindow_->onInviteToChat.connect(boost::bind(&ChatController::handleInviteToChat, this, _1)); +	chatWindow_->onClosed.connect(boost::bind(&ChatController::handleWindowClosed, this));  	handleBareJIDCapsChanged(toJID_);  	settings_->onSettingChanged.connect(boost::bind(&ChatController::handleSettingChanged, this, _1)); @@ -306,6 +307,10 @@ void ChatController::handleInviteToChat(const std::vector<JID>& droppedJIDs) {  	eventStream_->send(event);  } +void ChatController::handleWindowClosed() { +	onWindowClosed(); +} +  void ChatController::handleUIEvent(boost::shared_ptr<UIEvent> event) {  	boost::shared_ptr<InviteToMUCUIEvent> inviteEvent = boost::dynamic_pointer_cast<InviteToMUCUIEvent>(event);  	if (inviteEvent && inviteEvent->getRoom() == toJID_.toBare()) { diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h index 8b1bb9a..2e92be7 100644 --- a/Swift/Controllers/Chat/ChatController.h +++ b/Swift/Controllers/Chat/ChatController.h @@ -79,8 +79,8 @@ namespace Swift {  			void handleUnblockUserRequest();  			void handleInviteToChat(const std::vector<JID>& droppedJIDs); -			void handleInviteToMUCWindowDismissed(); -			void handleInviteToMUCWindowCompleted(); + +			void handleWindowClosed();  			void handleUIEvent(boost::shared_ptr<UIEvent> event); diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index 5363e0c..24341e6 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -197,6 +197,10 @@ void ChatControllerBase::activateChatWindow() {  	chatWindow_->activate();  } +bool ChatControllerBase::hasOpenWindow() const { +	return chatWindow_ && chatWindow_->isVisible(); +} +  std::string ChatControllerBase::addMessage(const std::string& message, const std::string& senderName, bool senderIsSelf, const boost::shared_ptr<SecurityLabel> label, const boost::filesystem::path& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) {  	if (boost::starts_with(message, "/me ")) {  		return chatWindow_->addAction(chatMessageParser_->parseMessageBody(String::getSplittedAtFirst(message, ' ').second), senderName, senderIsSelf, label, pathToString(avatarPath), time, highlight); diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h index cf0a4d2..a0b848b 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.h +++ b/Swift/Controllers/Chat/ChatControllerBase.h @@ -52,6 +52,7 @@ namespace Swift {  			virtual ~ChatControllerBase();  			void showChatWindow();  			void activateChatWindow(); +			bool hasOpenWindow() const;  			virtual void setAvailableServerFeatures(boost::shared_ptr<DiscoInfo> info);  			void handleIncomingMessage(boost::shared_ptr<MessageEvent> message);  			std::string addMessage(const std::string& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const boost::filesystem::path& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight); @@ -62,6 +63,7 @@ namespace Swift {  			/** Used for determining when something is recent.*/  			boost::signal<void (const std::string& /*activity*/)> onActivity;  			boost::signal<void ()> onUnreadCountChanged; +			boost::signal<void ()> onWindowClosed;  			int getUnreadCount();  			const JID& getToJID() {return toJID_;}  			void handleCapsChanged(const JID& jid); diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index 8a077d1..3db1327 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -224,6 +224,15 @@ void ChatsManager::saveRecents() {  		}  	} +	class RemoveRecent { +	public: +		static bool ifPrivateMessage(const ChatListWindow::Chat& chat) { +			return chat.isPrivateMessage; +		} +	}; + +	recentsLimited.erase(std::remove_if(recentsLimited.begin(), recentsLimited.end(), RemoveRecent::ifPrivateMessage), recentsLimited.end()); +  	oa << recentsLimited;  	std::string serializedStr = Base64::encode(createByteArray(serializeStream.str()));  	profileSettings_->storeString(RECENT_CHATS, serializedStr); @@ -310,7 +319,7 @@ void ChatsManager::loadRecents() {  			StatusShow::Type type = StatusShow::None;  			boost::filesystem::path path; -			ChatListWindow::Chat chat(jid, nickResolver_->jidToNick(jid), activity, 0, type, path, isMUC, nick); +			ChatListWindow::Chat chat(jid, nickResolver_->jidToNick(jid), activity, 0, type, path, isMUC, false, nick);  			chat = updateChatStatusAndAvatarHelper(chat);  			prependRecent(chat);  		} @@ -368,7 +377,7 @@ void ChatsManager::handleMUCBookmarkRemoved(const MUCBookmark& bookmark) {  	chatListWindow_->removeMUCBookmark(bookmark);  } -ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const std::string& activity) { +ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const std::string& activity, bool privateMessage) {  	int unreadCount = 0;  	if (mucRegistry_->isMUC(jid)) {  		MUCController* controller = mucControllers_[jid.toBare()]; @@ -387,14 +396,14 @@ ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const  			}  			if (controller->isImpromptu()) { -				ChatListWindow::Chat chat = ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, boost::filesystem::path(), true, nick, password); +				ChatListWindow::Chat chat = ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, boost::filesystem::path(), true, privateMessage, nick, password);  				typedef std::pair<std::string, JID> StringJIDPair;  				std::map<std::string, JID> participants = controller->getParticipantJIDs();  				chat.impromptuJIDs = participants;  				return chat;  			}  		} -		return ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, boost::filesystem::path(), true, nick, password); +		return ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, boost::filesystem::path(), true, privateMessage, nick, password);  	} else {  		ChatController* controller = getChatControllerIfExists(jid, false);  		if (controller) { @@ -404,22 +413,24 @@ ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const  		Presence::ref presence = presenceOracle_->getHighestPriorityPresence(bareishJID);  		StatusShow::Type type = presence ? presence->getShow() : StatusShow::None;  		boost::filesystem::path avatarPath = avatarManager_ ? avatarManager_->getAvatarPath(bareishJID) : boost::filesystem::path(); -		return ChatListWindow::Chat(bareishJID, nickResolver_->jidToNick(bareishJID), activity, unreadCount, type, avatarPath, false); +		return ChatListWindow::Chat(bareishJID, nickResolver_->jidToNick(bareishJID), activity, unreadCount, type, avatarPath, false, privateMessage);  	}  }  void ChatsManager::handleChatActivity(const JID& jid, const std::string& activity, bool isMUC) { -	if (mucRegistry_->isMUC(jid.toBare()) && !isMUC) { -		/* Don't include PMs in MUC rooms.*/ -		return; -	} -	ChatListWindow::Chat chat = createChatListChatItem(jid, activity); +	const bool privateMessage = mucRegistry_->isMUC(jid.toBare()) && !isMUC; +	ChatListWindow::Chat chat = createChatListChatItem(jid, activity, privateMessage);  	/* FIXME: handle nick changes */  	appendRecent(chat);  	handleUnreadCountChanged(NULL);  	saveRecents();  } +void ChatsManager::handleChatClosed(const JID& /*jid*/) { +	cleanupPrivateMessageRecents(); +	chatListWindow_->setRecents(recentChats_); +} +  void ChatsManager::handleUnreadCountChanged(ChatControllerBase* controller) {  	int unreadTotal = 0;  	bool controllerIsMUC = dynamic_cast<MUCController*>(controller); @@ -454,6 +465,24 @@ boost::optional<ChatListWindow::Chat> ChatsManager::removeExistingChat(const Cha  	}  } +void ChatsManager::cleanupPrivateMessageRecents() { +	/* if we leave a MUC and close a PM, remove it's recent chat entry */ +	const std::list<ChatListWindow::Chat> chats = recentChats_; +	foreach (const ChatListWindow::Chat& chat, chats) { +		if (chat.isPrivateMessage) { +			typedef std::map<JID, MUCController*> ControllerMap; +			ControllerMap::iterator muc = mucControllers_.find(chat.jid.toBare()); +			if (muc == mucControllers_.end() || !muc->second->isJoined()) { +				ChatController* chatController = getChatControllerIfExists(chat.jid); +				if (!chatController || !chatController->hasOpenWindow()) { +					removeExistingChat(chat); +					break; +				} +			} +		} +	} +} +  void ChatsManager::appendRecent(const ChatListWindow::Chat& chat) {  	boost::optional<ChatListWindow::Chat> oldChat = removeExistingChat(chat);  	ChatListWindow::Chat mergedChat = chat; @@ -479,15 +508,15 @@ void ChatsManager::handleUserLeftMUC(MUCController* mucController) {  			foreach (ChatListWindow::Chat& chat, recentChats_) {  				if (chat.isMUC && chat.jid == (*it).first) {  					chat.statusType = StatusShow::None; -					chatListWindow_->setRecents(recentChats_); -					break;  				}  			}  			mucControllers_.erase(it);  			delete mucController; -			return; +			break;  		}  	} +	cleanupPrivateMessageRecents(); +	chatListWindow_->setRecents(recentChats_);  }  void ChatsManager::handleSettingChanged(const std::string& settingPath) { @@ -701,6 +730,7 @@ ChatController* ChatsManager::createNewChatController(const JID& contact) {  	chatControllers_[contact] = controller;  	controller->setAvailableServerFeatures(serverDiscoInfo_);  	controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, contact, _1, false)); +	controller->onWindowClosed.connect(boost::bind(&ChatsManager::handleChatClosed, this, contact));  	controller->onUnreadCountChanged.connect(boost::bind(&ChatsManager::handleUnreadCountChanged, this, controller));  	controller->onConvertToMUC.connect(boost::bind(&ChatsManager::handleTransformChatToMUC, this, controller, _1, _2, _3));  	updatePresenceReceivingStateOnChatController(contact); diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h index 41435d9..179f536 100644 --- a/Swift/Controllers/Chat/ChatsManager.h +++ b/Swift/Controllers/Chat/ChatsManager.h @@ -89,7 +89,7 @@ namespace Swift {  			};  		private: -			ChatListWindow::Chat createChatListChatItem(const JID& jid, const std::string& activity); +			ChatListWindow::Chat createChatListChatItem(const JID& jid, const std::string& activity, bool privateMessage);  			void handleChatRequest(const std::string& contact);  			void finalizeImpromptuJoin(MUC::ref muc, const std::vector<JID>& jidsToInvite, const std::string& reason, const boost::optional<JID>& reuseChatJID = boost::optional<JID>());  			MUC::ref handleJoinMUCRequest(const JID& muc, const boost::optional<std::string>& password, const boost::optional<std::string>& nick, bool addAutoJoin, bool createAsReservedIfNew, bool isImpromptu, ChatWindow* reuseChatwindow = 0); @@ -103,10 +103,12 @@ namespace Swift {  			void handleUserLeftMUC(MUCController* mucController);  			void handleBookmarksReady();  			void handleChatActivity(const JID& jid, const std::string& activity, bool isMUC); +			void handleChatClosed(const JID& jid);  			void handleNewFileTransferController(FileTransferController*);  			void handleWhiteboardSessionRequest(const JID& contact, bool senderIsSelf);  			void handleWhiteboardStateChange(const JID& contact, const ChatWindow::WhiteboardSessionState state);  			boost::optional<ChatListWindow::Chat> removeExistingChat(const ChatListWindow::Chat& chat); +			void cleanupPrivateMessageRecents();  			void appendRecent(const ChatListWindow::Chat& chat);  			void prependRecent(const ChatListWindow::Chat& chat);  			void setupBookmarks(); diff --git a/Swift/Controllers/UIInterfaces/ChatListWindow.h b/Swift/Controllers/UIInterfaces/ChatListWindow.h index 38d8c3e..f7eb151 100644 --- a/Swift/Controllers/UIInterfaces/ChatListWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatListWindow.h @@ -21,9 +21,9 @@ namespace Swift {  		public:  			class Chat {  				public: -					Chat() : statusType(StatusShow::None), isMUC(false), unreadCount(0) {} -					Chat(const JID& jid, const std::string& chatName, const std::string& activity, int unreadCount, StatusShow::Type statusType, const boost::filesystem::path& avatarPath, bool isMUC, const std::string& nick = "", const boost::optional<std::string> password = boost::optional<std::string>()) -					: jid(jid), chatName(chatName), activity(activity), statusType(statusType), isMUC(isMUC), nick(nick), password(password), unreadCount(unreadCount), avatarPath(avatarPath) {} +					Chat() : statusType(StatusShow::None), isMUC(false), unreadCount(0), isPrivateMessage(false) {} +					Chat(const JID& jid, const std::string& chatName, const std::string& activity, int unreadCount, StatusShow::Type statusType, const boost::filesystem::path& avatarPath, bool isMUC, bool isPrivateMessage = false, const std::string& nick = "", const boost::optional<std::string> password = boost::optional<std::string>()) +					: jid(jid), chatName(chatName), activity(activity), statusType(statusType), isMUC(isMUC), nick(nick), password(password), unreadCount(unreadCount), avatarPath(avatarPath), isPrivateMessage(isPrivateMessage) {}  					/** Assume that nicks and other transient features aren't important for equality */  					bool operator==(const Chat& other) const {  						if (impromptuJIDs.empty()) { @@ -77,6 +77,7 @@ namespace Swift {  					int unreadCount;  					boost::filesystem::path avatarPath;  					std::map<std::string, JID> impromptuJIDs; +					bool isPrivateMessage;  			};  			virtual ~ChatListWindow(); diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index bf4744b..81d26c8 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.h @@ -130,6 +130,7 @@ namespace Swift {  			virtual void setContactChatState(ChatState::ChatStateType state) = 0;  			virtual void setName(const std::string& name) = 0;  			virtual void show() = 0; +			virtual bool isVisible() const = 0;  			virtual void activate() = 0;  			virtual void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels) = 0;  			virtual void setSecurityLabelsEnabled(bool enabled) = 0; diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h index 823ea3a..5e6606b 100644 --- a/Swift/Controllers/UnitTest/MockChatWindow.h +++ b/Swift/Controllers/UnitTest/MockChatWindow.h @@ -41,6 +41,7 @@ namespace Swift {  			virtual void setContactChatState(ChatState::ChatStateType /*state*/) {}  			virtual void setName(const std::string& name) {name_ = name;}  			virtual void show() {} +			virtual bool isVisible() const { return true; }  			virtual void activate() {}  			virtual void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels) {labels_ = labels;}  			virtual void setSecurityLabelsEnabled(bool enabled) {labelsEnabled_ = enabled;} diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 74ff109..47eeac0 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -525,6 +525,10 @@ void QtChatWindow::show() {  	emit windowOpening();  } +bool QtChatWindow::isVisible() const { +	return QWidget::isVisible(); +} +  void QtChatWindow::activate() {  	if (isWindow()) {  		QWidget::show(); diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h index b8e3c6a..b3a3f5e 100644 --- a/Swift/QtUI/QtChatWindow.h +++ b/Swift/QtUI/QtChatWindow.h @@ -97,6 +97,7 @@ namespace Swift {  			void setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state);  			void show(); +			bool isVisible() const;  			void activate();  			void setUnreadMessageCount(int count);  			void convertToMUC(MUCType mucType); | 
 Swift
 Swift