ircnicknamecompleter.cpp
1 //------------------------------------------------------------------------------
2 // ircnicknamecompleter.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library 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 GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301 USA
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2014 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "ircnicknamecompleter.h"
24 
25 #include "gui/irc/ircuserlistmodel.h"
26 
27 #include <QCompleter>
28 #include <QRegExp>
29 
30 class IRCNicknameCompleterState
31 {
32 public:
33  int cursorPos;
34  QString textLine;
35 
36  IRCNicknameCompleterState()
37  {
38  cursorPos = -1;
39  }
40 
41  QString extractNicknamePrefix() const
42  {
43  const QString NICKNAME_MATCH = R"(\[\]\{\}\-\^\`\|\\A-Za-z0-9_)";
44  QRegExp regex(QString("(?:.*)[^%1]?([%1]*)").arg(NICKNAME_MATCH));
45  regex.setCaseSensitivity(Qt::CaseInsensitive);
46  regex.setMinimal(false);
47  regex.indexIn(leftText());
48  return regex.cap(1);
49  }
50 
51  bool isValid() const
52  {
53  return cursorPos >= 0;
54  }
55 
56  QString leftText() const
57  {
58  return textLine.left(cursorPos);
59  }
60 
61  QString leftTextMinusNicknamePrefix() const
62  {
63  return textLine.left(cursorPos - extractNicknamePrefix().length());
64  }
65 
66  QString rightText() const
67  {
68  return textLine.mid(cursorPos);
69  }
70 };
71 
72 DClass<IRCNicknameCompleter>
73 {
74 public:
75  QCompleter completer;
76  IRCNicknameCompleterState state;
77 
78  IRCCompletionResult complete()
79  {
80  IRCCompletionResult result;
81  if (!completer.currentCompletion().isEmpty())
82  {
83  result.textLine = leftTextWithCompletedNickname() + state.rightText();
84  result.cursorPos = leftTextWithCompletedNickname().length();
85  }
86  return result;
87  }
88 
89  QString leftTextWithCompletedNickname() const
90  {
91  return state.leftTextMinusNicknamePrefix() + completer.currentCompletion();
92  }
93 };
94 
95 DPointeredNoCopy(IRCNicknameCompleter)
96 
98 {
99  d->completer.setCaseSensitivity(Qt::CaseInsensitive);
100  d->completer.setCompletionRole(IRCUserListModel::RoleCleanNickname);
101 }
102 
103 IRCNicknameCompleter::~IRCNicknameCompleter()
104 {
105 }
106 
108  int cursorPosition)
109 {
110  d->state = IRCNicknameCompleterState();
111  d->state.cursorPos = cursorPosition;
112  d->state.textLine = textLine;
113 
114  QString nickPrefix = d->state.extractNicknamePrefix();
115  d->completer.setCompletionPrefix(nickPrefix);
116  return d->complete();
117 }
118 
119 IRCCompletionResult IRCNicknameCompleter::cycleNext()
120 {
121  if (d->completer.completionCount() == 0)
122  return IRCCompletionResult();
123  if (d->completer.currentRow() + 1 >= d->completer.completionCount())
124  d->completer.setCurrentRow(0);
125  else
126  d->completer.setCurrentRow(d->completer.currentRow() + 1);
127  return d->complete();
128 }
129 
130 bool IRCNicknameCompleter::isReset() const
131 {
132  return !d->state.isValid();
133 }
134 
135 void IRCNicknameCompleter::reset()
136 {
137  d->state = IRCNicknameCompleterState();
138 }
139 
140 void IRCNicknameCompleter::setModel(QAbstractItemModel *model)
141 {
142  d->completer.setModel(model);
143 }