From 9e57b31133edad6a543da05aca54ee94d589b090 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Fri, 27 Apr 2012 15:58:37 +0100
Subject: Reset state of collapsing presence when a chat window is cleared.

To stop new presence being lost because it's trying to append to old (deleted) data.

Resolves: #925

diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 3f16071..5a18a98 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -91,6 +91,10 @@ ChatController::~ChatController() {
 	delete chatStateTracker_;
 }
 
+void ChatController::cancelReplaces() {
+	lastWasPresence_ = false;
+}
+
 void ChatController::handleBareJIDCapsChanged(const JID& /*jid*/) {
 	DiscoInfo::ref disco = entityCapsProvider_->getCaps(toJID_);
 	if (disco) {
diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h
index 2a66772..00d167e 100644
--- a/Swift/Controllers/Chat/ChatController.h
+++ b/Swift/Controllers/Chat/ChatController.h
@@ -31,6 +31,9 @@ namespace Swift {
 			virtual void handleNewFileTransferController(FileTransferController* ftc);
 			virtual void setContactIsReceivingPresence(bool /*isReceivingPresence*/);
 
+		protected:
+			void cancelReplaces();
+
 		private:
 			void handlePresenceChange(boost::shared_ptr<Presence> newPresence);
 			std::string getStatusChangeString(boost::shared_ptr<Presence> presence);
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp
index 583a102..3ff52a6 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.cpp
+++ b/Swift/Controllers/Chat/ChatControllerBase.cpp
@@ -37,6 +37,7 @@ ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaCha
 	chatWindow_ = chatWindowFactory_->createChatWindow(toJID, eventStream);
 	chatWindow_->onAllMessagesRead.connect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this));
 	chatWindow_->onSendMessageRequest.connect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1, _2));
+	chatWindow_->onLogCleared.connect(boost::bind(&ChatControllerBase::handleLogCleared, this));
 	entityCapsProvider_->onCapsChanged.connect(boost::bind(&ChatControllerBase::handleCapsChanged, this, _1));
 	setOnline(stanzaChannel->isAvailable() && iqRouter->isAvailable());
 	createDayChangeTimer();
@@ -46,6 +47,10 @@ ChatControllerBase::~ChatControllerBase() {
 	delete chatWindow_;
 }
 
