1 #include "completerwindow.h"
2 #include "ui_completerwindow.h"
3 #include "completermodel.h"
4 #include "common/unused.h"
5 #include "sqleditor.h"
6 #include "common/utils_sql.h"
7 #include <QKeyEvent>
8 #include <QListView>
9 #include <QDebug>
10
CompleterWindow(SqlEditor * parent)11 CompleterWindow::CompleterWindow(SqlEditor *parent) :
12 QDialog(parent, Qt::FramelessWindowHint),
13 ui(new Ui::CompleterWindow),
14 sqlEditor(parent)
15 {
16 ui->setupUi(this);
17 init();
18 }
19
~CompleterWindow()20 CompleterWindow::~CompleterWindow()
21 {
22 delete ui;
23 }
24
init()25 void CompleterWindow::init()
26 {
27 model = new CompleterModel(this);
28 ui->list->setModel(model);
29 model->setCompleterView(ui->list);
30
31 setFocusProxy(ui->list);
32 connect(ui->list, SIGNAL(focusOut()), this, SLOT(focusOut()));
33 connect(ui->list, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(doubleClicked(QModelIndex)));
34 connect(ui->list->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), this, SLOT(currentRowChanged(QModelIndex,QModelIndex)));
35 connect(ui->list, SIGNAL(textTyped(QString)), this, SIGNAL(textTyped(QString)));
36 connect(ui->list, SIGNAL(backspace()), this, SIGNAL(backspacePressed()));
37 connect(ui->list, SIGNAL(left()), this, SIGNAL(leftPressed()));
38 connect(ui->list, SIGNAL(right()), this, SIGNAL(rightPressed()));
39 reset();
40 }
41
reset()42 void CompleterWindow::reset()
43 {
44 model->clear();
45 ui->status->showMessage(QString());
46 }
47
setData(const CompletionHelper::Results & completionResults)48 void CompleterWindow::setData(const CompletionHelper::Results& completionResults)
49 {
50 ui->status->showMessage(QString());
51 model->setData(completionResults.expectedTokens);
52 filter = completionResults.partialToken;
53 wrappedFilter = completionResults.wrappedToken;
54 updateFilter();
55 }
56
setDb(Db * db)57 void CompleterWindow::setDb(Db* db)
58 {
59 this->db = db;
60 }
61
updateFilter()62 void CompleterWindow::updateFilter()
63 {
64 model->setFilter(filter);
65 ui->list->selectFirstVisible();
66
67 if (!ui->list->hasVisibleItem())
68 reject();
69 }
70
shringFilterBy(int chars)71 void CompleterWindow::shringFilterBy(int chars)
72 {
73 if (filter.size() < chars)
74 {
75 if (wrappedFilter && chars == 1)
76 {
77 wrappedFilter = false;
78 updateFilter();
79 return;
80 }
81
82 reject();
83 return;
84 }
85
86 filter.truncate(filter.length() - chars);
87 updateFilter();
88 }
89
extendFilterBy(const QString & text)90 void CompleterWindow::extendFilterBy(const QString& text)
91 {
92 if (filter.isEmpty() && text.size() == 1 && isWrapperChar(text[0]))
93 {
94 wrappedFilter = true;
95 updateFilter();
96 return;
97 }
98
99 filter.append(text);
100 updateFilter();
101 }
102
immediateResolution()103 bool CompleterWindow::immediateResolution()
104 {
105 if (ui->list->countVisibleItem() == 1)
106 {
107 accept();
108 return true;
109 }
110 return false;
111 }
112
getSelected()113 ExpectedTokenPtr CompleterWindow::getSelected()
114 {
115 QModelIndex current = ui->list->currentIndex();
116 if (!current.isValid())
117 return ExpectedTokenPtr();
118
119 return model->getToken(current.row());
120 }
121
getNumberOfCharsToRemove()122 int CompleterWindow::getNumberOfCharsToRemove()
123 {
124 return filter.size() + (wrappedFilter ? 1 : 0);
125 }
126
changeEvent(QEvent * e)127 void CompleterWindow::changeEvent(QEvent *e)
128 {
129 QDialog::changeEvent(e);
130 switch (e->type()) {
131 case QEvent::LanguageChange:
132 ui->retranslateUi(this);
133 break;
134 default:
135 break;
136 }
137 }
138
keyPressEvent(QKeyEvent * e)139 void CompleterWindow::keyPressEvent(QKeyEvent* e)
140 {
141 if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter)
142 {
143 accept();
144 return;
145 }
146
147 QDialog::keyPressEvent(e);
148 }
149
getStatusMsg(const QModelIndex & index)150 QString CompleterWindow::getStatusMsg(const QModelIndex& index)
151 {
152 ExpectedToken::Type type = (ExpectedToken::Type)index.data(CompleterModel::TYPE).toInt();
153 QString value = index.data(CompleterModel::VALUE).toString();
154 QString label = index.data(CompleterModel::LABEL).toString();
155
156 switch (type)
157 {
158 case ExpectedToken::COLUMN:
159 return tr("Column: %1", "completer statusbar").arg(value);
160 case ExpectedToken::TABLE:
161 return tr("Table: %1", "completer statusbar").arg(value);
162 case ExpectedToken::INDEX:
163 return tr("Index: %1", "completer statusbar").arg(value);
164 case ExpectedToken::TRIGGER:
165 return tr("Trigger: %1", "completer statusbar").arg(value);
166 case ExpectedToken::VIEW:
167 return tr("View: %1", "completer statusbar").arg(value);
168 case ExpectedToken::DATABASE:
169 return tr("Database: %1", "completer statusbar").arg(value);
170 case ExpectedToken::OTHER:
171 {
172 if (!label.isEmpty())
173 return label;
174
175 if (!value.isEmpty())
176 return value;
177
178 return "";
179 }
180 case ExpectedToken::KEYWORD:
181 return tr("Keyword: %1", "completer statusbar").arg(value);
182 case ExpectedToken::FUNCTION:
183 return tr("Function: %1", "completer statusbar").arg(value);
184 case ExpectedToken::OPERATOR:
185 return tr("Operator: %1", "completer statusbar").arg(value);
186 case ExpectedToken::STRING:
187 return tr("String", "completer statusbar");
188 case ExpectedToken::NUMBER:
189 return tr("Number", "completer statusbar").arg(value);
190 case ExpectedToken::BLOB:
191 return tr("Binary data", "completer statusbar").arg(value);
192 case ExpectedToken::COLLATION:
193 return tr("Collation: %1", "completer statusbar").arg(value);
194 case ExpectedToken::PRAGMA:
195 return tr("Pragma function: %1", "completer statusbar").arg(value);
196 case ExpectedToken::NO_VALUE:
197 {
198 if (!label.isEmpty())
199 return label;
200
201 if (!value.isEmpty())
202 return value;
203
204 return "";
205 }
206 }
207 return "";
208 }
209
focusOut()210 void CompleterWindow::focusOut()
211 {
212 QWidget* focused = QApplication::focusWidget();
213 if (!focused || focused == this || isAncestorOf(focused))
214 return;
215
216 reject();
217 }
218
doubleClicked(const QModelIndex & index)219 void CompleterWindow::doubleClicked(const QModelIndex& index)
220 {
221 UNUSED(index);
222 accept();
223 }
224
currentRowChanged(const QModelIndex & current,const QModelIndex & previous)225 void CompleterWindow::currentRowChanged(const QModelIndex& current, const QModelIndex& previous)
226 {
227 UNUSED(previous);
228 ui->status->showMessage(getStatusMsg(current));
229 }
230
showEvent(QShowEvent * e)231 void CompleterWindow::showEvent(QShowEvent*e)
232 {
233 QDialog::showEvent(e);
234
235 // A hack for Gnome3 to give this widget a focus. Harmless for others.
236 ui->list->activateWindow();
237 }
238