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 <QRegularExpression>
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  QRegularExpression regex(QString("(?:.*)[^%1]?([%1]*)").arg(NICKNAME_MATCH), QRegularExpression::CaseInsensitiveOption);
45  return regex.match(leftText()).captured(1);
46  }
47 
48  bool isValid() const
49  {
50  return cursorPos >= 0;
51  }
52 
53  QString leftText() const
54  {
55  return textLine.left(cursorPos);
56  }
57 
58  QString leftTextMinusNicknamePrefix() const
59  {
60  return textLine.left(cursorPos - extractNicknamePrefix().length());
61  }
62 
63  QString rightText() const
64  {
65  return textLine.mid(cursorPos);
66  }
67 };
68 
69 DClass<IRCNicknameCompleter>
70 {
71 public:
72  QCompleter completer;
73  IRCNicknameCompleterState state;
74 
75  IRCCompletionResult complete()
76  {
77  IRCCompletionResult result;
78  if (!completer.currentCompletion().isEmpty())
79  {
80  result.textLine = leftTextWithCompletedNickname() + state.rightText();
81  result.cursorPos = leftTextWithCompletedNickname().length();
82  }
83  return result;
84  }
85 
86  QString leftTextWithCompletedNickname() const
87  {
88  return state.leftTextMinusNicknamePrefix() + completer.currentCompletion();
89  }
90 };
91 
92 DPointeredNoCopy(IRCNicknameCompleter)
93 
95 {
96  d->completer.setCaseSensitivity(Qt::CaseInsensitive);
97  d->completer.setCompletionRole(IRCUserListModel::RoleCleanNickname);
98 }
99 
100 IRCNicknameCompleter::~IRCNicknameCompleter()
101 {
102 }
103 
105  int cursorPosition)
106 {
107  d->state = IRCNicknameCompleterState();
108  d->state.cursorPos = cursorPosition;
109  d->state.textLine = textLine;
110 
111  QString nickPrefix = d->state.extractNicknamePrefix();
112  d->completer.setCompletionPrefix(nickPrefix);
113  return d->complete();
114 }
115 
116 IRCCompletionResult IRCNicknameCompleter::cycleNext()
117 {
118  if (d->completer.completionCount() == 0)
119  return IRCCompletionResult();
120  if (d->completer.currentRow() + 1 >= d->completer.completionCount())
121  d->completer.setCurrentRow(0);
122  else
123  d->completer.setCurrentRow(d->completer.currentRow() + 1);
124  return d->complete();
125 }
126 
127 bool IRCNicknameCompleter::isReset() const
128 {
129  return !d->state.isValid();
130 }
131 
132 void IRCNicknameCompleter::reset()
133 {
134  d->state = IRCNicknameCompleterState();
135 }
136 
137 void IRCNicknameCompleter::setModel(QAbstractItemModel *model)
138 {
139  d->completer.setModel(model);
140 }