+void ChatControllerBase::handleLogCleared() {
+	cancelReplaces();
+}
+
 void ChatControllerBase::handleCapsChanged(const JID& jid) {
 	if (jid.compare(toJID_, JID::WithoutResource) == 0) {
 		handleBareJIDCapsChanged(jid);
diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h
index 7dd339c..8654311 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.h
+++ b/Swift/Controllers/Chat/ChatControllerBase.h
@@ -75,6 +75,7 @@ namespace Swift {
 			virtual void handleBareJIDCapsChanged(const JID& jid) = 0;
 			std::string getErrorMessage(boost::shared_ptr<ErrorPayload>);
 			virtual void setContactIsReceivingPresence(bool /* isReceivingPresence */) {}
+			virtual void cancelReplaces() = 0;
 
 		private:
 			IDGenerator idGenerator_;
@@ -87,6 +88,7 @@ namespace Swift {
 			void handleMUCInvitation(Message::ref message);
 			void handleMediatedMUCInvitation(Message::ref message);
 			void handleGeneralMUCInvitation(MUCInviteEvent::ref event);
+			void handleLogCleared();
 
 		protected:
 			JID selfJID_;
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 3386877..e4209f4 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -114,6 +114,10 @@ MUCController::~MUCController() {
 	delete completer_;
 }
 
+void MUCController::cancelReplaces() {
+	lastWasPresence_ = false;
+}
+
 void MUCController::handleWindowOccupantSelectionChanged(ContactRosterItem* item) {
 	std::vector<ChatWindow::OccupantAction> actions;
 
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index c2a5103..9550ca9 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -61,6 +61,7 @@ namespace Swift {
 			boost::optional<boost::posix_time::ptime> getMessageTimestamp(boost::shared_ptr<Message> message) const;
 			void preHandleIncomingMessage(boost::shared_ptr<MessageEvent>);
 			void postHandleIncomingMessage(boost::shared_ptr<MessageEvent>);
+			void cancelReplaces();
 
 		private:
 			void setAvailableRoomActions(const MUCOccupant::Affiliation& affiliation, const MUCOccupant::Role& role);
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index 2986de1..b5b1604 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -1,11 +1,10 @@
 /*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
 
-#ifndef SWIFTEN_CHATWINDOW_H
-#define SWIFTEN_CHATWINDOW_H
+#pragma once
 
 #include <boost/optional.hpp>
 #include "Swiften/Base/boost_bsignals.h"
@@ -123,6 +122,7 @@ namespace Swift {
 			boost::signal<void ()> onGetAffiliationsRequest;
 			boost::signal<void (MUCOccupant::Affiliation, const JID&)> onSetAffiliationRequest;
 			boost::signal<void (const std::vector<std::pair<MUCOccupant::Affiliation, JID> >& changes)> onChangeAffiliationsRequest;
+			boost::signal<void ()> onLogCleared;
 			
 			// File transfer related
 			boost::signal<void (std::string /* id */)> onFileTransferCancel;
@@ -131,5 +131,4 @@ namespace Swift {
 			boost::signal<void (std::string /* path */)> onSendFileRequest;
 	};
 }
-#endif
 
diff --git a/Swift/QtUI/QtChatView.cpp b/Swift/QtUI/QtChatView.cpp
index e1d718f..54bce09 100644
--- a/Swift/QtUI/QtChatView.cpp
+++ b/Swift/QtUI/QtChatView.cpp
@@ -76,6 +76,7 @@ void QtChatView::handleClearRequested() {
 	messageBox.setDefaultButton(QMessageBox::Yes);
 	int button = messageBox.exec();
 	if (button == QMessageBox::Yes) {
+		logCleared();
 		resetView();
 	}
 }
diff --git a/Swift/QtUI/QtChatView.h b/Swift/QtUI/QtChatView.h
index 6b40c05..2e64593 100644
--- a/Swift/QtUI/QtChatView.h
+++ b/Swift/QtUI/QtChatView.h
@@ -47,6 +47,7 @@ namespace Swift {
 		signals:
 			void gotFocus();
 			void fontResized(int);
+			void logCleared();
 
 		public slots:
 			void copySelectionToClipboard();
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index ed134aa..1a82a66 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -164,6 +164,7 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt
 	connect(messageLog_, SIGNAL(gotFocus()), input_, SLOT(setFocus()));
 	resize(400,300);
 	connect(messageLog_, SIGNAL(fontResized(int)), this, SIGNAL(fontResized(int)));
+	connect(messageLog_, SIGNAL(logCleared()), this, SLOT(handleLogCleared()));
 
 	treeWidget_->onSomethingSelectedChanged.connect(boost::bind(&QtChatWindow::handleOccupantSelectionChanged, this, _1));
 	treeWidget_->onOccupantActionSelected.connect(boost::bind(boost::ref(onOccupantActionSelected), _1, _2));
@@ -180,6 +181,9 @@ QtChatWindow::~QtChatWindow() {
 	}
 }
 
+void QtChatWindow::handleLogCleared() {
+	onLogCleared();
+}
 
 void QtChatWindow::handleOccupantSelectionChanged(RosterItem* item) {
 	onOccupantSelectionChanged(dynamic_cast<ContactRosterItem*>(item));
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index 1d1959d..4b888eb 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -118,6 +118,7 @@ namespace Swift {
 			void showEvent(QShowEvent* event);
 
 		private slots:
+			void handleLogCleared();
 			void returnPressed();
 			void handleInputChanged();
 			void handleCursorPositionChanged();
-- 
cgit v0.10.2-6-g49f6