1
/* This file is part of the KDE project
2
Copyright (C) 2011-2016 JarosÅaw Staniek <staniek@kde.org>
3
Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
5
This program is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Library General Public
7
License as published by the Free Software Foundation; either
8
version 2 of the License, or (at your option) any later version.
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 GNU
13
Library General Public License for more details.
15
You should have received a copy of the GNU Library General Public License
16
along with this program; see the file COPYING. If not, write to
17
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
* Boston, MA 02110-1301, USA.
21
#include "KexiSearchLineEdit.h"
22
#include <KexiSearchableModel.h>
24
#include <KLocalizedString>
26
#include <kexiutils/completer/KexiCompleter.h>
27
#include <kexiutils/KexiTester.h>
31
#include <QKeySequence>
33
#include <QAbstractProxyModel>
34
#include <QInputMethodEvent>
35
#include <QStyledItemDelegate>
36
#include <QTextLayout>
39
class SearchableObject
42
KexiSearchableModel *model;
46
class KexiSearchLineEditCompleterPopupModel : public QAbstractListModel
50
explicit KexiSearchLineEditCompleterPopupModel(QObject *parent = 0);
51
~KexiSearchLineEditCompleterPopupModel();
52
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
53
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
54
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
55
void addSearchableModel(KexiSearchableModel *model);
61
class KexiSearchLineEditCompleterPopupModel::Private
69
qDeleteAll(searchableObjects);
71
void updateCachedCount() {
72
if (searchableModels.isEmpty()) {
76
foreach (KexiSearchableModel* searchableModel, searchableModels) {
77
cachedCount += searchableModel->searchableObjectCount();
81
QList<KexiSearchableModel*> searchableModels;
82
QMap<int, SearchableObject*> searchableObjects;
85
KexiSearchLineEditCompleterPopupModel::KexiSearchLineEditCompleterPopupModel(QObject *parent)
86
: QAbstractListModel(parent), d(new Private)
90
KexiSearchLineEditCompleterPopupModel::~KexiSearchLineEditCompleterPopupModel()
95
int KexiSearchLineEditCompleterPopupModel::rowCount(const QModelIndex &parent) const
98
if (d->cachedCount < 0) {
99
d->updateCachedCount();
101
return d->cachedCount;
104
QVariant KexiSearchLineEditCompleterPopupModel::data(const QModelIndex &index, int role) const
106
const int row = index.row();
107
if (d->cachedCount <= row) {
110
SearchableObject *object = static_cast<SearchableObject*>(index.internalPointer());
111
QModelIndex sourceIndex = object->model->sourceIndexForSearchableObject(object->index);
112
return object->model->searchableData(sourceIndex, role);
115
QModelIndex KexiSearchLineEditCompleterPopupModel::index(int row, int column,
116
const QModelIndex &parent) const
119
if (!hasIndex(row, column, parent)) {
120
qDebug() << "!hasIndex";
121
return QModelIndex();
125
SearchableObject *sobject = d->searchableObjects.value(row);
127
foreach (KexiSearchableModel* searchableModel, d->searchableModels) {
128
const int count = searchableModel->searchableObjectCount();
130
sobject = new SearchableObject;
131
sobject->model = searchableModel;
133
d->searchableObjects.insert(row, sobject);
142
return QModelIndex();
144
return createIndex(row, column, sobject);
147
void KexiSearchLineEditCompleterPopupModel::addSearchableModel(KexiSearchableModel *model)
149
d->searchableModels.removeAll(model);
150
d->searchableModels.append(model);
151
d->updateCachedCount();
156
class KexiSearchLineEditCompleter : public KexiCompleter
160
explicit KexiSearchLineEditCompleter(QObject *parent = 0) : KexiCompleter(parent) {
161
setCompletionRole(Qt::DisplayRole);
164
virtual QString pathFromIndex(const QModelIndex &index) const {
165
if (!index.isValid())
167
SearchableObject *object = static_cast<SearchableObject*>(index.internalPointer());
168
QModelIndex sourceIndex = object->model->sourceIndexForSearchableObject(object->index);
169
return object->model->pathFromIndex(sourceIndex);
175
class KexiSearchLineEditPopupItemDelegate;
177
class KexiSearchLineEdit::Private
180
explicit Private(KexiSearchLineEdit *_q)
181
: q(_q), clearShortcut(QKeySequence(Qt::Key_Escape), _q),
182
recentlyHighlightedModel(0)
184
// make Escape key clear the search box
185
QObject::connect(&clearShortcut, SIGNAL(activated()),
186
q, SLOT(slotClearShortcutActivated()));
189
void highlightSearchableObject(const QPair<QModelIndex, KexiSearchableModel*> &source)
191
source.second->highlightSearchableObject(source.first);
192
recentlyHighlightedModel = source.second;
195
void removeHighlightingForSearchableObject()
197
if (recentlyHighlightedModel) {
198
recentlyHighlightedModel->highlightSearchableObject(QModelIndex());
199
recentlyHighlightedModel = 0;
203
KexiSearchLineEditCompleter *completer;
204
QTreeView *popupTreeView;
205
KexiSearchLineEditCompleterPopupModel *model;
206
KexiSearchLineEditPopupItemDelegate *delegate;
207
QPointer<QWidget> previouslyFocusedWidget;
210
KexiSearchLineEdit *q;
211
QShortcut clearShortcut;
212
KexiSearchableModel *recentlyHighlightedModel;
217
static QSizeF viewItemTextLayout(QTextLayout &textLayout, int lineWidth)
221
textLayout.beginLayout();
223
QTextLine line = textLayout.createLine();
226
line.setLineWidth(lineWidth);
227
line.setPosition(QPointF(0, height));
228
height += line.height();
229
widthUsed = qMax(widthUsed, line.naturalTextWidth());
231
textLayout.endLayout();
232
return QSizeF(widthUsed, height);
235
class KexiSearchLineEditPopupItemDelegate : public QStyledItemDelegate
239
KexiSearchLineEditPopupItemDelegate(QObject *parent, KexiCompleter *completer)
240
: QStyledItemDelegate(parent), highlightMatchingSubstrings(true), m_completer(completer)
244
//! Implemented to improve width hint
245
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
247
QSize size(QStyledItemDelegate::sizeHint(option, index));
248
QStyleOptionViewItemV4 v4 = option;
249
QStyledItemDelegate::initStyleOption(&v4, index);
250
const QSize s = v4.widget->style()->sizeFromContents(QStyle::CT_ItemViewItem, &v4, size, v4.widget);
251
size.setWidth(s.width());
255
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
256
const QModelIndex &index) const
258
QStyledItemDelegate::paint(painter, option, index);
259
QStyleOptionViewItemV4 v4 = option;
260
QStyledItemDelegate::initStyleOption(&v4, index);
261
// like in QCommonStyle::paint():
262
if (!v4.text.isEmpty()) {
264
painter->setClipRect(v4.rect);
265
QPalette::ColorGroup cg = v4.state & QStyle::State_Enabled
266
? QPalette::Normal : QPalette::Disabled;
267
if (cg == QPalette::Normal && !(v4.state & QStyle::State_Active)) {
268
cg = QPalette::Inactive;
270
if (v4.state & QStyle::State_Selected) {
271
painter->setPen(v4.palette.color(cg, QPalette::HighlightedText));
274
painter->setPen(v4.palette.color(cg, QPalette::Text));
276
QRect textRect = v4.widget->style()->subElementRect(QStyle::SE_ItemViewItemText,
278
viewItemDrawText(painter, &v4, textRect);
282
bool highlightMatchingSubstrings;
285
// bits from qcommonstyle.cpp
286
void viewItemDrawText(QPainter *p, const QStyleOptionViewItemV4 *option, const QRect &rect) const
288
const QWidget *widget = option->widget;
289
const int textMargin = widget->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1;
291
QRect textRect = rect.adjusted(textMargin, 0, -textMargin, 0); // remove width padding
292
const bool wrapText = option->features & QStyleOptionViewItemV2::WrapText;
293
QTextOption textOption;
294
textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap);
295
textOption.setTextDirection(option->direction);
296
textOption.setAlignment(QStyle::visualAlignment(option->direction, option->displayAlignment));
297
QTextLayout textLayout;
298
textLayout.setTextOption(textOption);
299
textLayout.setFont(option->font);
300
QString text = option->text;
301
textLayout.setText(text);
303
if (highlightMatchingSubstrings) {
304
QList<QTextLayout::FormatRange> formats;
305
QString substring = m_completer->completionPrefix();
306
QColor underLineColor(p->pen().color());
307
underLineColor.setAlpha(128);
308
QTextLayout::FormatRange formatRange;
309
formatRange.format.setFontUnderline(true);
310
formatRange.format.setUnderlineColor(underLineColor);
312
for (int i = 0; i < text.length();) {
313
i = text.indexOf(substring, i, Qt::CaseInsensitive);
316
formatRange.length = substring.length();
317
formatRange.start = i;
318
formats.append(formatRange);
319
i += formatRange.length;
321
textLayout.setAdditionalFormats(formats);
323
viewItemTextLayout(textLayout, textRect.width());
325
const int lineCount = textLayout.lineCount();
326
QPointF position = textRect.topLeft();
327
for (int i = 0; i < lineCount; ++i) {
328
const QTextLine line = textLayout.lineAt(i);
329
const QPointF adjustPos(0, qreal(textRect.height() - line.rect().height()) / 2.0);
330
line.draw(p, position + adjustPos);
331
position.setY(position.y() + line.y() + line.ascent());
335
virtual void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const
337
QStyledItemDelegate::initStyleOption(option, index);
338
QStyleOptionViewItemV4 *v4 = qstyleoption_cast<QStyleOptionViewItemV4*>(option);
343
KexiCompleter *m_completer;
348
//! @internal Style-dependent fixes for the left margin, probably needed because of the limited
349
//! width of the line edit - it's placed in tab bar's corner widget.
350
static void fixLeftMargin(QLineEdit *lineEdit)
353
const QByteArray st(lineEdit->style()->objectName().toLatin1());
354
if (st == "breeze" || st == "gtk+") {
355
add = 4; // like QLineEditIconButton::IconMargin
357
else if (st == "fusion") {
361
QMargins margins(lineEdit->textMargins());
362
margins.setLeft(margins.left() + add);
363
lineEdit->setTextMargins(margins);
369
KexiSearchLineEdit::KexiSearchLineEdit(QWidget *parent)
370
: QLineEdit(parent), d(new Private(this))
372
d->completer = new KexiSearchLineEditCompleter(this);
373
d->popupTreeView = new QTreeView;
374
kexiTester() << KexiTestObject(d->popupTreeView, "globalSearch.treeView");
376
d->completer->setPopup(d->popupTreeView);
377
d->completer->setModel(d->model = new KexiSearchLineEditCompleterPopupModel(d->completer));
378
d->completer->setCaseSensitivity(Qt::CaseInsensitive);
379
d->completer->setSubstringCompletion(true);
380
d->completer->setMaxVisibleItems(12);
381
// Use unsorted model, sorting is handled in the source model itself.
382
// Moreover, sorting KexiCompleter::CaseInsensitivelySortedModel breaks
383
// filtering so only table names are displayed.
384
d->completer->setModelSorting(KexiCompleter::UnsortedModel);
386
d->popupTreeView->setHeaderHidden(true);
387
d->popupTreeView->setRootIsDecorated(false);
388
d->popupTreeView->setItemDelegate(
389
d->delegate = new KexiSearchLineEditPopupItemDelegate(d->popupTreeView, d->completer));
391
// forked initialization like in QLineEdit::setCompleter:
392
d->completer->setWidget(this);
397
setFocusPolicy(Qt::NoFocus); // We cannot focus set any policy here.
398
// Qt::ClickFocus would make it impossible to find
399
// previously focus widget in KexiSearchLineEdit::setFocus().
400
// We need this information to focus back when pressing Escape key.
401
setClearButtonEnabled(true);
402
setPlaceholderText(xi18n("Search"));
406
KexiSearchLineEdit::~KexiSearchLineEdit()
411
void KexiSearchLineEdit::connectCompleter()
413
connect(d->completer, SIGNAL(activated(QString)),
414
this, SLOT(setText(QString)));
415
connect(d->completer, SIGNAL(activated(QModelIndex)),
416
this, SLOT(slotCompletionActivated(QModelIndex)));
417
connect(d->completer, SIGNAL(highlighted(QString)),
418
this, SLOT(slotCompletionHighlighted(QString)));
419
connect(d->completer, SIGNAL(highlighted(QModelIndex)),
420
this, SLOT(slotCompletionHighlighted(QModelIndex)));
423
void KexiSearchLineEdit::disconnectCompleter()
425
disconnect(d->completer, 0, this, 0);
428
void KexiSearchLineEdit::slotClearShortcutActivated()
430
//qDebug() << (QWidget*)d->previouslyFocusedWidget << text();
431
d->removeHighlightingForSearchableObject();
432
if (text().isEmpty() && d->previouslyFocusedWidget) {
433
// after second Escape, go back to previously focused widget
434
d->previouslyFocusedWidget->setFocus();
435
d->previouslyFocusedWidget = 0;
442
void KexiSearchLineEdit::addSearchableModel(KexiSearchableModel *model)
444
d->model->addSearchableModel(model);
447
QPair<QModelIndex, KexiSearchableModel*> KexiSearchLineEdit::mapCompletionIndexToSource(const QModelIndex &index) const
449
QModelIndex realIndex
450
= qobject_cast<QAbstractProxyModel*>(d->completer->completionModel())->mapToSource(index);
451
if (!realIndex.isValid()) {
452
return qMakePair(QModelIndex(), static_cast<KexiSearchableModel*>(0));
454
SearchableObject *object = static_cast<SearchableObject*>(realIndex.internalPointer());
456
return qMakePair(QModelIndex(), static_cast<KexiSearchableModel*>(0));
458
return qMakePair(object->model->sourceIndexForSearchableObject(object->index), object->model);
461
void KexiSearchLineEdit::slotCompletionHighlighted(const QString &newText)
463
if (d->completer->completionMode() != KexiCompleter::InlineCompletion) {
467
int p = cursorPosition();
469
setText(t.left(p) + newText.mid(p));
471
cursorBackward(text().length() - p, true);
475
void KexiSearchLineEdit::slotCompletionHighlighted(const QModelIndex &index)
477
QPair<QModelIndex, KexiSearchableModel*> source = mapCompletionIndexToSource(index);
478
if (!source.first.isValid())
480
//qDebug() << source.second->searchableData(source.first, Qt::EditRole);
481
d->highlightSearchableObject(source);
484
void KexiSearchLineEdit::slotCompletionActivated(const QModelIndex &index)
486
QPair<QModelIndex, KexiSearchableModel*> source = mapCompletionIndexToSource(index);
487
if (!source.first.isValid())
489
//qDebug() << source.second->searchableData(source.first, Qt::EditRole);
491
d->highlightSearchableObject(source);
492
d->removeHighlightingForSearchableObject();
493
if (source.second->activateSearchableObject(source.first)) {
498
// forked bits from QLineEdit::inputMethodEvent()
499
void KexiSearchLineEdit::inputMethodEvent(QInputMethodEvent *e)
501
QLineEdit::inputMethodEvent(e);
502
if (isReadOnly() || !e->isAccepted())
504
if (!e->commitString().isEmpty()) {
505
complete(Qt::Key_unknown);
509
void KexiSearchLineEdit::setFocus()
511
//qDebug() << "d->previouslyFocusedWidget:" << (QWidget*)d->previouslyFocusedWidget
512
// << "window()->focusWidget():" << window()->focusWidget();
513
if (!d->previouslyFocusedWidget && window()->focusWidget() != this) {
514
d->previouslyFocusedWidget = window()->focusWidget();
516
QLineEdit::setFocus();
519
// forked bits from QLineEdit::focusInEvent()
520
void KexiSearchLineEdit::focusInEvent(QFocusEvent *e)
522
//qDebug() << "d->previouslyFocusedWidget:" << (QWidget*)d->previouslyFocusedWidget
523
// << "window()->focusWidget():" << window()->focusWidget();
524
if (!d->previouslyFocusedWidget && window()->focusWidget() != this) {
525
d->previouslyFocusedWidget = window()->focusWidget();
527
QLineEdit::focusInEvent(e);
528
d->completer->setWidget(this);
533
// forked bits from QLineEdit::focusOutEvent()
534
void KexiSearchLineEdit::focusOutEvent(QFocusEvent *e)
536
QLineEdit::focusOutEvent(e);
537
disconnectCompleter();
539
if (e->reason() == Qt::TabFocusReason || e->reason() == Qt::BacktabFocusReason) {
540
// go back to previously focused widget
541
if (d->previouslyFocusedWidget) {
542
d->previouslyFocusedWidget->setFocus();
546
d->previouslyFocusedWidget = 0;
547
d->removeHighlightingForSearchableObject();
550
// forked bits from QLineControl::processKeyEvent()
551
void KexiSearchLineEdit::keyPressEvent(QKeyEvent *event)
553
bool inlineCompletionAccepted = false;
555
//qDebug() << event->key() << (QWidget*)d->previouslyFocusedWidget;
557
KexiCompleter::CompletionMode completionMode = d->completer->completionMode();
558
if ((completionMode == KexiCompleter::PopupCompletion
559
|| completionMode == KexiCompleter::UnfilteredPopupCompletion)
560
&& d->completer->popup()
561
&& d->completer->popup()->isVisible()) {
562
// The following keys are forwarded by the completer to the widget
563
// Ignoring the events lets the completer provide suitable default behavior
564
switch (event->key()) {
568
#ifdef QT_KEYPAD_NAVIGATION
570
if (!QApplication::keypadNavigationEnabled())
572
d->completer->popup()->hide(); // just hide. will end up propagating to parent
575
break; // normal key processing
577
} else if (completionMode == KexiCompleter::InlineCompletion) {
578
switch (event->key()) {
582
#ifdef QT_KEYPAD_NAVIGATION
584
if (!QApplication::keypadNavigationEnabled())
587
if (!d->completer->currentCompletion().isEmpty() && hasSelectedText()
588
&& textAfterSelection().isEmpty())
590
setText(d->completer->currentCompletion());
591
inlineCompletionAccepted = true;
594
break; // normal key processing
598
if (d->completer->popup() && !d->completer->popup()->isVisible()
599
&& (event->key() == Qt::Key_F4 || event->key() == Qt::Key_Down))
601
// go back to completing when popup is closed and F4/Down pressed
602
d->completer->complete();
604
else if (d->completer->popup() && d->completer->popup()->isVisible()
605
&& event->key() == Qt::Key_F4)
607
// hide popup if F4 pressed
608
d->completer->popup()->hide();
611
if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
612
if (d->completer->popup() && !d->completer->popup()->isVisible()) {
613
d->completer->setCompletionPrefix(text());
615
if (d->completer->completionCount() == 1) {
616
// single item on the completion list, select it automatically
617
d->completer->setCurrentRow(0);
618
slotCompletionActivated(d->completer->currentIndex());
620
if (d->completer->popup()) {
621
d->completer->popup()->hide();
625
//qDebug() << "currentRow:" << d->completer->currentRow();
626
//qDebug() << "currentIndex:" << d->completer->currentIndex().isValid();
627
//qDebug() << "currentCompletion:" << d->completer->currentCompletion();
628
if (d->completer->popup() && d->completer->completionCount() > 1) {
629
//qDebug() << "11111" << d->completer->completionPrefix()
630
// << d->completer->completionCount();
632
// more than one item on completion list, find exact match, if found, accept
633
for (int i = 0; i < d->completer->completionCount(); i++) {
634
//qDebug() << d->completer->completionModel()->index(i, 0, QModelIndex()).data(Qt::EditRole).toString();
635
if (d->completer->completionPrefix()
636
== d->completer->completionModel()->index(i, 0, QModelIndex()).data(Qt::EditRole).toString())
638
d->completer->setCurrentRow(i);
639
slotCompletionActivated(d->completer->currentIndex());
641
d->completer->popup()->hide();
645
// exactly matching item not found
646
bool selectedItem = !d->completer->popup()->selectionModel()->selectedIndexes().isEmpty();
647
if (!selectedItem || !d->completer->popup()->isVisible()) {
648
if (!d->completer->popup()->isVisible()) {
649
// there is no matching text, go back to completing
650
d->completer->complete();
657
// applying completion since there is item selected
658
d->completer->popup()->hide();
660
QLineEdit::keyPressEvent(event); /* executes this:
661
if (hasAcceptableInput() || fixup()) {
662
emit returnPressed();
663
emit editingFinished();
665
if (inlineCompletionAccepted)
672
if (event == QKeySequence::MoveToNextChar) {
673
#if defined(Q_OS_WIN)
674
if (hasSelectedText()
675
&& d->completer->completionMode() == KexiCompleter::InlineCompletion)
677
int selEnd = selectionEnd();
679
setCursorPosition(selEnd);
686
else if (event == QKeySequence::MoveToPreviousChar) {
687
#if defined(Q_OS_WIN)
688
if (hasSelectedText()
689
&& d->completer->completionMode() == KexiCompleter::InlineCompletion)
691
int selStart = selectionStart();
693
setCursorPosition(selStart);
701
if (event->modifiers() & Qt::ControlModifier) {
702
switch (event->key()) {
705
complete(event->key());
709
} else { // ### check for *no* modifier
710
switch (event->key()) {
711
case Qt::Key_Backspace:
714
complete(Qt::Key_Backspace);
720
QLineEdit::keyPressEvent(event);
721
complete(Qt::Key_Delete);
731
QString t = event->text();
732
if (!t.isEmpty() && t.at(0).isPrint()) {
733
QLineEdit::keyPressEvent(event);
734
complete(event->key());
739
QLineEdit::keyPressEvent(event);
742
void KexiSearchLineEdit::changeEvent(QEvent *event)
744
QLineEdit::changeEvent(event);
745
if (event->type() == QEvent::StyleChange) {
750
// forked bits from QLineControl::advanceToEnabledItem()
751
// iterating forward(dir=1)/backward(dir=-1) from the
752
// current row based. dir=0 indicates a new completion prefix was set.
753
bool KexiSearchLineEdit::advanceToEnabledItem(int dir)
755
int start = d->completer->currentRow();
762
if (!d->completer->setCurrentRow(i)) {
763
if (!d->completer->wrapAround())
765
i = i > 0 ? 0 : d->completer->completionCount() - 1;
767
QModelIndex currentIndex = d->completer->currentIndex();
768
if (d->completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled)
772
} while (i != start);
774
d->completer->setCurrentRow(start); // restore
778
QString KexiSearchLineEdit::textBeforeSelection() const
780
return hasSelectedText() ? text().left(selectionStart()) : QString();
783
QString KexiSearchLineEdit::textAfterSelection() const
785
return hasSelectedText() ? text().mid(selectionEnd()) : QString();
788
int KexiSearchLineEdit::selectionEnd() const
790
return hasSelectedText() ?
791
(selectionStart() + selectedText().length()) : -1;
794
// forked bits from QLineControl::complete()
795
void KexiSearchLineEdit::complete(int key)
797
if (isReadOnly() || echoMode() != QLineEdit::Normal)
800
QString text = this->text();
801
if (d->completer->completionMode() == KexiCompleter::InlineCompletion) {
802
if (key == Qt::Key_Backspace)
805
if (key == Qt::Key_Up || key == Qt::Key_Down) {
806
if (textAfterSelection().length())
808
QString prefix = hasSelectedText() ? textBeforeSelection() : text;
809
if (text.compare(d->completer->currentCompletion(), d->completer->caseSensitivity()) != 0
810
|| prefix.compare(d->completer->completionPrefix(), d->completer->caseSensitivity()) != 0) {
811
d->completer->setCompletionPrefix(prefix);
813
n = (key == Qt::Key_Up) ? -1 : +1;
816
d->completer->setCompletionPrefix(text);
818
if (!advanceToEnabledItem(n))
821
#ifndef QT_KEYPAD_NAVIGATION
822
if (text.isEmpty()) {
823
d->completer->popup()->hide();
827
d->completer->setCompletionPrefix(text);
830
d->popupTreeView->resizeColumnToContents(0);
831
d->completer->complete();
834
bool KexiSearchLineEdit::highlightMatchingSubstrings() const
836
return d->delegate->highlightMatchingSubstrings;
839
void KexiSearchLineEdit::setHighlightMatchingSubstrings(bool highlight)
841
d->delegate->highlightMatchingSubstrings = highlight;
844
#include "KexiSearchLineEdit.moc"