From 831075a8aeb15dc79c84d28d284b5cdbae2f60ea Mon Sep 17 00:00:00 2001
From: Catalin Badea <catalin.badea392@gmail.com>
Date: Sun, 1 Jul 2012 23:13:27 +0300
Subject: Dump message logs using new db structure. Avatars not working


diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index b0413af..632d760 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -353,9 +353,9 @@ boost::optional<boost::posix_time::ptime> ChatController::getMessageTimestamp(bo
 	return message->getTimestamp();
 }
 
-void ChatController::logMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp, bool isIncoming) {
+void ChatController::logMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp, bool /* isIncoming */) {
 	if (historyController_) {
-		historyController_->addMessage(message, fromJID, toJID, timeStamp);
+		historyController_->addMessage(message, fromJID, toJID, false, timeStamp);
 	}
 }
 
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 222fb01..f86c726 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -783,7 +783,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, timeStamp);
+		historyController_->addMessage(message, fromJID, toJID, true, timeStamp);
 	}
 }
 
diff --git a/Swift/Controllers/HistoryController.cpp b/Swift/Controllers/HistoryController.cpp
index 7e3d1e4..a25c40f 100644
--- a/Swift/Controllers/HistoryController.cpp
+++ b/Swift/Controllers/HistoryController.cpp
@@ -19,17 +19,17 @@ HistoryController::~HistoryController() {
 	delete localHistory_;
 }
 
-void HistoryController::addMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp) {
-	HistoryMessage historyMessage(message, fromJID, toJID, timeStamp);
+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);
 	localHistory_->addMessage(historyMessage);
 }
 
