From d4517116fc71d1b2d5967004757630293613e928 Mon Sep 17 00:00:00 2001
From: Catalin Badea <catalin.badea392@gmail.com>
Date: Fri, 13 Apr 2012 22:49:39 +0300
Subject: Improve tab completion

Remember last tab completion suggestion and use it for cycling through all completion candidates.

Resolves: #1070

License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details.

diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index cf520ee..5223ddb 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -149,10 +149,12 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt
 
 	inputClearing_ = false;
 	contactIsTyping_ = false;
+	tabCompletion_ = false;
 
 	connect(input_, SIGNAL(unhandledKeyPressEvent(QKeyEvent*)), this, SLOT(handleKeyPressEvent(QKeyEvent*)));
 	connect(input_, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
 	connect(input_, SIGNAL(textChanged()), this, SLOT(handleInputChanged()));
+	connect(input_, SIGNAL(cursorPositionChanged()), this, SLOT(handleCursorPositionChanged()));
 	setFocusProxy(input_);
 	logRosterSplitter_->setFocusProxy(input_);
 	midBar->setFocusProxy(input_);
@@ -288,11 +290,15 @@ void QtChatWindow::tabComplete() {
 	if (!completer_) {
 		return;
 	}
-//	QTextDocument* document = input_->document();
-	QTextCursor cursor = input_->textCursor();
-	cursor.select(QTextCursor::WordUnderCursor);
+
+	QTextCursor cursor;
+	if (tabCompleteCursor_.hasSelection()) {
+		cursor = tabCompleteCursor_;
+	} else {
+		cursor = input_->textCursor();
+		cursor.select(QTextCursor::WordUnderCursor);
+	}
 	QString root = cursor.selectedText();
-	bool firstWord = cursor.selectionStart() == 0;
 	if (root.isEmpty()) {
 		return;
 	}
@@ -300,14 +306,17 @@ void QtChatWindow::tabComplete() {
 	if (root == suggestion) {
 		return;
 	}
+	tabCompletion_ = true;
 	cursor.beginEditBlock();
 	cursor.removeSelectedText();
+	int oldPosition = cursor.position();
+
 	cursor.insertText(suggestion);
-	if (firstWord) {
-		//	cursor.insertText(":");
-	}
-	//cursor.insertText(" ");
+	tabCompleteCursor_ = cursor;
+	tabCompleteCursor_.setPosition(oldPosition, QTextCursor::KeepAnchor);
+
 	cursor.endEditBlock();
+	tabCompletion_ = false;
 }
 
 void QtChatWindow::setRosterModel(Roster* roster) {
@@ -699,6 +708,13 @@ void QtChatWindow::handleInputChanged() {
 	}
 }
 
+void QtChatWindow::handleCursorPositionChanged() {
+	if (tabCompletion_) {
+		return;
+	}
+	tabCompleteCursor_.clearSelection();
+}
+
 void QtChatWindow::show() {
 	if (parentWidget() == NULL) {
 		QWidget::show();
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index 18eb092..9db1884 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -16,6 +16,7 @@
 
 #include <map>
 #include <QPointer>
+#include <QTextCursor>
 
 class QTextEdit;
 class QLineEdit;
@@ -118,6 +119,7 @@ namespace Swift {
 		private slots:
 			void returnPressed();
 			void handleInputChanged();
+			void handleCursorPositionChanged();
 			void handleKeyPressEvent(QKeyEvent* event);
 			void handleSplitterMoved(int pos, int index);
 			void handleAlertButtonClicked();
@@ -150,6 +152,7 @@ namespace Swift {
 			LastLineTracker lastLineTracker_;
 			QString contact_;
 			QString lastSentMessage_;
+			QTextCursor tabCompleteCursor_;
 			QtChatView* messageLog_;
 			QtChatTheme* theme_;
 			QtTextEdit* input_;
@@ -168,6 +171,7 @@ namespace Swift {
 			PreviousMessageKind previousMessageKind_;
 			QString previousSenderName_;
 			bool inputClearing_;
+			bool tabCompletion_;
 			UIEventStream* eventStream_;
 			bool inputEnabled_;
 			QSplitter *logRosterSplitter_;
-- 
cgit v0.10.2-6-g49f6