1 #include "lineeditcompleter.h"
2 
3 #include <QAbstractItemView>
4 #include <QCompleter>
5 #include <QFocusEvent>
6 #include <QKeyEvent>
7 #include <QScrollBar>
8 #include <QStringListModel>
9 #include <QTextCursor>
10 #include <QWidget>
11 
LineEditCompleter(QWidget * parent)12 LineEditCompleter::LineEditCompleter(QWidget *parent) : LineEditUnfocusable(parent), c(nullptr)
13 {
14 }
15 
focusOutEvent(QFocusEvent * e)16 void LineEditCompleter::focusOutEvent(QFocusEvent *e)
17 {
18     LineEditUnfocusable::focusOutEvent(e);
19     if (c->popup()->isVisible()) {
20         // Remove Popup
21         c->popup()->hide();
22         // Truncate the line to last space or whole string
23         QString textValue = text();
24         int lastIndex = textValue.length();
25         int lastWordStartIndex = textValue.lastIndexOf(" ") + 1;
26         int leftShift = qMin(lastIndex, lastWordStartIndex);
27         setText(textValue.left(leftShift));
28         // Insert highlighted line from popup
29         insert(c->completionModel()->index(c->popup()->currentIndex().row(), 0).data().toString() + " ");
30         // Set focus back to the textbox since tab was pressed
31         setFocus();
32     }
33 }
34 
keyPressEvent(QKeyEvent * event)35 void LineEditCompleter::keyPressEvent(QKeyEvent *event)
36 {
37     switch (event->key()) {
38         case Qt::Key_Return:
39         case Qt::Key_Enter:
40         case Qt::Key_Escape:
41             if (c->popup()->isVisible()) {
42                 event->ignore();
43                 // Remove Popup
44                 c->popup()->hide();
45                 // Truncate the line to last space or whole string
46                 QString textValue = text();
47                 int lastIndexof = qMax(0, textValue.lastIndexOf(" "));
48                 QString finalString = textValue.left(lastIndexof);
49                 // Add a space if there's a word
50                 if (finalString != "")
51                     finalString += " ";
52                 setText(finalString);
53                 return;
54             }
55             break;
56         case Qt::Key_Space:
57             if (c->popup()->isVisible()) {
58                 event->ignore();
59                 // Remove Popup
60                 c->popup()->hide();
61                 // Truncate the line to last space or whole string
62                 QString textValue = text();
63                 int lastIndex = textValue.length();
64                 int lastWordStartIndex = textValue.lastIndexOf(" ") + 1;
65                 int leftShift = qMin(lastIndex, lastWordStartIndex);
66                 setText(textValue.left(leftShift));
67                 // Insert highlighted line from popup
68                 insert(c->completionModel()->index(c->popup()->currentIndex().row(), 0).data().toString() + " ");
69                 return;
70             }
71             break;
72         default:
73             break;
74     }
75 
76     LineEditUnfocusable::keyPressEvent(event);
77     // return if the completer is null or if the most recently typed char was '@'.
78     // Only want the popup AFTER typing the first char of the mention.
79     if (!c || text().right(1).contains("@")) {
80         c->popup()->hide();
81         return;
82     }
83 
84     // Set new completion prefix
85     c->setCompletionPrefix(cursorWord(text()));
86     if (c->completionPrefix().length() < 1) {
87         c->popup()->hide();
88         return;
89     }
90 
91     // Draw completion box
92     QRect cr = cursorRect();
93     cr.setWidth(c->popup()->sizeHintForColumn(0) + c->popup()->verticalScrollBar()->sizeHint().width());
94     c->complete(cr);
95 
96     // Select first item in the completion popup
97     QItemSelectionModel *sm = new QItemSelectionModel(c->completionModel());
98     c->popup()->setSelectionModel(sm);
99     sm->select(c->completionModel()->index(0, 0), QItemSelectionModel::ClearAndSelect);
100     sm->setCurrentIndex(c->completionModel()->index(0, 0), QItemSelectionModel::NoUpdate);
101 }
102 
cursorWord(const QString & line) const103 QString LineEditCompleter::cursorWord(const QString &line) const
104 {
105     return line.mid(line.left(cursorPosition()).lastIndexOf(" ") + 1,
106                     cursorPosition() - line.left(cursorPosition()).lastIndexOf(" ") - 1);
107 }
108 
insertCompletion(QString arg)109 void LineEditCompleter::insertCompletion(QString arg)
110 {
111     QString s_arg = arg + " ";
112     setText(text().replace(text().left(cursorPosition()).lastIndexOf(" ") + 1,
113                            cursorPosition() - text().left(cursorPosition()).lastIndexOf(" ") - 1, s_arg));
114 }
115 
setCompleter(QCompleter * completer)116 void LineEditCompleter::setCompleter(QCompleter *completer)
117 {
118     c = completer;
119     c->setWidget(this);
120     connect(c, SIGNAL(activated(QString)), this, SLOT(insertCompletion(QString)));
121 }
122 
setCompletionList(QStringList completionList)123 void LineEditCompleter::setCompletionList(QStringList completionList)
124 {
125     if (!c || c->popup()->isVisible())
126         return;
127 
128     QStringListModel *model;
129     model = (QStringListModel *)(c->model());
130     if (model == NULL)
131         model = new QStringListModel();
132     model->setStringList(completionList);
133 }
134