diff options
-rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.cpp | 8 | ||||
-rw-r--r-- | Swift/Controllers/HistoryController.cpp | 8 | ||||
-rw-r--r-- | Swift/Controllers/HistoryController.h | 3 | ||||
-rw-r--r-- | Swift/Controllers/HistoryViewController.cpp | 39 | ||||
-rw-r--r-- | Swift/Controllers/HistoryViewController.h | 2 | ||||
-rw-r--r-- | Swift/Controllers/UIInterfaces/HistoryWindow.h | 2 | ||||
-rw-r--r-- | Swift/QtUI/QtHistoryWindow.cpp | 7 | ||||
-rw-r--r-- | Swift/QtUI/QtHistoryWindow.h | 2 | ||||
-rw-r--r-- | Swiften/History/HistoryManager.h | 3 | ||||
-rw-r--r-- | Swiften/History/SQLiteHistoryManager.cpp | 66 | ||||
-rw-r--r-- | Swiften/History/SQLiteHistoryManager.h | 8 |
11 files changed, 123 insertions, 25 deletions
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index 302f793..97b574b 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -145,7 +145,9 @@ void ChatControllerBase::handleSendMessageRequest(const std::string &body, bool onActivity(message->getBody()); // log message - historyController_->addMessage(getBaseJID(), selfJID_, std::string("me"), body, now); + if (historyController_) { + historyController_->addMessage(getBaseJID(), selfJID_, std::string("me"), body, now); + } } void ChatControllerBase::handleSecurityLabelsCatalogResponse(boost::shared_ptr<SecurityLabelsCatalog> catalog, ErrorPayload::ref error) { @@ -252,7 +254,9 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m } else { lastMessagesUIID_[from] = addMessage(body, senderDisplayNameFromMessage(from), isIncomingMessageFromMe(message), label, std::string(avatarManager_->getAvatarPath(from).string()), timeStamp); - historyController_->addMessage(getBaseJID(), from, senderDisplayNameFromMessage(from), body, timeStamp); + if (historyController_) { + historyController_->addMessage(getBaseJID(), from, senderDisplayNameFromMessage(from), body, timeStamp); + } } } chatWindow_->show(); diff --git a/Swift/Controllers/HistoryController.cpp b/Swift/Controllers/HistoryController.cpp index c82892a..63d4690 100644 --- a/Swift/Controllers/HistoryController.cpp +++ b/Swift/Controllers/HistoryController.cpp @@ -24,8 +24,12 @@ void HistoryController::addMessage(const JID& baseJID, const JID& fromJID, const localHistory_->addMessage(message); } -std::vector<HistoryMessage> HistoryController::getMessages() const { - return localHistory_->getMessages(); +std::vector<HistoryMessage> HistoryController::getMessages(const JID& baseJID) const { + return localHistory_->getMessages(baseJID); +} + +std::vector<JID> HistoryController::getAllContacts() const { + return localHistory_->getAllContacts(); } } diff --git a/Swift/Controllers/HistoryController.h b/Swift/Controllers/HistoryController.h index 6ead3f1..0d337f6 100644 --- a/Swift/Controllers/HistoryController.h +++ b/Swift/Controllers/HistoryController.h @@ -21,7 +21,8 @@ namespace Swift { ~HistoryController(); void addMessage(const JID& baseJID, const JID& fromJID, const std::string& displayNick, const std::string& messageBody, boost::posix_time::ptime timeStamp); - std::vector<HistoryMessage> getMessages() const; + std::vector<HistoryMessage> getMessages(const JID& baseJID) const; + std::vector<JID> getAllContacts() const; private: HistoryManager* localHistory_; diff --git a/Swift/Controllers/HistoryViewController.cpp b/Swift/Controllers/HistoryViewController.cpp index 1061e78..5cc25e0 100644 --- a/Swift/Controllers/HistoryViewController.cpp +++ b/Swift/Controllers/HistoryViewController.cpp @@ -26,8 +26,11 @@ HistoryViewController::HistoryViewController( HistoryViewController::~HistoryViewController() { uiEventStream_->onUIEvent.disconnect(boost::bind(&HistoryViewController::handleUIEvent, this, _1)); - delete historyWindow_; - delete roster_; + if (historyWindow_) { + historyWindow_->onSelectedContactChanged.disconnect(boost::bind(&HistoryViewController::handleSelectedContactChanged, this, _1)); + delete historyWindow_; + delete roster_; + } } void HistoryViewController::handleUIEvent(boost::shared_ptr<UIEvent> rawEvent) { @@ -35,24 +38,34 @@ void HistoryViewController::handleUIEvent(boost::shared_ptr<UIEvent> rawEvent) { if (event != NULL) { if (historyWindow_ == NULL) { historyWindow_ = historyWindowFactory_->createHistoryWindow(uiEventStream_); + historyWindow_->onSelectedContactChanged.connect(boost::bind(&HistoryViewController::handleSelectedContactChanged, this, _1)); + roster_ = new Roster(false, true); historyWindow_->setRosterModel(roster_); - JID putin("vputin@karla.com"); - JID medvedev("dmedvedev@karla.com"); - JID kev("kevin@doomsong.co.uk"); - const std::set<ContactRosterItem::Feature> none; - roster_->addContact(putin, putin, "Vladimir Putin", "Recent", ""); - roster_->addContact(medvedev, medvedev, "Dmitri Medvedev", "Recent", ""); - roster_->addContact(kev, kev, "Kev", "Recent", ""); + std::vector<JID> contacts = historyController_->getAllContacts(); + for (std::vector<JID>::iterator it = contacts.begin(); it != contacts.end(); it++) { + roster_->addContact(*it, *it, *it, "Recent", ""); + } } - std::vector<HistoryMessage> messages = historyController_->getMessages(); - for (std::vector<HistoryMessage>::iterator it = messages.begin(); it != messages.end(); it++) { - historyWindow_->addMessage(*it); - } historyWindow_->activate(); } } +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); + + std::vector<HistoryMessage> messages = historyController_->getMessages(contact->getJID()); + for (std::vector<HistoryMessage>::iterator it = messages.begin(); it != messages.end(); it++) { + historyWindow_->addMessage(*it); + } +} + } diff --git a/Swift/Controllers/HistoryViewController.h b/Swift/Controllers/HistoryViewController.h index f64dd35..94e5df3 100644 --- a/Swift/Controllers/HistoryViewController.h +++ b/Swift/Controllers/HistoryViewController.h @@ -16,6 +16,7 @@ namespace Swift { class HistoryWindowFactory; class HistoryWindow; class Roster; + class RosterItem; class HistoryController; class HistoryViewController { @@ -25,6 +26,7 @@ namespace Swift { private: void handleUIEvent(boost::shared_ptr<UIEvent> event); + void handleSelectedContactChanged(RosterItem* item); private: UIEventStream* uiEventStream_; diff --git a/Swift/Controllers/UIInterfaces/HistoryWindow.h b/Swift/Controllers/UIInterfaces/HistoryWindow.h index 9ec79e2..cc3f0b8 100644 --- a/Swift/Controllers/UIInterfaces/HistoryWindow.h +++ b/Swift/Controllers/UIInterfaces/HistoryWindow.h @@ -18,5 +18,7 @@ namespace Swift { virtual void activate() = 0; virtual void setRosterModel(Roster*) = 0; virtual void addMessage(const HistoryMessage& message) = 0; + + boost::signal<void (RosterItem*)> onSelectedContactChanged; }; } diff --git a/Swift/QtUI/QtHistoryWindow.cpp b/Swift/QtUI/QtHistoryWindow.cpp index d067190..b3df29f 100644 --- a/Swift/QtUI/QtHistoryWindow.cpp +++ b/Swift/QtUI/QtHistoryWindow.cpp @@ -42,6 +42,8 @@ QtHistoryWindow::QtHistoryWindow(SettingsProvider* settings, UIEventStream* even ui_.bottomLeftLayout_->addWidget(conversationRoster_); setWindowTitle(tr("History")); + + conversationRoster_->onSomethingSelectedChanged.connect(boost::bind(&QtHistoryWindow::handleSomethingSelectedChanged, this, _1)); } QtHistoryWindow::~QtHistoryWindow() { @@ -72,4 +74,9 @@ void QtHistoryWindow::addMessage(const HistoryMessage& message) { conversation_->addMessage(snippet); } +void QtHistoryWindow::handleSomethingSelectedChanged(RosterItem* item) { + conversation_->resetView(); + onSelectedContactChanged(item); +} + } diff --git a/Swift/QtUI/QtHistoryWindow.h b/Swift/QtUI/QtHistoryWindow.h index d522f53..1f0cdb7 100644 --- a/Swift/QtUI/QtHistoryWindow.h +++ b/Swift/QtUI/QtHistoryWindow.h @@ -31,6 +31,8 @@ namespace Swift { virtual void closeEvent(QCloseEvent* event); virtual void showEvent(QShowEvent* event); + void handleSomethingSelectedChanged(RosterItem* item); + Ui::QtHistoryWindow ui_; QtChatTheme* theme_; QtChatView* conversation_; diff --git a/Swiften/History/HistoryManager.h b/Swiften/History/HistoryManager.h index 7a4324b..151f8be 100644 --- a/Swiften/History/HistoryManager.h +++ b/Swiften/History/HistoryManager.h @@ -17,6 +17,7 @@ namespace Swift { virtual void addMessage(const HistoryMessage& message) = 0; - virtual std::vector<HistoryMessage> getMessages() const = 0; + virtual std::vector<HistoryMessage> getMessages(const JID&) const = 0; + virtual std::vector<JID> getAllContacts() const = 0; }; } diff --git a/Swiften/History/SQLiteHistoryManager.cpp b/Swiften/History/SQLiteHistoryManager.cpp index e10de07..33d2c58 100644 --- a/Swiften/History/SQLiteHistoryManager.cpp +++ b/Swiften/History/SQLiteHistoryManager.cpp @@ -9,6 +9,7 @@ #include <sqlite3.h> #include <Swiften/History/SQLiteHistoryManager.h> +#include <sstream> inline std::string getEscapedString(const std::string& s) { std::string result(s); @@ -36,6 +37,12 @@ SQLiteHistoryManager::SQLiteHistoryManager(const std::string& file) : db_(0) { std::cerr << "SQL Error: " << errorMessage << std::endl; sqlite3_free(errorMessage); } + + 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() { @@ -43,6 +50,8 @@ 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("INSERT INTO messages('baseID', 'from', 'nick', 'message', 'time') VALUES(") + boost::lexical_cast<std::string>(getIDForJID(message.getBaseJID())) + ", " + @@ -58,11 +67,18 @@ void SQLiteHistoryManager::addMessage(const HistoryMessage& message) { } } -std::vector<HistoryMessage> SQLiteHistoryManager::getMessages() const { +std::vector<HistoryMessage> SQLiteHistoryManager::getMessages(const JID& baseJID) const { std::vector<HistoryMessage> result; sqlite3_stmt* selectStatement; - std::string selectQuery("SELECT messages.'baseID', messages.'from', messages.'nick', messages.'message', messages.'time' FROM messages"); - int r = sqlite3_prepare(db_, selectQuery.c_str(), selectQuery.size(), &selectStatement, NULL); + boost::optional<int> baseID = getIDFromJID(baseJID); + if (!baseID) { + return std::vector<HistoryMessage>(); + } + + std::stringstream selectQuery; + selectQuery << "SELECT messages.'baseID', messages.'from', messages.'nick', messages.'message', messages.'time' FROM messages WHERE baseID=" << *baseID; + + int r = sqlite3_prepare(db_, selectQuery.str().c_str(), selectQuery.str().size(), &selectStatement, NULL); if (r != SQLITE_OK) { std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; } @@ -138,4 +154,48 @@ 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); + } +} + +std::vector<JID> SQLiteHistoryManager::getAllContacts() const { + std::string query("SELECT conversations.'id' FROM conversations"); + 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); + std::vector<JID> result; + while (r == SQLITE_ROW) { + boost::optional<JID> contactJID(getJIDFromID(sqlite3_column_int(selectStatement, 0))); + if (contactJID) { + result.push_back(*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 ffd9492..ff82f5e 100644 --- a/Swiften/History/SQLiteHistoryManager.h +++ b/Swiften/History/SQLiteHistoryManager.h @@ -18,16 +18,18 @@ namespace Swift { SQLiteHistoryManager(const std::string& file); ~SQLiteHistoryManager(); - virtual void addMessage(const HistoryMessage& message); - virtual std::vector<HistoryMessage> getMessages() const; + void addMessage(const HistoryMessage& message); + std::vector<HistoryMessage> getMessages(const JID&) const; + std::vector<JID> getAllContacts() 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; - private: sqlite3* db_; }; } |