-std::vector<HistoryMessage> HistoryController::getMessages(const JID& selfJID, const JID& contactJID) const {
-	return localHistory_->getMessages(selfJID, contactJID);
+std::vector<HistoryMessage> HistoryController::getMessages(const JID& selfJID, const JID& contactJID, bool isGroupChat) const {
+	return localHistory_->getMessages(selfJID, contactJID, isGroupChat);
 }
 
-std::vector<JID> HistoryController::getAllContacts() const {
-	return localHistory_->getAllContacts();
+void HistoryController::getAllContacts(const JID& selfJID, std::set<JID>& mucs, std::set<JID>& contacts) const {
+	return localHistory_->getAllContacts(selfJID, mucs, contacts);
 }
 
 }
diff --git a/Swift/Controllers/HistoryController.h b/Swift/Controllers/HistoryController.h
index 9a38b15..5c0378a 100644
--- a/Swift/Controllers/HistoryController.h
+++ b/Swift/Controllers/HistoryController.h
@@ -9,6 +9,7 @@
 #include <Swiften/JID/JID.h>
 #include <boost/date_time/posix_time/posix_time.hpp>
 #include <vector>
+#include <set>
 
 namespace Swift {
 	class HistoryManager;
@@ -20,9 +21,9 @@ namespace Swift {
 			HistoryController();
 			~HistoryController();
 
-			void addMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp);
-			std::vector<HistoryMessage> getMessages(const JID& selfJID, const JID& contactJID) const;
-			std::vector<JID> getAllContacts() const;
+			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;
 
 		private:
 			HistoryManager* localHistory_;
diff --git a/Swift/Controllers/HistoryViewController.cpp b/Swift/Controllers/HistoryViewController.cpp
index f88d097..9c10874 100644
--- a/Swift/Controllers/HistoryViewController.cpp
+++ b/Swift/Controllers/HistoryViewController.cpp
@@ -10,15 +10,20 @@
 #include <Swift/Controllers/UIEvents/RequestHistoryUIEvent.h>
 #include <Swift/Controllers/HistoryController.h>
 #include <Swiften/History/HistoryMessage.h>
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Client/NickResolver.h>
+#include <Swiften/Avatars/AvatarManager.h>
 
 namespace Swift {
 
 HistoryViewController::HistoryViewController(
+		const JID& selfJID,
 		UIEventStream* uiEventStream,
 		HistoryController* historyController,
 		NickResolver* nickResolver,
 		AvatarManager* avatarManager,
 		HistoryWindowFactory* historyWindowFactory) :
+			selfJID_(selfJID),
 			uiEventStream_(uiEventStream),
 			historyController_(historyController),
 			nickResolver_(nickResolver),
@@ -47,9 +52,13 @@ void HistoryViewController::handleUIEvent(boost::shared_ptr<UIEvent> rawEvent) {
 			roster_ = new Roster(false, true);
 			historyWindow_->setRosterModel(roster_);
 
-			std::vector<JID> contacts = historyController_->getAllContacts();
-			for (std::vector<JID>::iterator it = contacts.begin(); it != contacts.end(); it++) {
-				roster_->addContact(*it, *it, *it, "Recent", "");
+			historyController_->getAllContacts(selfJID_, rooms_, contacts_);
+
+			foreach (const JID& muc, rooms_) {
+				roster_->addContact(muc, muc, nickResolver_->jidToNick(muc), "MUC", byteArrayToString(avatarManager_->getAvatar(muc)));
+			}
+			foreach (const JID& contact, contacts_) {
+				roster_->addContact(contact, contact, nickResolver_->jidToNick(contact), "Contacts", byteArrayToString(avatarManager_->getAvatar(contact)));
 			}
 		}
 
@@ -58,17 +67,20 @@ void HistoryViewController::handleUIEvent(boost::shared_ptr<UIEvent> rawEvent) {
 }
 
 void HistoryViewController::handleSelectedContactChanged(RosterItem* newContact) {
-	// TODO: check if actually changed
 	// FIXME: signal is triggerd twice.
 	if (newContact == NULL) {
 		return;
 	}
 
 	ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(newContact);
+	JID contactJID = contact->getJID();
+	bool isRoom = rooms_.count(contactJID);
 
-	std::vector<HistoryMessage> messages; //TODO = historyController_->getMessages(contact->getJID());
-	for (std::vector<HistoryMessage>::iterator it = messages.begin(); it != messages.end(); it++) {
-		historyWindow_->addMessage(*it);
+	std::vector<HistoryMessage> messages = historyController_->getMessages(selfJID_, contactJID, isRoom);
+	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());
 	}
 }
 
diff --git a/Swift/Controllers/HistoryViewController.h b/Swift/Controllers/HistoryViewController.h
index 7dabf46..f1ff286 100644
--- a/Swift/Controllers/HistoryViewController.h
+++ b/Swift/Controllers/HistoryViewController.h
@@ -11,6 +11,8 @@
 #include <boost/shared_ptr.hpp>
 
 #include <Swift/Controllers/UIEvents/UIEventStream.h>
+#include <Swiften/JID/JID.h>
+#include <set>
 
 namespace Swift {
 	class HistoryWindowFactory;
@@ -23,7 +25,7 @@ namespace Swift {
 
 	class HistoryViewController {
 		public:
-			HistoryViewController(UIEventStream* uiEventStream, HistoryController* historyController, NickResolver* nickResolver, AvatarManager* avatarManager, HistoryWindowFactory* historyWindowFactory);
+			HistoryViewController(const JID& selfJID, UIEventStream* uiEventStream, HistoryController* historyController, NickResolver* nickResolver, AvatarManager* avatarManager, HistoryWindowFactory* historyWindowFactory);
 			~HistoryViewController();
 
 		private:
@@ -31,6 +33,7 @@ namespace Swift {
 			void handleSelectedContactChanged(RosterItem* item);
 
 		private:
+			JID selfJID_;
 			UIEventStream* uiEventStream_;
 			HistoryController* historyController_;
 			NickResolver* nickResolver_;
@@ -38,5 +41,8 @@ namespace Swift {
 			HistoryWindowFactory* historyWindowFactory_;
 			HistoryWindow* historyWindow_;
 			Roster* roster_;
+
+			std::set<JID> rooms_;
+			std::set<JID> contacts_;
 	};
 }
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 60a882a..8b1c489 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -299,7 +299,7 @@ void MainController::handleConnected() {
 
 		chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, historyController_);
 
-		historyViewController_ = new HistoryViewController(uiEventStream_, historyController_, client_->getNickResolver(), client_->getAvatarManager(), uiFactory_);
+		historyViewController_ = new HistoryViewController(jid_, uiEventStream_, historyController_, client_->getNickResolver(), client_->getAvatarManager(), uiFactory_);
 		
 		client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1));
 		chatsManager_->setAvatarManager(client_->getAvatarManager());
diff --git a/Swift/Controllers/UIInterfaces/HistoryWindow.h b/Swift/Controllers/UIInterfaces/HistoryWindow.h
index cc3f0b8..d51b65d 100644
--- a/Swift/Controllers/UIInterfaces/HistoryWindow.h
+++ b/Swift/Controllers/UIInterfaces/HistoryWindow.h
@@ -9,15 +9,13 @@
 #include <Swift/Controllers/Roster/Roster.h>
 
 namespace Swift {
-	class HistoryMessage;
-
 	class HistoryWindow {
 		public:
 			virtual ~HistoryWindow() {};
 
 			virtual void activate() = 0;
 			virtual void setRosterModel(Roster*) = 0;
-			virtual void addMessage(const HistoryMessage& message) = 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;
 
 			boost::signal<void (RosterItem*)> onSelectedContactChanged;
 	};
diff --git a/Swift/QtUI/QtHistoryWindow.cpp b/Swift/QtUI/QtHistoryWindow.cpp
index 24085d9..122655a 100644
--- a/Swift/QtUI/QtHistoryWindow.cpp
+++ b/Swift/QtUI/QtHistoryWindow.cpp
@@ -13,6 +13,13 @@
 #include <string>
 
 #include <boost/shared_ptr.hpp>
+
+#include <QTime>
+#include <QUrl>
+#include <QMenu>
+#include <QTextDocument>
+#include <Swift/QtUI/QtScaledAvatarCache.h>
+
 #include <boost/smart_ptr/make_shared.hpp>
 
 namespace Swift {
@@ -69,12 +76,18 @@ void QtHistoryWindow::setRosterModel(Roster* model) {
 	conversationRoster_->setRosterModel(model);
 }
 
-void QtHistoryWindow::addMessage(const HistoryMessage& message) {
-	// TODO
-	// boost::shared_ptr<MessageSnippet> snippet(new MessageSnippet(QString::fromStdString(message.getMessage()), QString::fromStdString(message.getDisplayNick()), QDateTime::currentDateTime(), "", false, false, theme_, "id")); 
-	// conversation_->addMessage(snippet);
+void QtHistoryWindow::addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, const std::string& avatarPath, const boost::posix_time::ptime& time) {
+	QString scaledAvatarPath = QtScaledAvatarCache(32).getScaledAvatarPath(avatarPath.c_str());
+
+	QString messageHTML(P2QSTRING(message));
+	messageHTML = Qt::escape(messageHTML);
+
+	QString qAvatarPath =  scaledAvatarPath.isEmpty() ? "qrc:/icons/avatar.png" : QUrl::fromLocalFile(scaledAvatarPath).toEncoded();
+
+	conversation_->addMessage(boost::shared_ptr<ChatSnippet>(new MessageSnippet(messageHTML, Qt::escape(P2QSTRING(senderName)), B2QDATE(time), qAvatarPath, senderIsSelf, false, theme_, "id")));
 }
 
+
 void QtHistoryWindow::handleSomethingSelectedChanged(RosterItem* item) {
 	conversation_->resetView();
 	onSelectedContactChanged(item);
diff --git a/Swift/QtUI/QtHistoryWindow.h b/Swift/QtUI/QtHistoryWindow.h
index 1ddaf61..965abf7 100644
--- a/Swift/QtUI/QtHistoryWindow.h
+++ b/Swift/QtUI/QtHistoryWindow.h
@@ -21,7 +21,7 @@ namespace Swift {
 			~QtHistoryWindow();
 			void activate();
 			void setRosterModel(Roster*);
-			void addMessage(const HistoryMessage& message);
+			void addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, const std::string& avatarPath, const boost::posix_time::ptime& time);
 
 		private:
 			virtual void closeEvent(QCloseEvent* event);
diff --git a/Swiften/History/HistoryManager.h b/Swiften/History/HistoryManager.h
index 1c0d784..a10bb41 100644
--- a/Swiften/History/HistoryManager.h
+++ b/Swiften/History/HistoryManager.h
@@ -6,6 +6,7 @@
 
 #pragma once
 
+#include <set>
 #include <vector>
 #include <Swiften/JID/JID.h>
 #include <Swiften/History/HistoryMessage.h>
@@ -17,7 +18,7 @@ namespace Swift {
 
 			virtual void addMessage(const HistoryMessage& message) = 0;
 
-			virtual std::vector<HistoryMessage> getMessages(const JID& selfJID, const JID& contactJID) const = 0;
-			virtual std::vector<JID> getAllContacts() const = 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;
 	};
 }
diff --git a/Swiften/History/HistoryMessage.h b/Swiften/History/HistoryMessage.h
index 0bcff99..021d6b9 100644
--- a/Swiften/History/HistoryMessage.h
+++ b/Swiften/History/HistoryMessage.h
@@ -16,10 +16,12 @@ namespace Swift {
 				const std::string& message,
 				const JID& fromJID,
 				const JID& toJID,
+				bool isGroupChat,
 				const boost::posix_time::ptime& time) :
 					message_(message),
 					fromJID_(fromJID),
 					toJID_(toJID),
+					isGroupChat_(isGroupChat),
 					time_(time) {
 			}
 
@@ -35,18 +37,23 @@ namespace Swift {
 				return toJID_;
 			}
 
+			bool isGroupChat() const {
+				return isGroupChat_;
+			}
+
 			boost::posix_time::ptime getTime() const {
 				return time_;
 			}
 
 			bool operator==(const HistoryMessage& o) const {
-				return message_ == o.message_ && fromJID_ == o.fromJID_ && toJID_ == o.toJID_ && time_ == o.time_;
+				return message_ == o.message_ && fromJID_ == o.fromJID_ && toJID_ == o.toJID_ && isGroupChat_ == o.isGroupChat_ && time_ == o.time_;
 			}
 
 		private:
 			std::string message_;
 			JID fromJID_;
 			JID toJID_;
+			bool isGroupChat_; // TODO: <- maybe use Message::Type ?
 			boost::posix_time::ptime time_;
 	};
 }
diff --git a/Swiften/History/SQLiteHistoryManager.cpp b/Swiften/History/SQLiteHistoryManager.cpp
index 9f02ca2..af09b66 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, '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, 'groupChat' INTEGER, 'time' INTEGER)", 0, 0, &errorMessage);
 	if (result != SQLITE_OK) {
 		std::cerr << "SQL Error: " << errorMessage << std::endl;
 		sqlite3_free(errorMessage);
@@ -41,13 +41,6 @@ SQLiteHistoryManager::SQLiteHistoryManager(const std::string& file) : db_(0) {
 		std::cerr << "SQL Error: " << errorMessage << std::endl;
 		sqlite3_free(errorMessage);
 	}
-
-	// FIXME: remove
-	result = sqlite3_exec(db_, "CREATE TABLE IF NOT EXISTS conversations('id' INTEGER UNIQUE NOT NULL, 'time' INTEGER)", 0, 0, &errorMessage);
-	if (result != SQLITE_OK) {
-		std::cerr << "SQL Error: " << errorMessage << std::endl;
-		sqlite3_free(errorMessage);
-	}
 }
 
 SQLiteHistoryManager::~SQLiteHistoryManager() {
@@ -55,16 +48,15 @@ SQLiteHistoryManager::~SQLiteHistoryManager() {
 }
 
 void SQLiteHistoryManager::addMessage(const HistoryMessage& message) {
-	// updateConversation(message);
-
 	int secondsSinceEpoch = (message.getTime() - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_seconds();
 
-	std::string statement = std::string("'message', 'fromBare', 'fromResource', 'toBare', 'toResource', 'time') VALUES(") +
+	std::string statement = std::string("INSERT INTO messages('message', 'fromBare', 'fromResource', 'toBare', 'toResource', 'groupChat', '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.getFromJID().toBare())) + ", '" +
+					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>(secondsSinceEpoch) + ")";
 	char* errorMessage;
 	int result = sqlite3_exec(db_, statement.c_str(), 0, 0, &errorMessage);
@@ -74,7 +66,7 @@ void SQLiteHistoryManager::addMessage(const HistoryMessage& message) {
 	}
 }
 
-std::vector<HistoryMessage> SQLiteHistoryManager::getMessages(const JID& selfJID, const JID& contactJID) const {
+std::vector<HistoryMessage> SQLiteHistoryManager::getMessages(const JID& selfJID, const JID& contactJID, bool isGroupChat) const {
 	sqlite3_stmt* selectStatement;
 
 	boost::optional<int> selfID = getIDFromJID(selfJID.toBare());
@@ -85,11 +77,22 @@ std::vector<HistoryMessage> SQLiteHistoryManager::getMessages(const JID& selfJID
 		return std::vector<HistoryMessage>();
 	}
 
-	std::string selectQuery = "SELECT * FROM messages WHERE (fromBare=" +
-			boost::lexical_cast<std::string>(*selfID) + " AND fromBare=" +
-			boost::lexical_cast<std::string>(*contactID) + ") OR (fromBare=" +
-			boost::lexical_cast<std::string>(*contactID) + " AND fromBare=" +
-			boost::lexical_cast<std::string>(*selfID) + ")";
+	std::string selectQuery = "SELECT * FROM messages WHERE groupChat=" + boost::lexical_cast<std::string>(isGroupChat);
+	if (contactJID.isBare()) {
+		// match only bare jid
+		selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND toBare=" +
+				boost::lexical_cast<std::string>(*contactID) + ") OR (fromBare=" +
+				boost::lexical_cast<std::string>(*contactID) + " AND toBare=" + boost::lexical_cast<std::string>(*selfID) + "))";
+	}
+	else {
+		// match resource too
+		selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND (toBare=" +
+				boost::lexical_cast<std::string>(*contactID) +" AND toResource='" +
+				getEscapedString(contactJID.getResource()) + "')) OR ((fromBare=" +
+				boost::lexical_cast<std::string>(*contactID) + " AND fromResource='" +
+				getEscapedString(contactJID.getResource()) + "') AND toBare=" +
+				boost::lexical_cast<std::string>(*selfID) + "))";
+	}
 
 	int r = sqlite3_prepare(db_, selectQuery.c_str(), selectQuery.size(), &selectStatement, NULL);
 	if (r != SQLITE_OK) {
@@ -116,11 +119,14 @@ std::vector<HistoryMessage> SQLiteHistoryManager::getMessages(const JID& selfJID
 			toJID = boost::optional<JID>(JID(toJID->getNode(), toJID->getDomain(), toResource));
 		}
 
+		// message type
+		bool isGroupChat = sqlite3_column_int(selectStatement, 5);
+
 		// timestamp
-		int secondsSinceEpoch(sqlite3_column_int(selectStatement, 5));
+		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()), time));
+		result.push_back(HistoryMessage(message, (fromJID ? *fromJID : JID()), (toJID ? *toJID : JID()), isGroupChat, time));
 		r = sqlite3_step(selectStatement);
 	}
 	if (r != SQLITE_DONE) {
@@ -184,28 +190,15 @@ boost::optional<int> SQLiteHistoryManager::getIDFromJID(const JID& jid) const {
 	return result;
 }
 
-void SQLiteHistoryManager::updateConversation(const HistoryMessage& message) {
-
-	/*
-	int id = getIDForJID(message.getBaseJID());
-	int secondsSinceEpoch = (message.getTime() - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_seconds(); // this might fail in 2038
-
-	std::stringstream statement;
-	statement << "insert or replace into conversations('id', 'time') VALUES(" <<
-		id <<", " << secondsSinceEpoch << ")";
-
-	char* errorMessage;
-	int result = sqlite3_exec(db_, statement.str().c_str(), 0, 0, &errorMessage);
-
-	if (result != SQLITE_OK) {
-		std::cerr << "SQL Error: " << errorMessage << std::endl;
-		sqlite3_free(errorMessage);
+void SQLiteHistoryManager::getAllContacts(const JID& selfJID, std::set<JID>& mucs, std::set<JID>& contacts) const {
+	// get id
+	boost::optional<int> id = getIDFromJID(selfJID);
+	if (!id) {
+		return;
 	}
-	*/
-}
 
-std::vector<JID> SQLiteHistoryManager::getAllContacts() const {
-	std::string query("SELECT conversations.'id' FROM conversations");
+	// 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);
@@ -214,21 +207,64 @@ std::vector<JID> SQLiteHistoryManager::getAllContacts() const {
 	}
 
 	r = sqlite3_step(selectStatement);
-	std::vector<JID> result;
 	while (r == SQLITE_ROW) {
 		boost::optional<JID> contactJID(getJIDFromID(sqlite3_column_int(selectStatement, 0)));
 		if (contactJID) {
-			result.push_back(*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="
+		+ 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);
+	if (r != SQLITE_OK) {
+		std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl;
+	}
+
+	r = sqlite3_step(selectStatement);
+	while (r == SQLITE_ROW) {
+		int fromBareID = sqlite3_column_int(selectStatement, 0);
+		std::string fromResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 1)));
+		int toBareID = sqlite3_column_int(selectStatement, 2);
+		std::string toResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 3)));
+		std::string resource;
+
+		boost::optional<JID> contactJID;
+
+		if (fromBareID == *id) {
+			contactJID = getJIDFromID(toBareID);
+			resource = toResource;
+		}
+		else {
+			contactJID = getJIDFromID(fromBareID);
+			resource = fromResource;
+		}
 
+		// check if it is a MUC contact (from a private conversation)
+		if (contactJID && mucs.count(*contactJID)) {
+			contactJID = boost::optional<JID>(JID(contactJID->getNode(), contactJID->getDomain(), resource));
+		}
+
+		if (contactJID) {
+			contacts.insert(*contactJID);
+		}
+
+		r = sqlite3_step(selectStatement);
+	}
+
+	if (r != SQLITE_DONE) {
+		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 9d9ec05..480d570 100644
--- a/Swiften/History/SQLiteHistoryManager.h
+++ b/Swiften/History/SQLiteHistoryManager.h
@@ -19,13 +19,12 @@ namespace Swift {
 			~SQLiteHistoryManager();
 
 			void addMessage(const HistoryMessage& message);
-			std::vector<HistoryMessage> getMessages(const JID& selfJID, const JID& contactJID) const;
-			std::vector<JID> getAllContacts() const;
+			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;
 
 		private:
 			int getIDForJID(const JID&);
 			int addJID(const JID&);
-			void updateConversation(const HistoryMessage& message);
 
 			boost::optional<JID> getJIDFromID(int id) const;
 			boost::optional<int> getIDFromJID(const JID& jid) const;
-- 
cgit v0.10.2-6-g49f6