/***************************************************************************
- * Copyright (C) 2005/06 by the Quassel IRC Team *
+ * Copyright (C) 2005/06 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "tabcompleter.h"
-TabCompleter::TabCompleter(QLineEdit *l, QObject *parent) : QObject(parent) {
- lineEdit = l;
- enabled = false;
- startOfLineSuffix = QString(": "); // TODO make start of line suffix configurable
-}
+#include "inputline.h"
+#include "client.h"
+#include "buffermodel.h"
+#include "networkmodel.h"
+#include "network.h"
+#include "ircchannel.h"
+#include "ircuser.h"
+#include "uisettings.h"
-void TabCompleter::updateNickList(QStringList l) {
- nickList = l;
-}
+#include <QRegExp>
-void TabCompleter::updateChannelList(QStringList l) {
- channelList = l;
+TabCompleter::TabCompleter(InputLine *inputLine_)
+ : QObject(inputLine_),
+ inputLine(inputLine_),
+ enabled(false),
+ nickSuffix(": ")
+{
+ inputLine->installEventFilter(this);
}
void TabCompleter::buildCompletionList() {
+ // ensure a safe state in case we return early.
+ completionMap.clear();
+ nextCompletion = completionMap.begin();
+
// this is the first time tab is pressed -> build up the completion list and it's iterator
- QString tabAbbrev = lineEdit->text().left(lineEdit->cursorPosition()).section(' ',-1,-1);
- completionList.clear();
- foreach(QString nick, nickList) {
- if(nick.toLower().startsWith(tabAbbrev.toLower())) {
- completionList << nick;
+ QModelIndex currentIndex = Client::bufferModel()->currentIndex();
+ if(!currentIndex.data(NetworkModel::BufferIdRole).isValid())
+ return;
+
+ NetworkId networkId = currentIndex.data(NetworkModel::NetworkIdRole).value<NetworkId>();
+ QString bufferName = currentIndex.sibling(currentIndex.row(), 0).data().toString();
+
+ const Network *network = Client::network(networkId);
+ if(!network)
+ return;
+
+
+ QString tabAbbrev = inputLine->text().left(inputLine->cursorPosition()).section(' ',-1,-1);
+ QRegExp regex(QString("^[^a-zA-Z]*").append(QRegExp::escape(tabAbbrev)), Qt::CaseInsensitive);
+
+ switch(static_cast<BufferInfo::Type>(currentIndex.data(NetworkModel::BufferTypeRole).toInt())) {
+ case BufferInfo::ChannelBuffer:
+ { // scope is needed for local var declaration
+ IrcChannel *channel = network->ircChannel(bufferName);
+ if(!channel)
+ return;
+ foreach(IrcUser *ircUser, channel->ircUsers()) {
+ if(regex.indexIn(ircUser->nick()) > -1)
+ completionMap[ircUser->nick().toLower()] = ircUser->nick();
+ }
}
+ break;
+ case BufferInfo::QueryBuffer:
+ if(regex.indexIn(bufferName) > -1)
+ completionMap[bufferName.toLower()] = bufferName;
+ case BufferInfo::StatusBuffer:
+ if(!network->myNick().isEmpty() && regex.indexIn(network->myNick()) > -1)
+ completionMap[network->myNick().toLower()] = network->myNick();
+ break;
+ default:
+ return;
}
- completionList.sort();
- nextCompletion = completionList.begin();
+
+ nextCompletion = completionMap.begin();
lastCompletionLength = tabAbbrev.length();
}
+void TabCompleter::ircUserJoinedOrParted(IrcUser *ircUser) {
+ Q_UNUSED(ircUser)
+ buildCompletionList();
+}
+
void TabCompleter::complete() {
- if (! enabled) {
+ UiSettings uiSettings;
+ nickSuffix = uiSettings.value("CompletionSuffix", QString(": ")).toString();
+
+ if(!enabled) {
buildCompletionList();
- enabled = true;
+ enabled = true;
}
- if (nextCompletion != completionList.end()) {
+ if (nextCompletion != completionMap.end()) {
// clear previous completion
for (int i = 0; i < lastCompletionLength; i++) {
- lineEdit->backspace();
+ inputLine->backspace();
}
// insert completion
- lineEdit->insert(*nextCompletion);
+ inputLine->insert(*nextCompletion);
// remember charcount to delete next time and advance to next completion
lastCompletionLength = nextCompletion->length();
nextCompletion++;
// we're completing the first word of the line
- if(lineEdit->text().length() == lastCompletionLength) {
- lineEdit->insert(startOfLineSuffix);
- lastCompletionLength += 2;
+ if(inputLine->cursorPosition() == lastCompletionLength) {
+ inputLine->insert(nickSuffix);
+ lastCompletionLength += nickSuffix.length();
}
// we're at the end of the list -> start over again
} else {
- nextCompletion = completionList.begin();
+ if(!completionMap.isEmpty()) {
+ nextCompletion = completionMap.begin();
+ complete();
+ }
}
}
-void TabCompleter::disable() {
+void TabCompleter::reset() {
enabled = false;
}
+bool TabCompleter::eventFilter(QObject *obj, QEvent *event) {
+ if(obj != inputLine || event->type() != QEvent::KeyPress)
+ return QObject::eventFilter(obj, event);
+
+ QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
+
+ if(keyEvent->key() == Qt::Key_Tab) {
+ complete();
+ return true;
+ } else {
+ reset();
+ return false;
+ }
+}
+