1 /***************************************************************************
2 * Copyright (C) 2005/06 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "tabcompleter.h"
23 #include "inputline.h"
25 #include "buffermodel.h"
26 #include "networkmodel.h"
28 #include "ircchannel.h"
30 #include "uisettings.h"
34 TabCompleter::TabCompleter(InputLine *inputLine_)
35 : QObject(inputLine_),
36 inputLine(inputLine_),
40 inputLine->installEventFilter(this);
43 void TabCompleter::buildCompletionList() {
44 // ensure a safe state in case we return early.
45 completionMap.clear();
46 nextCompletion = completionMap.begin();
48 // this is the first time tab is pressed -> build up the completion list and it's iterator
49 QModelIndex currentIndex = Client::bufferModel()->currentIndex();
50 if(!currentIndex.data(NetworkModel::BufferIdRole).isValid())
53 NetworkId networkId = currentIndex.data(NetworkModel::NetworkIdRole).value<NetworkId>();
54 QString bufferName = currentIndex.sibling(currentIndex.row(), 0).data().toString();
56 const Network *network = Client::network(networkId);
61 QString tabAbbrev = inputLine->text().left(inputLine->cursorPosition()).section(' ',-1,-1);
62 QRegExp regex(QString("^[^a-zA-Z]*").append(QRegExp::escape(tabAbbrev)), Qt::CaseInsensitive);
64 switch(static_cast<BufferInfo::Type>(currentIndex.data(NetworkModel::BufferTypeRole).toInt())) {
65 case BufferInfo::ChannelBuffer:
66 { // scope is needed for local var declaration
67 IrcChannel *channel = network->ircChannel(bufferName);
70 foreach(IrcUser *ircUser, channel->ircUsers()) {
71 if(regex.indexIn(ircUser->nick()) > -1)
72 completionMap[ircUser->nick().toLower()] = ircUser->nick();
76 case BufferInfo::QueryBuffer:
77 if(regex.indexIn(bufferName) > -1)
78 completionMap[bufferName.toLower()] = bufferName;
79 case BufferInfo::StatusBuffer:
80 if(!network->myNick().isEmpty() && regex.indexIn(network->myNick()) > -1)
81 completionMap[network->myNick().toLower()] = network->myNick();
87 nextCompletion = completionMap.begin();
88 lastCompletionLength = tabAbbrev.length();
91 void TabCompleter::ircUserJoinedOrParted(IrcUser *ircUser) {
93 buildCompletionList();
96 void TabCompleter::complete() {
97 UiSettings uiSettings;
98 nickSuffix = uiSettings.value("CompletionSuffix", QString(": ")).toString();
101 buildCompletionList();
105 if (nextCompletion != completionMap.end()) {
106 // clear previous completion
107 for (int i = 0; i < lastCompletionLength; i++) {
108 inputLine->backspace();
112 inputLine->insert(*nextCompletion);
114 // remember charcount to delete next time and advance to next completion
115 lastCompletionLength = nextCompletion->length();
118 // we're completing the first word of the line
119 if(inputLine->cursorPosition() == lastCompletionLength) {
120 inputLine->insert(nickSuffix);
121 lastCompletionLength += nickSuffix.length();
124 // we're at the end of the list -> start over again
126 if(!completionMap.isEmpty()) {
127 nextCompletion = completionMap.begin();
134 void TabCompleter::reset() {
138 bool TabCompleter::eventFilter(QObject *obj, QEvent *event) {
139 if(obj != inputLine || event->type() != QEvent::KeyPress)
140 return QObject::eventFilter(obj, event);
142 QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
144 if(keyEvent->key() == Qt::Key_Tab) {