From 168405b68c8ce2dd174c86ce3938fbabff93efd7 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Mon, 4 Oct 2010 11:26:17 +0100
Subject: Fix chat logs scrolling to bottom.

(bug introduced since beta6)

Resolves: #591

diff --git a/Swift/QtUI/QtChatView.cpp b/Swift/QtUI/QtChatView.cpp
index 1ad274f..70bb0e8 100644
--- a/Swift/QtUI/QtChatView.cpp
+++ b/Swift/QtUI/QtChatView.cpp
@@ -44,15 +44,13 @@ QtChatView::QtChatView(QtChatTheme* theme, QWidget* parent) : QWidget(parent) {
 	mainLayout->addWidget(webView_);
 #endif
 
-
-	
-
 	webPage_ = new QWebPage(this);
 	webPage_->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
 	webView_->setPage(webPage_);
 	connect(webPage_, SIGNAL(selectionChanged()), SLOT(copySelectionToClipboard()));
 
 	viewReady_ = false;
+	isAtBottom_ = true;
 	resetView();
 }
 
@@ -76,7 +74,7 @@ QWebElement QtChatView::snippetToDOM(boost::shared_ptr<ChatSnippet> snippet) {
 }
 
 void QtChatView::addToDOM(boost::shared_ptr<ChatSnippet> snippet) {
-	bool bottom = isScrolledToBottom();
+	rememberScrolledToBottom();
 	QWebElement newElement = snippetToDOM(snippet);
 	QWebElement continuationElement = lastElement_.findFirst("#insert");
 	if (snippet->getAppendToPrevious()) {
@@ -87,27 +85,21 @@ void QtChatView::addToDOM(boost::shared_ptr<ChatSnippet> snippet) {
 		newInsertPoint_.prependOutside(newElement);
 	}
 	lastElement_ = newElement;
-	if (bottom) {
-		/* Warning: I'm not confident about this, although it does work.*/
-		QTimer::singleShot(0, this, SLOT(scrollToBottom()));
-	}
 }
 
 void QtChatView::replaceLastMessage(const QString& newMessage) {
 	assert(viewReady_);
 	/* FIXME: must be queued? */
-	bool bottom = isScrolledToBottom();
+	rememberScrolledToBottom();
 	assert(!lastElement_.isNull());
 	QWebElement replace = lastElement_.findFirst("span.swift_message");
 	assert(!replace.isNull());
 	QString old = lastElement_.toOuterXml();
 	replace.setInnerXml(ChatSnippet::escape(newMessage));
-	if (bottom) {
-		QTimer::singleShot(0, this, SLOT(scrollToBottom()));
-	}
 }
 
 void QtChatView::replaceLastMessage(const QString& newMessage, const QString& note) {
+	rememberScrolledToBottom();
 	replaceLastMessage(newMessage);
 	QWebElement replace = lastElement_.findFirst("span.swift_time");
 	assert(!replace.isNull());
@@ -129,14 +121,21 @@ void QtChatView::setAckXML(const QString& id, const QString& xml) {
 	ackElement.setInnerXml(xml);
 }
 
-bool QtChatView::isScrolledToBottom() const {
-	return webPage_->mainFrame()->scrollBarValue(Qt::Vertical) == webPage_->mainFrame()->scrollBarMaximum(Qt::Vertical);
+void QtChatView::rememberScrolledToBottom() {
+	isAtBottom_ = webPage_->mainFrame()->scrollBarValue(Qt::Vertical) == webPage_->mainFrame()->scrollBarMaximum(Qt::Vertical);
 }
 
 void QtChatView::scrollToBottom() {
+	isAtBottom_ = true;
 	webPage_->mainFrame()->setScrollBarValue(Qt::Vertical, webPage_->mainFrame()->scrollBarMaximum(Qt::Vertical));
 }
 
+void QtChatView::handleFrameSizeChanged() {
+	if (isAtBottom_) {
+		scrollToBottom();
+	}
+}
+
 void QtChatView::handleLinkClicked(const QUrl& url) {
 	QDesktopServices::openUrl(url);
 }
@@ -180,6 +179,8 @@ void QtChatView::resetView() {
 	newInsertPoint_.setOuterXml("<div id='swift_insert'/>");
 	chatElement.appendInside(newInsertPoint_);
 	Q_ASSERT(!newInsertPoint_.isNull());
+
+	connect(webPage_->mainFrame(), SIGNAL(contentsSizeChanged(const QSize&)), this, SLOT(handleFrameSizeChanged()), Qt::UniqueConnection);
 }
 
 }
diff --git a/Swift/QtUI/QtChatView.h b/Swift/QtUI/QtChatView.h
index 8c1a99a..84738d4 100644
--- a/Swift/QtUI/QtChatView.h
+++ b/Swift/QtUI/QtChatView.h
@@ -30,7 +30,7 @@ namespace Swift {
 			void addMessage(boost::shared_ptr<ChatSnippet> snippet);
 			void replaceLastMessage(const QString& newMessage);
 			void replaceLastMessage(const QString& newMessage, const QString& note);
-			bool isScrolledToBottom() const;
+			void rememberScrolledToBottom();
 			void setAckXML(const QString& id, const QString& xml);
 
 		signals:
@@ -45,6 +45,7 @@ namespace Swift {
 
 		private slots:
 			void handleViewLoadFinished(bool);
+			void handleFrameSizeChanged();
 
 		private:
 			void headerEncode();
@@ -54,6 +55,7 @@ namespace Swift {
 			QWebElement snippetToDOM(boost::shared_ptr<ChatSnippet> snippet);
 
 			bool viewReady_;
+			bool isAtBottom_;
 			QtWebView* webView_;
 			QWebPage* webPage_;
 			QList<boost::shared_ptr<ChatSnippet> > queuedSnippets_;
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index 6913747..a71cd43 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -349,8 +349,8 @@ void QtChatWindow::returnPressed() {
 	if (!inputEnabled_) {
 		return;
 	}
-	onSendMessageRequest(Q2PSTRING(input_->toPlainText()));
 	messageLog_->scrollToBottom();
+	onSendMessageRequest(Q2PSTRING(input_->toPlainText()));
 	inputClearing_ = true;
 	input_->clear();
 	inputClearing_ = false;
-- 
cgit v0.10.2-6-g49f6