diff options
| -rw-r--r-- | Swift/Controllers/Chat/ChatController.cpp | 14 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatController.h | 2 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.cpp | 2 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.h | 4 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatsManager.cpp | 4 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/MUCController.cpp | 7 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/MUCController.h | 2 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp | 2 | ||||
| -rw-r--r-- | Swift/Controllers/HistoryController.cpp | 12 | ||||
| -rw-r--r-- | Swift/Controllers/HistoryController.h | 8 | ||||
| -rw-r--r-- | Swift/Controllers/HistoryViewController.cpp | 91 | ||||
| -rw-r--r-- | Swift/Controllers/HistoryViewController.h | 4 | ||||
| -rw-r--r-- | Swift/Controllers/UIInterfaces/HistoryWindow.h | 1 | ||||
| -rw-r--r-- | Swift/QtUI/QtHistoryWindow.cpp | 5 | ||||
| -rw-r--r-- | Swift/QtUI/QtHistoryWindow.h | 1 | ||||
| -rw-r--r-- | Swiften/History/HistoryManager.h | 4 | ||||
| -rw-r--r-- | Swiften/History/HistoryMessage.h | 18 | ||||
| -rw-r--r-- | Swiften/History/SQLiteHistoryManager.cpp | 58 | ||||
| -rw-r--r-- | Swiften/History/SQLiteHistoryManager.h | 4 | 
19 files changed, 149 insertions, 94 deletions
| diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index 632d760..f40f704 100644 --- a/Swift/Controllers/Chat/ChatController.cpp +++ b/Swift/Controllers/Chat/ChatController.cpp @@ -37,8 +37,8 @@ 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, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts, SettingsProvider* settings, HistoryController* historyController) -	: ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, timerFactory, entityCapsProvider, historyController), eventStream_(eventStream), userWantsReceipts_(userWantsReceipts), settings_(settings) { +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, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts, SettingsProvider* settings, HistoryController* historyController, MUCRegistry* mucRegistry) +	: ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry), eventStream_(eventStream), userWantsReceipts_(userWantsReceipts), settings_(settings) {  	isInMUC_ = isInMUC;  	lastWasPresence_ = false;  	chatStateNotifier_ = new ChatStateNotifier(stanzaChannel, contact, entityCapsProvider); @@ -354,8 +354,16 @@ boost::optional<boost::posix_time::ptime> ChatController::getMessageTimestamp(bo  }  void ChatController::logMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp, bool /* isIncoming */) { +	HistoryMessage::Type type; +	if (mucRegistry_->isMUC(fromJID.toBare()) || mucRegistry_->isMUC(toJID.toBare())) { +		type = HistoryMessage::PrivateMessage; +	} +	else { +		type = HistoryMessage::Chat; +	} +  	if (historyController_) { -		historyController_->addMessage(message, fromJID, toJID, false, timeStamp); +		historyController_->addMessage(message, fromJID, toJID, type, timeStamp);  	}  } diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h index daf687d..a873ae9 100644 --- a/Swift/Controllers/Chat/ChatController.h +++ b/Swift/Controllers/Chat/ChatController.h @@ -25,7 +25,7 @@ namespace Swift {  	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, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts, SettingsProvider* settings, HistoryController* historyController); +			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, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts, SettingsProvider* settings, HistoryController* historyController, MUCRegistry* mucRegistry);  			virtual ~ChatController();  			virtual void setToJID(const JID& jid);  			virtual void setOnline(bool online); diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index 115c258..ad6aabe 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -33,7 +33,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, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, HistoryController* historyController) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency), eventController_(eventController), timerFactory_(timerFactory), entityCapsProvider_(entityCapsProvider), historyController_(historyController) { +ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency), eventController_(eventController), timerFactory_(timerFactory), entityCapsProvider_(entityCapsProvider), historyController_(historyController), mucRegistry_(mucRegistry) {  	chatWindow_ = chatWindowFactory_->createChatWindow(toJID, eventStream);  	chatWindow_->onAllMessagesRead.connect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this));  	chatWindow_->onSendMessageRequest.connect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1, _2)); diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h index 762a1a3..b618d3c 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.h +++ b/Swift/Controllers/Chat/ChatControllerBase.h @@ -28,6 +28,7 @@  #include "Swiften/Queries/IQRouter.h"  #include "Swiften/Base/IDGenerator.h"  #include <Swift/Controllers/HistoryController.h> +#include <Swiften/MUC/MUCRegistry.h>  namespace Swift {  	class IQRouter; @@ -59,7 +60,7 @@ namespace Swift {  			void handleCapsChanged(const JID& jid);  		protected: -			ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, HistoryController* historyController); +			ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry);  			/**  			 * Pass the Message appended, and the stanza used to send it. @@ -113,5 +114,6 @@ namespace Swift {  			TimerFactory* timerFactory_;  			EntityCapsProvider* entityCapsProvider_;  			HistoryController* historyController_; +			MUCRegistry* mucRegistry_;  	};  } diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index 3817a41..6b51df6 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -514,7 +514,7 @@ ChatController* ChatsManager::getChatControllerOrFindAnother(const JID &contact)  ChatController* ChatsManager::createNewChatController(const JID& contact) {  	assert(chatControllers_.find(contact) == chatControllers_.end()); -	ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, eventController_, timerFactory_, entityCapsProvider_, userWantsReceipts_, settings_, historyController_); +	ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, eventController_, timerFactory_, entityCapsProvider_, userWantsReceipts_, settings_, historyController_, mucRegistry_);  	chatControllers_[contact] = controller;  	controller->setAvailableServerFeatures(serverDiscoInfo_);  	controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, contact, _1, false)); @@ -587,7 +587,7 @@ void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional  		if (createAsReservedIfNew) {  			muc->setCreateAsReservedIfNew();  		} -		MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_, historyController_); +		MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_, historyController_, mucRegistry_);  		mucControllers_[mucJID] = controller;  		controller->setAvailableServerFeatures(serverDiscoInfo_);  		controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller)); diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index f86c726..bdc9b20 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -60,8 +60,9 @@ MUCController::MUCController (  		EventController* eventController,  		EntityCapsProvider* entityCapsProvider,  		XMPPRoster* roster, -		HistoryController* historyController) : -			ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider, historyController), muc_(muc), nick_(nick), desiredNick_(nick), password_(password) { +		HistoryController* historyController, +		MUCRegistry* mucRegistry) : +			ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry), muc_(muc), nick_(nick), desiredNick_(nick), password_(password) {  	parting_ = true;  	joined_ = false;  	lastWasPresence_ = false; @@ -783,7 +784,7 @@ void MUCController::handleAffiliationListReceived(MUCOccupant::Affiliation affil  void MUCController::logMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp, bool isIncoming) {  	// log only incoming messages  	if (isIncoming && historyController_) { -		historyController_->addMessage(message, fromJID, toJID, true, timeStamp); +		historyController_->addMessage(message, fromJID, toJID, HistoryMessage::Groupchat, timeStamp);  	}  } diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h index 41393cd..0c6cfa4 100644 --- a/Swift/Controllers/Chat/MUCController.h +++ b/Swift/Controllers/Chat/MUCController.h @@ -44,7 +44,7 @@ namespace Swift {  	class MUCController : public ChatControllerBase {  		public: -			MUCController(const JID& self, MUC::ref muc, const boost::optional<std::string>& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, XMPPRoster* roster, HistoryController* historyController); +			MUCController(const JID& self, MUC::ref muc, const boost::optional<std::string>& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, XMPPRoster* roster, HistoryController* historyController, MUCRegistry* mucRegistry);  			~MUCController();  			boost::signal<void ()> onUserLeft;  			boost::signal<void ()> onUserJoined; diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp index 090899b..3615bed 100644 --- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp @@ -63,7 +63,7 @@ public:  		entityCapsProvider_ = new DummyEntityCapsProvider();  		muc_ = boost::make_shared<MUC>(stanzaChannel_, iqRouter_, directedPresenceSender_, mucJID_, mucRegistry_);  		mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(muc_->getJID(), uiEventStream_).Return(window_); -		controller_ = new MUCController (self_, muc_, boost::optional<std::string>(), nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_, entityCapsProvider_, NULL, NULL); +		controller_ = new MUCController (self_, muc_, boost::optional<std::string>(), nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_, entityCapsProvider_, NULL, NULL, mucRegistry_);  	};  	void tearDown() { diff --git a/Swift/Controllers/HistoryController.cpp b/Swift/Controllers/HistoryController.cpp index 5bd4ffa..fe54e79 100644 --- a/Swift/Controllers/HistoryController.cpp +++ b/Swift/Controllers/HistoryController.cpp @@ -19,18 +19,18 @@ HistoryController::~HistoryController() {  	delete localHistory_;  } -void HistoryController::addMessage(const std::string& message, const JID& fromJID, const JID& toJID, bool isGroupChat, const boost::posix_time::ptime& timeStamp) { -	HistoryMessage historyMessage(message, fromJID, toJID, isGroupChat, timeStamp); +void HistoryController::addMessage(const std::string& message, const JID& fromJID, const JID& toJID, HistoryMessage::Type type, const boost::posix_time::ptime& timeStamp) { +	HistoryMessage historyMessage(message, fromJID, toJID, type, timeStamp);  	localHistory_->addMessage(historyMessage);  	onNewMessage(historyMessage);  } -std::vector<HistoryMessage> HistoryController::getMessages(const JID& selfJID, const JID& contactJID, bool isGroupChat) const { -	return localHistory_->getMessages(selfJID, contactJID, isGroupChat); +std::vector<HistoryMessage> HistoryController::getMessages(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type) const { +	return localHistory_->getMessages(selfJID, contactJID, type);  } -void HistoryController::getAllContacts(const JID& selfJID, std::set<JID>& mucs, std::set<JID>& contacts) const { -	return localHistory_->getAllContacts(selfJID, mucs, contacts); +std::set<JID> HistoryController::getContacts(const JID& selfJID, HistoryMessage::Type type) const { +	return localHistory_->getContacts(selfJID, type);  }  } diff --git a/Swift/Controllers/HistoryController.h b/Swift/Controllers/HistoryController.h index babda8a..c08e112 100644 --- a/Swift/Controllers/HistoryController.h +++ b/Swift/Controllers/HistoryController.h @@ -11,10 +11,10 @@  #include <vector>  #include <set>  #include <Swiften/Base/boost_bsignals.h> +#include <Swiften/History/HistoryMessage.h>  namespace Swift {  	class HistoryManager; -	class HistoryMessage;  	class JID;  	class HistoryController { @@ -22,9 +22,9 @@ namespace Swift {  			HistoryController();  			~HistoryController(); -			void addMessage(const std::string& message, const JID& fromJID, const JID& toJID, bool isGroupChat, const boost::posix_time::ptime& timeStamp); -			std::vector<HistoryMessage> getMessages(const JID& selfJID, const JID& contactJID, bool isGroupChat) const; -			void getAllContacts(const JID& selfJID, std::set<JID>& mucs, std::set<JID>& contacts) const; +			void addMessage(const std::string& message, const JID& fromJID, const JID& toJID, HistoryMessage::Type type, const boost::posix_time::ptime& timeStamp); +			std::vector<HistoryMessage> getMessages(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type) const; +			std::set<JID> getContacts(const JID& selfJID, HistoryMessage::Type type) const;  			boost::signal<void (const HistoryMessage&)> onNewMessage; diff --git a/Swift/Controllers/HistoryViewController.cpp b/Swift/Controllers/HistoryViewController.cpp index a67f6cd..18e27bd 100644 --- a/Swift/Controllers/HistoryViewController.cpp +++ b/Swift/Controllers/HistoryViewController.cpp @@ -48,6 +48,7 @@ HistoryViewController::~HistoryViewController() {  }  void HistoryViewController::handleUIEvent(boost::shared_ptr<UIEvent> rawEvent) { +	// TODO: add new nick manager  	boost::shared_ptr<RequestHistoryUIEvent> event = boost::dynamic_pointer_cast<RequestHistoryUIEvent>(rawEvent);  	if (event != NULL) {  		if (historyWindow_ == NULL) { @@ -56,13 +57,31 @@ void HistoryViewController::handleUIEvent(boost::shared_ptr<UIEvent> rawEvent) {  			historyWindow_->setRosterModel(roster_); -			historyController_->getAllContacts(selfJID_, rooms_, contacts_); +			// MUCs +			std::set<JID> rooms = historyController_->getContacts(selfJID_, HistoryMessage::Groupchat); +			foreach (const JID& room, rooms) { +				if ( !rooms_.count(room)) { +					roster_->addContact(room, room, nickResolver_->jidToNick(room), "MUC", avatarManager_->getAvatarPath(room).string()); +					rooms_.insert(room); +				} +			} -			foreach (const JID& muc, rooms_) { -				roster_->addContact(muc, muc, nickResolver_->jidToNick(muc), "MUC", byteArrayToString(avatarManager_->getAvatar(muc))); +			// Contacts +			std::set<JID> contacts = historyController_->getContacts(selfJID_, HistoryMessage::Chat); +			foreach (const JID& contact, contacts) { +				if (!contacts_.count(contact)) { +					roster_->addContact(contact, contact, nickResolver_->jidToNick(contact), "Contacts", avatarManager_->getAvatarPath(contact).string()); +					contacts_.insert(contact); +				}  			} -			foreach (const JID& contact, contacts_) { -				roster_->addContact(contact, contact, nickResolver_->jidToNick(contact), "Contacts", byteArrayToString(avatarManager_->getAvatar(contact))); + +			// MUC contacts +			std::set<JID> roomPrivateContacts = historyController_->getContacts(selfJID_, HistoryMessage::PrivateMessage); +			foreach (const JID& contact, roomPrivateContacts) { +				if ( !roomPrivateContacts_.count(contact)) { +					roster_->addContact(contact, contact, nickResolver_->jidToNick(contact), "Contacts", avatarManager_->getAvatarPath(contact).string()); +					roomPrivateContacts_.insert(contact); +				}  			}  		} @@ -72,38 +91,68 @@ void HistoryViewController::handleUIEvent(boost::shared_ptr<UIEvent> rawEvent) {  void HistoryViewController::handleSelectedContactChanged(RosterItem* newContact) {  	// FIXME: signal is triggerd twice. -	selectedItem_ = dynamic_cast<ContactRosterItem*>(newContact); +	ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(newContact); -	if (newContact == NULL) { +	if (contact && selectedItem_ != contact) { +		selectedItem_ = contact; +		historyWindow_->resetConversationView(); +	} +	else {  		return;  	} -	ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(newContact);  	JID contactJID = contact->getJID(); -	bool isRoom = rooms_.count(contactJID); -	std::vector<HistoryMessage> messages = historyController_->getMessages(selfJID_, contactJID, isRoom); +	std::vector<HistoryMessage> messages; +	if (roomPrivateContacts_.count(contactJID)) { +		messages = historyController_->getMessages(selfJID_, contactJID, HistoryMessage::PrivateMessage); +	} +	else if (contacts_.count(contactJID)) { +		messages = historyController_->getMessages(selfJID_, contactJID, HistoryMessage::Chat); +	} +	else { +		messages = historyController_->getMessages(selfJID_, contactJID, HistoryMessage::Groupchat); +	} +  	foreach (const HistoryMessage& message, messages) { -		bool senderIsSelf = message.getFromJID() == selfJID_; -		std::string avatarPath = byteArrayToString(avatarManager_->getAvatar(message.getFromJID())); -		historyWindow_->addMessage(message.getMessage(), nickResolver_->jidToNick(message.getFromJID()), senderIsSelf, avatarPath, message.getTime()); +		addNewMessage(message);  	}  }  void HistoryViewController::handleNewMessage(const HistoryMessage& message) {  	JID contactJID = message.getFromJID().toBare() == selfJID_ ? message.getToJID() : message.getFromJID(); -	if (selectedItem_ && selectedItem_->getJID().toBare() == contactJID) { -		bool senderIsSelf = message.getFromJID().toBare() == selfJID_; -		std::string avatarPath = byteArrayToString(avatarManager_->getAvatar(message.getFromJID())); -		historyWindow_->addMessage(message.getMessage(), nickResolver_->jidToNick(message.getFromJID()), senderIsSelf, avatarPath, message.getTime()); +	JID displayJID; +	if (message.getType() == HistoryMessage::PrivateMessage) { +		displayJID = contactJID; +	} +	else { +		displayJID = contactJID.toBare(); +	} + +	// check current conversation +	if (selectedItem_ && selectedItem_->getJID() == displayJID) { +		addNewMessage(message);  	} -	else if (!rooms_.count(contactJID.toBare()) && message.isGroupChat()) { -		roster_->addContact(contactJID.toBare(), contactJID.toBare(), nickResolver_->jidToNick(contactJID.toBare()), "MUC", byteArrayToString(avatarManager_->getAvatar(contactJID.toBare()))); +	// add new contact +	else if (message.getType() == HistoryMessage::Groupchat && !rooms_.count(displayJID)) { +		roster_->addContact(displayJID, displayJID, nickResolver_->jidToNick(displayJID), "MUC", avatarManager_->getAvatarPath(displayJID).string()); +		rooms_.insert(displayJID);  	} -	else if (!contacts_.count(contactJID) && !message.isGroupChat()) { -		roster_->addContact(contactJID, contactJID, nickResolver_->jidToNick(contactJID), "Contacts", byteArrayToString(avatarManager_->getAvatar(contactJID))); +	else if (message.getType() == HistoryMessage::Chat && !contacts_.count(displayJID)) { +		roster_->addContact(displayJID, displayJID, nickResolver_->jidToNick(displayJID), "Contacts", avatarManager_->getAvatarPath(displayJID).string()); +		contacts_.insert(displayJID);  	} +	else if (message.getType() == HistoryMessage::PrivateMessage && !roomPrivateContacts_.count(displayJID)) { +		roster_->addContact(displayJID, displayJID, nickResolver_->jidToNick(displayJID), "Contacts", avatarManager_->getAvatarPath(displayJID).string()); +		roomPrivateContacts_.insert(displayJID); +	} +} + +void HistoryViewController::addNewMessage(const HistoryMessage& message) { +	bool senderIsSelf = message.getFromJID().toBare() == selfJID_; +	std::string avatarPath = avatarManager_->getAvatarPath(message.getFromJID()).string(); +	historyWindow_->addMessage(message.getMessage(), nickResolver_->jidToNick(message.getFromJID()), senderIsSelf, avatarPath, message.getTime());  }  } diff --git a/Swift/Controllers/HistoryViewController.h b/Swift/Controllers/HistoryViewController.h index 4f43f47..4957e37 100644 --- a/Swift/Controllers/HistoryViewController.h +++ b/Swift/Controllers/HistoryViewController.h @@ -34,6 +34,7 @@ namespace Swift {  			void handleUIEvent(boost::shared_ptr<UIEvent> event);  			void handleSelectedContactChanged(RosterItem* item);  			void handleNewMessage(const HistoryMessage& message); +			void addNewMessage(const HistoryMessage& message);  		private:  			JID selfJID_; @@ -45,8 +46,9 @@ namespace Swift {  			HistoryWindow* historyWindow_;  			Roster* roster_; -			std::set<JID> rooms_;  			std::set<JID> contacts_; +			std::set<JID> rooms_; +			std::set<JID> roomPrivateContacts_;  			ContactRosterItem* selectedItem_;  	};  } diff --git a/Swift/Controllers/UIInterfaces/HistoryWindow.h b/Swift/Controllers/UIInterfaces/HistoryWindow.h index d51b65d..cd232f1 100644 --- a/Swift/Controllers/UIInterfaces/HistoryWindow.h +++ b/Swift/Controllers/UIInterfaces/HistoryWindow.h @@ -16,6 +16,7 @@ namespace Swift {  			virtual void activate() = 0;  			virtual void setRosterModel(Roster*) = 0;  			virtual void addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, const std::string& avatarPath, const boost::posix_time::ptime& time) = 0; +			virtual void resetConversationView() = 0;  			boost::signal<void (RosterItem*)> onSelectedContactChanged;  	}; diff --git a/Swift/QtUI/QtHistoryWindow.cpp b/Swift/QtUI/QtHistoryWindow.cpp index 122655a..50fd66e 100644 --- a/Swift/QtUI/QtHistoryWindow.cpp +++ b/Swift/QtUI/QtHistoryWindow.cpp @@ -89,8 +89,11 @@ void QtHistoryWindow::addMessage(const std::string &message, const std::string &  void QtHistoryWindow::handleSomethingSelectedChanged(RosterItem* item) { -	conversation_->resetView();  	onSelectedContactChanged(item);  } +void QtHistoryWindow::resetConversationView() { +	conversation_->resetView(); +} +  } diff --git a/Swift/QtUI/QtHistoryWindow.h b/Swift/QtUI/QtHistoryWindow.h index 965abf7..279657d 100644 --- a/Swift/QtUI/QtHistoryWindow.h +++ b/Swift/QtUI/QtHistoryWindow.h @@ -22,6 +22,7 @@ namespace Swift {  			void activate();  			void setRosterModel(Roster*);  			void addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, const std::string& avatarPath, const boost::posix_time::ptime& time); +			void resetConversationView();  		private:  			virtual void closeEvent(QCloseEvent* event); diff --git a/Swiften/History/HistoryManager.h b/Swiften/History/HistoryManager.h index a10bb41..bc1680b 100644 --- a/Swiften/History/HistoryManager.h +++ b/Swiften/History/HistoryManager.h @@ -18,7 +18,7 @@ namespace Swift {  			virtual void addMessage(const HistoryMessage& message) = 0; -			virtual std::vector<HistoryMessage> getMessages(const JID& selfJID, const JID& contactJID, bool isGroupChat) const = 0; -			virtual void getAllContacts(const JID& selfJID, std::set<JID>& mucs, std::set<JID>& contacts) const = 0; +			virtual std::vector<HistoryMessage> getMessages(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type) const = 0; +			virtual std::set<JID> getContacts(const JID& selfJID, HistoryMessage::Type type) const = 0;  	};  } diff --git a/Swiften/History/HistoryMessage.h b/Swiften/History/HistoryMessage.h index 021d6b9..d35474f 100644 --- a/Swiften/History/HistoryMessage.h +++ b/Swiften/History/HistoryMessage.h @@ -12,16 +12,22 @@  namespace Swift {  	class HistoryMessage {  		public: +			enum Type { +				Chat = 0, +				Groupchat = 1, +				PrivateMessage = 2 +			}; +  			HistoryMessage(  				const std::string& message,  				const JID& fromJID,  				const JID& toJID, -				bool isGroupChat, +				Type type,  				const boost::posix_time::ptime& time) :  					message_(message),  					fromJID_(fromJID),  					toJID_(toJID), -					isGroupChat_(isGroupChat), +					type_(type),  					time_(time) {  			} @@ -37,8 +43,8 @@ namespace Swift {  				return toJID_;  			} -			bool isGroupChat() const { -				return isGroupChat_; +			Type getType() const { +				return type_;  			}  			boost::posix_time::ptime getTime() const { @@ -46,14 +52,14 @@ namespace Swift {  			}  			bool operator==(const HistoryMessage& o) const { -				return message_ == o.message_ && fromJID_ == o.fromJID_ && toJID_ == o.toJID_ && isGroupChat_ == o.isGroupChat_ && time_ == o.time_; +				return message_ == o.message_ && fromJID_ == o.fromJID_ && toJID_ == o.toJID_ && type_ == o.type_ && time_ == o.time_;  			}  		private:  			std::string message_;  			JID fromJID_;  			JID toJID_; -			bool isGroupChat_; // TODO: <- maybe use Message::Type ? +			Type type_;  			boost::posix_time::ptime time_;  	};  } diff --git a/Swiften/History/SQLiteHistoryManager.cpp b/Swiften/History/SQLiteHistoryManager.cpp index af09b66..3304a07 100644 --- a/Swiften/History/SQLiteHistoryManager.cpp +++ b/Swiften/History/SQLiteHistoryManager.cpp @@ -30,7 +30,7 @@ SQLiteHistoryManager::SQLiteHistoryManager(const std::string& file) : db_(0) {  	}  	char* errorMessage; -	int result = sqlite3_exec(db_, "CREATE TABLE IF NOT EXISTS messages('message' STRING, 'fromBare' INTEGER, 'fromResource' STRING, 'toBare' INTEGER, 'toResource' STRING, 'groupChat' INTEGER, 'time' INTEGER)", 0, 0, &errorMessage); +	int result = sqlite3_exec(db_, "CREATE TABLE IF NOT EXISTS messages('message' STRING, 'fromBare' INTEGER, 'fromResource' STRING, 'toBare' INTEGER, 'toResource' STRING, 'type' INTEGER, 'time' INTEGER)", 0, 0, &errorMessage);  	if (result != SQLITE_OK) {  		std::cerr << "SQL Error: " << errorMessage << std::endl;  		sqlite3_free(errorMessage); @@ -50,13 +50,13 @@ SQLiteHistoryManager::~SQLiteHistoryManager() {  void SQLiteHistoryManager::addMessage(const HistoryMessage& message) {  	int secondsSinceEpoch = (message.getTime() - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_seconds(); -	std::string statement = std::string("INSERT INTO messages('message', 'fromBare', 'fromResource', 'toBare', 'toResource', 'groupChat', 'time') VALUES(") + +	std::string statement = std::string("INSERT INTO messages('message', 'fromBare', 'fromResource', 'toBare', 'toResource', 'type', 'time') VALUES(") +  					"'" + getEscapedString(message.getMessage()) + "', " +  					boost::lexical_cast<std::string>(getIDForJID(message.getFromJID().toBare())) + ", '" +  					getEscapedString(message.getFromJID().getResource()) + "', " +  					boost::lexical_cast<std::string>(getIDForJID(message.getToJID().toBare())) + ", '" +  					getEscapedString(message.getToJID().getResource()) + "', " + -					boost::lexical_cast<std::string>(message.isGroupChat()) + ", " +  +					boost::lexical_cast<std::string>(message.getType()) + ", " +  					boost::lexical_cast<std::string>(secondsSinceEpoch) + ")";  	char* errorMessage;  	int result = sqlite3_exec(db_, statement.c_str(), 0, 0, &errorMessage); @@ -66,7 +66,7 @@ void SQLiteHistoryManager::addMessage(const HistoryMessage& message) {  	}  } -std::vector<HistoryMessage> SQLiteHistoryManager::getMessages(const JID& selfJID, const JID& contactJID, bool isGroupChat) const { +std::vector<HistoryMessage> SQLiteHistoryManager::getMessages(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type) const {  	sqlite3_stmt* selectStatement;  	boost::optional<int> selfID = getIDFromJID(selfJID.toBare()); @@ -77,7 +77,7 @@ std::vector<HistoryMessage> SQLiteHistoryManager::getMessages(const JID& selfJID  		return std::vector<HistoryMessage>();  	} -	std::string selectQuery = "SELECT * FROM messages WHERE groupChat=" + boost::lexical_cast<std::string>(isGroupChat); +	std::string selectQuery = "SELECT * FROM messages WHERE type=" + boost::lexical_cast<std::string>(type);  	if (contactJID.isBare()) {  		// match only bare jid  		selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND toBare=" + @@ -120,13 +120,13 @@ std::vector<HistoryMessage> SQLiteHistoryManager::getMessages(const JID& selfJID  		}  		// message type -		bool isGroupChat = sqlite3_column_int(selectStatement, 5); +		HistoryMessage::Type type = static_cast<HistoryMessage::Type>(sqlite3_column_int(selectStatement, 5));  		// timestamp  		int secondsSinceEpoch(sqlite3_column_int(selectStatement, 6));  		boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); -		result.push_back(HistoryMessage(message, (fromJID ? *fromJID : JID()), (toJID ? *toJID : JID()), isGroupChat, time)); +		result.push_back(HistoryMessage(message, (fromJID ? *fromJID : JID()), (toJID ? *toJID : JID()), type, time));  		r = sqlite3_step(selectStatement);  	}  	if (r != SQLITE_DONE) { @@ -190,42 +190,22 @@ boost::optional<int> SQLiteHistoryManager::getIDFromJID(const JID& jid) const {  	return result;  } -void SQLiteHistoryManager::getAllContacts(const JID& selfJID, std::set<JID>& mucs, std::set<JID>& contacts) const { +std::set<JID> SQLiteHistoryManager::getContacts(const JID& selfJID, HistoryMessage::Type type) const { +	std::set<JID> result; +	sqlite3_stmt* selectStatement; +  	// get id  	boost::optional<int> id = getIDFromJID(selfJID);  	if (!id) { -		return; +		return result;  	} -	// get all MUCs -	std::string query = "SELECT DISTINCT messages.'fromBare' FROM messages WHERE groupChat=1 AND toBare=" + boost::lexical_cast<std::string>(*id); -	sqlite3_stmt* selectStatement; - -	int r = sqlite3_prepare(db_, query.c_str(), query.size(), &selectStatement, NULL); -	if (r != SQLITE_OK) { -		std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; -	} - -	r = sqlite3_step(selectStatement); -	while (r == SQLITE_ROW) { -		boost::optional<JID> contactJID(getJIDFromID(sqlite3_column_int(selectStatement, 0))); -		if (contactJID) { -			mucs.insert(*contactJID); -		} - -		r = sqlite3_step(selectStatement); -	} - -	if (r != SQLITE_DONE) { -		std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; -	} -	sqlite3_finalize(selectStatement); - -	// get all contacts -	query = "SELECT DISTINCT messages.'fromBare', messages.'fromResource', messages.'toBare', messages.'toResource' FROM messages WHERE groupChat=0 AND (toBare=" +	// get contacts +	std::string query = "SELECT DISTINCT messages.'fromBare', messages.'fromResource', messages.'toBare', messages.'toResource' FROM messages WHERE type=" +		+ boost::lexical_cast<std::string>(type) + " AND (toBare="  		+ boost::lexical_cast<std::string>(*id) + " OR fromBare=" + boost::lexical_cast<std::string>(*id) + ")"; -	r = sqlite3_prepare(db_, query.c_str(), query.size(), &selectStatement, NULL); +	int r = sqlite3_prepare(db_, query.c_str(), query.size(), &selectStatement, NULL);  	if (r != SQLITE_OK) {  		std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl;  	} @@ -250,12 +230,12 @@ void SQLiteHistoryManager::getAllContacts(const JID& selfJID, std::set<JID>& muc  		}  		// check if it is a MUC contact (from a private conversation) -		if (contactJID && mucs.count(*contactJID)) { +		if (type == HistoryMessage::PrivateMessage) {  			contactJID = boost::optional<JID>(JID(contactJID->getNode(), contactJID->getDomain(), resource));  		}  		if (contactJID) { -			contacts.insert(*contactJID); +			result.insert(*contactJID);  		}  		r = sqlite3_step(selectStatement); @@ -265,6 +245,8 @@ void SQLiteHistoryManager::getAllContacts(const JID& selfJID, std::set<JID>& muc  		std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl;  	}  	sqlite3_finalize(selectStatement); + +	return result;  }  } diff --git a/Swiften/History/SQLiteHistoryManager.h b/Swiften/History/SQLiteHistoryManager.h index 480d570..fce30f8 100644 --- a/Swiften/History/SQLiteHistoryManager.h +++ b/Swiften/History/SQLiteHistoryManager.h @@ -19,8 +19,8 @@ namespace Swift {  			~SQLiteHistoryManager();  			void addMessage(const HistoryMessage& message); -			std::vector<HistoryMessage> getMessages(const JID& selfJID, const JID& contactJID, bool isGroupChat) const; -			void getAllContacts(const JID& selfJID, std::set<JID>& mucs, std::set<JID>& contacts) const; +			std::vector<HistoryMessage> getMessages(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type) const; +			std::set<JID> getContacts(const JID& selfJID, HistoryMessage::Type type) const;  		private:  			int getIDForJID(const JID&); | 
 Swift
 Swift