summaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2015-05-19 10:18:54 -0700
committerGerald Combs <gerald@wireshark.org>2015-05-20 03:03:58 +0000
commitaf054591c31fdccd8661c87bb3d28cdeb3077db3 (patch)
treea115ca9125de66b8764c6ce3e284cee4c40dd021 /ui
parentfd985194f590225d4a41a8291cf9afae12f1b013 (diff)
downloadwireshark-af054591c31fdccd8661c87bb3d28cdeb3077db3.tar.gz
Add capture filter autocompletion.
Autocomplete on recent and saved capture filters along with the primitives in gencode.l in the libpcap sources. Move common autocomplete code to SyntaxLineEdit. Change-Id: I0931a6775bacf9c917c294befbbdaade51d19b93 Reviewed-on: https://code.wireshark.org/review/8542 Petri-Dish: Gerald Combs <gerald@wireshark.org> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Gerald Combs <gerald@wireshark.org>
Diffstat (limited to 'ui')
-rw-r--r--ui/qt/capture_filter_combo.cpp7
-rw-r--r--ui/qt/capture_filter_edit.cpp75
-rw-r--r--ui/qt/capture_filter_edit.h6
-rw-r--r--ui/qt/display_filter_edit.cpp143
-rw-r--r--ui/qt/display_filter_edit.h17
-rw-r--r--ui/qt/syntax_line_edit.cpp139
-rw-r--r--ui/qt/syntax_line_edit.h26
7 files changed, 251 insertions, 162 deletions
diff --git a/ui/qt/capture_filter_combo.cpp b/ui/qt/capture_filter_combo.cpp
index b2040b3d7c..9bc21a9471 100644
--- a/ui/qt/capture_filter_combo.cpp
+++ b/ui/qt/capture_filter_combo.cpp
@@ -30,8 +30,6 @@
#include "capture_filter_combo.h"
#include "wireshark_application.h"
-#include <QCompleter>
-
CaptureFilterCombo::CaptureFilterCombo(QWidget *parent) :
QComboBox(parent),
cf_edit_(NULL)
@@ -39,6 +37,10 @@ CaptureFilterCombo::CaptureFilterCombo(QWidget *parent) :
cf_edit_ = new CaptureFilterEdit(this, true);
setEditable(true);
+ // Enabling autocompletion here gives us two simultaneous completions:
+ // Inline (highlighted text) for entire filters, handled here and popup
+ // completion for fields handled by CaptureFilterEdit.
+ setAutoCompletion(false);
setLineEdit(cf_edit_);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
setInsertPolicy(QComboBox::NoInsert);
@@ -72,7 +74,6 @@ CaptureFilterCombo::CaptureFilterCombo(QWidget *parent) :
" left: 1px;"
"}"
);
- completer()->setCompletionMode(QCompleter::PopupCompletion);
connect(this, SIGNAL(interfacesChanged()), cf_edit_, SLOT(checkFilter()));
connect(cf_edit_, SIGNAL(pushFilterSyntaxStatus(const QString&)),
diff --git a/ui/qt/capture_filter_edit.cpp b/ui/qt/capture_filter_edit.cpp
index df54093646..ce84b9fc66 100644
--- a/ui/qt/capture_filter_edit.cpp
+++ b/ui/qt/capture_filter_edit.cpp
@@ -26,17 +26,27 @@
#include <epan/proto.h>
#include "capture_opts.h"
-#include "ui/capture_globals.h"
+
+#include <ui/capture_globals.h>
+#include <ui/filters.h>
+#include <ui/utf8_entities.h>
#include "capture_filter_edit.h"
#include "wireshark_application.h"
+#include <QComboBox>
+#include <QCompleter>
#include <QPainter>
+#include <QStringListModel>
#include <QStyleOptionFrame>
-#include "ui/utf8_entities.h"
#include "qt_ui_utils.h"
+// To do:
+// - This duplicates some DisplayFilterEdit code.
+// - We need simplified (button- and dropdown-free) versions for use in dialogs and field-only checking.
+
+
#if defined(Q_OS_MAC) && 0
// http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSImage_Class/Reference/Reference.html
// http://www.virtualbox.org/svn/vbox/trunk/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaSpecialControls.mm
@@ -72,8 +82,26 @@ UIMiniCancelButton::UIMiniCancelButton(QWidget *pParent /* = 0 */)
#endif
-
-// XXX - We need simplified (button- and dropdown-free) versions for use in dialogs and field-only checking.
+static const QString libpcap_primitive_chars_ = "-0123456789abcdefghijklmnopqrstuvwxyz";
+
+// grep '^[a-z].*return [A-Z].*;$' scanner.l | awk '{gsub(/\|/, "\n") ; print " << \"" $1 "\""}' | sort
+static const QStringList libpcap_primitives_ = QStringList()
+ << "aarp" << "action" << "address1" << "address2" << "address3" << "address4"
+ << "ah" << "and" << "arp" << "atalk" << "bcc" << "broadcast" << "byte" << "carp"
+ << "clnp" << "connectmsg" << "csnp" << "decnet" << "direction" << "dpc"
+ << "dst" << "es-is" << "esis" << "esp" << "fddi" << "fisu" << "gateway"
+ << "greater" << "hdpc" << "hfisu" << "hlssu" << "hmsu" << "hopc" << "host"
+ << "hsio" << "hsls" << "icmp" << "icmp6" << "igmp" << "igrp" << "iih" << "ilmic"
+ << "inbound" << "ip" << "ip6" << "ipx" << "is-is" << "isis" << "iso" << "l1"
+ << "l2" << "lane" << "lat" << "len" << "less" << "link" << "llc" << "lsp"
+ << "lssu" << "lsu" << "mask" << "metac" << "metaconnect" << "mopdl" << "moprc"
+ << "mpls" << "msu" << "multicast" << "net" << "netbeui" << "oam" << "oamf4"
+ << "oamf4ec" << "oamf4sc" << "on" << "opc" << "or" << "outbound" << "pim"
+ << "port" << "portrange" << "pppoed" << "pppoes" << "proto" << "psnp" << "ra"
+ << "radio" << "rarp" << "reason" << "rnr" << "rset" << "sc" << "sca" << "sctp"
+ << "sio" << "sls" << "snp" << "src" << "srnr" << "stp" << "subtype" << "ta"
+ << "tcp" << "type" << "udp" << "vci" << "vlan" << "vpi" << "vrrp"
+ ;
CaptureFilterEdit::CaptureFilterEdit(QWidget *parent, bool plain) :
SyntaxLineEdit(parent),
@@ -83,6 +111,10 @@ CaptureFilterEdit::CaptureFilterEdit(QWidget *parent, bool plain) :
{
setAccessibleName(tr("Capture filter entry"));
+ completion_model_ = new QStringListModel(this);
+ setCompleter(new QCompleter(completion_model_, this));
+ setCompletionTokenChars(libpcap_primitive_chars_);
+
placeholder_text_ = QString(tr("Enter a capture filter %1")).arg(UTF8_HORIZONTAL_ELLIPSIS);
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
setPlaceholderText(placeholder_text_);
@@ -343,6 +375,41 @@ void CaptureFilterEdit::bookmarkClicked()
emit addBookmark(text());
}
+void CaptureFilterEdit::buildCompletionList(const QString &primitive_word)
+{
+ if (primitive_word.length() < 1) {
+ completion_model_->setStringList(QStringList());
+ return;
+ }
+
+ // Grab matching capture filters from our parent combo and from the
+ // saved capture filters file. Skip ones that look like single fields
+ // and assume they will be added below.
+ QStringList complex_list;
+ QComboBox *cf_combo = qobject_cast<QComboBox *>(parent());
+ if (cf_combo) {
+ for (int i = 0; i < cf_combo->count() ; i++) {
+ QString recent_filter = cf_combo->itemText(i);
+
+ if (isComplexFilter(recent_filter)) {
+ complex_list << recent_filter;
+ }
+ }
+ }
+ for (const GList *cf_item = get_filter_list_first(CFILTER_LIST); cf_item; cf_item = g_list_next(cf_item)) {
+ const filter_def *cf_def = (filter_def *) cf_item->data;
+ if (!cf_def || !cf_def->strval) continue;
+ QString saved_filter = cf_def->strval;
+
+ if (isComplexFilter(saved_filter) && !complex_list.contains(saved_filter)) {
+ complex_list << saved_filter;
+ }
+ }
+
+ completion_model_->setStringList(complex_list + libpcap_primitives_);
+ completer()->setCompletionPrefix(primitive_word);
+}
+
void CaptureFilterEdit::applyCaptureFilter()
{
if (syntaxState() == Invalid) {
diff --git a/ui/qt/capture_filter_edit.h b/ui/qt/capture_filter_edit.h
index 020799622f..a4d61076e4 100644
--- a/ui/qt/capture_filter_edit.h
+++ b/ui/qt/capture_filter_edit.h
@@ -38,8 +38,8 @@ protected:
void paintEvent(QPaintEvent *evt);
#endif
void resizeEvent(QResizeEvent *);
-// void focusInEvent(QFocusEvent *evt);
-// void focusOutEvent(QFocusEvent *evt);
+ void keyPressEvent(QKeyEvent *event) { completionKeyPressEvent(event); }
+ void focusInEvent(QFocusEvent *event) { completionFocusInEvent(event); }
public slots:
void checkFilter();
@@ -60,6 +60,8 @@ private:
QToolButton *apply_button_;
CaptureFilterSyntaxWorker *syntax_worker_;
+ void buildCompletionList(const QString& primitive_word);
+
signals:
void pushFilterSyntaxStatus(const QString&);
void popFilterSyntaxStatus();
diff --git a/ui/qt/display_filter_edit.cpp b/ui/qt/display_filter_edit.cpp
index b20b88963a..09fc1fb8d3 100644
--- a/ui/qt/display_filter_edit.cpp
+++ b/ui/qt/display_filter_edit.cpp
@@ -36,9 +36,7 @@
#include <QComboBox>
#include <QCompleter>
#include <QEvent>
-#include <QKeyEvent>
#include <QPainter>
-#include <QScrollBar>
#include <QStringListModel>
#include <QStyleOptionFrame>
#include <QToolButton>
@@ -95,22 +93,19 @@ UIMiniCancelButton::UIMiniCancelButton(QWidget *pParent /* = 0 */)
#define DEFAULT_MODIFIER "Ctrl-"
#endif
-const int max_completion_items_ = 20;
-
// proto.c:fld_abbrev_chars
static const QString fld_abbrev_chars_ = "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
DisplayFilterEdit::DisplayFilterEdit(QWidget *parent, bool plain) :
SyntaxLineEdit(parent),
plain_(plain),
- apply_button_(NULL),
- completer_(NULL)
+ apply_button_(NULL)
{
setAccessibleName(tr("Display filter entry"));
completion_model_ = new QStringListModel(this);
- QCompleter *completer_ = new QCompleter(completion_model_, this);
- setCompleter(completer_);
+ setCompleter(new QCompleter(completion_model_, this));
+ setCompletionTokenChars(fld_abbrev_chars_);
if (plain_) {
placeholder_text_ = QString(tr("Enter a display filter %1")).arg(UTF8_HORIZONTAL_ELLIPSIS);
@@ -238,27 +233,6 @@ DisplayFilterEdit::DisplayFilterEdit(QWidget *parent, bool plain) :
);
}
-// Override setCompleter so that we don't clobber the filter text on activate.
-void DisplayFilterEdit::setCompleter(QCompleter *c)
-{
- if (completer_)
- QObject::disconnect(completer_, 0, this, 0);
-
- completer_ = c;
-
- if (!completer_)
- return;
-
- completer_->setWidget(this);
- completer_->setCompletionMode(QCompleter::PopupCompletion);
- completer_->setCaseSensitivity(Qt::CaseInsensitive);
- // Completion items are not guaranteed to be sorted (recent filters +
- // fields), so no setModelSorting.
- completer_->setMaxVisibleItems(max_completion_items_);
- QObject::connect(completer_, SIGNAL(activated(QString)),
- this, SLOT(insertFieldCompletion(QString)));
-}
-
#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
void DisplayFilterEdit::paintEvent(QPaintEvent *evt) {
SyntaxLineEdit::paintEvent(evt);
@@ -308,64 +282,11 @@ void DisplayFilterEdit::resizeEvent(QResizeEvent *)
bookmark_button_->setMaximumHeight(contentsRect().height());
}
-void DisplayFilterEdit::keyPressEvent(QKeyEvent *event)
-{
- // Forward to the completer if needed...
- if (completer_ && completer_->popup()->isVisible()) {
- switch (event->key()) {
- case Qt::Key_Enter:
- case Qt::Key_Return:
- case Qt::Key_Escape:
- case Qt::Key_Tab:
- case Qt::Key_Backtab:
- event->ignore();
- return;
- default:
- break;
- }
- }
-
- // ...otherwise process the key ourselves.
- QLineEdit::keyPressEvent(event);
-
- if (!completer_) return;
-
- // Do nothing on bare shift.
- if ((event->modifiers() & Qt::ShiftModifier) && event->text().isEmpty()) return;
-
- if (event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) {
- completer_->popup()->hide();
- return;
- }
-
- QPoint field_coords(getFieldUnderCursor());
-
- QString field_word = text().mid(field_coords.x(), field_coords.y());
- buildCompletionList(field_word);
-
- if (completion_model_->stringList().length() < 1) {
- completer_->popup()->hide();
- return;
- }
-
- QRect cr = cursorRect();
- cr.setWidth(completer_->popup()->sizeHintForColumn(0)
- + completer_->popup()->verticalScrollBar()->sizeHint().width());
- completer_->complete(cr);
-}
-
-void DisplayFilterEdit::focusInEvent(QFocusEvent *evt)
-{
- if (completer_)
- completer_->setWidget(this);
- SyntaxLineEdit::focusInEvent(evt);
-}
-
-void DisplayFilterEdit::focusOutEvent(QFocusEvent *evt)
+void DisplayFilterEdit::focusOutEvent(QFocusEvent *event)
{
if (syntaxState() == Valid)
emit popFilterSyntaxStatus();
- SyntaxLineEdit::focusOutEvent(evt);
+ SyntaxLineEdit::focusOutEvent(event);
}
void DisplayFilterEdit::checkFilter(const QString& text)
@@ -404,22 +325,6 @@ void DisplayFilterEdit::checkFilter(const QString& text)
}
}
-bool DisplayFilterEdit::isComplexFilter(const QString &dfilter)
-{
- bool is_complex = false;
- for (int i = 0; i < dfilter.length(); i++) {
- if (!fld_abbrev_chars_.contains(dfilter.at(i))) {
- is_complex = true;
- break;
- }
- }
- // Don't complete the current filter.
- if (is_complex && dfilter.startsWith(text()) && dfilter.compare(text())) {
- return true;
- }
- return false;
-}
-
// GTK+ behavior:
// - Operates on words (proto.c:fld_abbrev_chars).
// - Popup appears when you enter or remove text.
@@ -563,44 +468,6 @@ void DisplayFilterEdit::changeEvent(QEvent* event)
SyntaxLineEdit::changeEvent(event);
}
-void DisplayFilterEdit::insertFieldCompletion(const QString &completion_text)
-{
- QCompleter *completer_ = completer();
- if (!completer_) return;
-
- QPoint field_coords(getFieldUnderCursor());
-
- // Insert only if we have a matching field or if the entry is empty
- if (field_coords.y() < 1 && !text().isEmpty()) {
- completer_->popup()->hide();
- return;
- }
-
- QString new_text = text().replace(field_coords.x(), field_coords.y(), completion_text);
- setText(new_text);
- setCursorPosition(field_coords.x() + completion_text.length());
-}
-
-QPoint DisplayFilterEdit::getFieldUnderCursor()
-{
- if (selectionStart() >= 0) return (QPoint(0,0));
-
- int pos = cursorPosition();
- int start = pos;
- int len = 0;
-
- while (start > 0 && fld_abbrev_chars_.contains(text().at(start -1))) {
- start--;
- len++;
- }
- while (pos < text().length() && fld_abbrev_chars_.contains(text().at(pos))) {
- pos++;
- len++;
- }
-
- return QPoint(start, len);
-}
-
/*
* Editor modelines
*
diff --git a/ui/qt/display_filter_edit.h b/ui/qt/display_filter_edit.h
index 70fdb1b75e..f26389a6cf 100644
--- a/ui/qt/display_filter_edit.h
+++ b/ui/qt/display_filter_edit.h
@@ -24,9 +24,7 @@
#include "syntax_line_edit.h"
-class QCompleter;
class QEvent;
-class QStringListModel;
class QToolButton;
class DisplayFilterEdit : public SyntaxLineEdit
@@ -35,17 +33,14 @@ class DisplayFilterEdit : public SyntaxLineEdit
public:
explicit DisplayFilterEdit(QWidget *parent = 0, bool plain = true);
- void setCompleter(QCompleter *c);
- QCompleter *completer() const { return completer_; }
-
protected:
#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
void paintEvent(QPaintEvent *evt);
#endif
void resizeEvent(QResizeEvent *);
- void keyPressEvent(QKeyEvent *event);
- void focusInEvent(QFocusEvent *evt);
- void focusOutEvent(QFocusEvent *evt);
+ void keyPressEvent(QKeyEvent *event) { completionKeyPressEvent(event); }
+ void focusInEvent(QFocusEvent *event) { completionFocusInEvent(event); }
+ void focusOutEvent(QFocusEvent *event);
public slots:
void applyDisplayFilter();
@@ -56,7 +51,6 @@ private slots:
void bookmarkClicked();
void clearFilter();
void changeEvent(QEvent* event);
- void insertFieldCompletion(const QString & completion_text);
private:
bool plain_;
@@ -64,13 +58,8 @@ private:
QToolButton *bookmark_button_;
QToolButton *clear_button_;
QToolButton *apply_button_;
- QCompleter *completer_;
- QStringListModel *completion_model_;
- bool isComplexFilter(const QString &dfilter);
void buildCompletionList(const QString& field_word);
- // x = Start position, y = length
- QPoint getFieldUnderCursor();
signals:
void pushFilterSyntaxStatus(const QString&);
diff --git a/ui/qt/syntax_line_edit.cpp b/ui/qt/syntax_line_edit.cpp
index 867c01d38a..ac1b029a9f 100644
--- a/ui/qt/syntax_line_edit.cpp
+++ b/ui/qt/syntax_line_edit.cpp
@@ -31,12 +31,43 @@
#include "color_utils.h"
+#include <QAbstractItemView>
+#include <QCompleter>
+#include <QKeyEvent>
+#include <QScrollBar>
+#include <QStringListModel>
+
+const int max_completion_items_ = 20;
+
SyntaxLineEdit::SyntaxLineEdit(QWidget *parent) :
- QLineEdit(parent)
+ QLineEdit(parent),
+ completer_(NULL),
+ completion_model_(NULL)
{
setSyntaxState();
}
+// Override setCompleter so that we don't clobber the filter text on activate.
+void SyntaxLineEdit::setCompleter(QCompleter *c)
+{
+ if (completer_)
+ QObject::disconnect(completer_, 0, this, 0);
+
+ completer_ = c;
+
+ if (!completer_)
+ return;
+
+ completer_->setWidget(this);
+ completer_->setCompletionMode(QCompleter::PopupCompletion);
+ completer_->setCaseSensitivity(Qt::CaseInsensitive);
+ // Completion items are not guaranteed to be sorted (recent filters +
+ // fields), so no setModelSorting.
+ completer_->setMaxVisibleItems(max_completion_items_);
+ QObject::connect(completer_, SIGNAL(activated(QString)),
+ this, SLOT(insertFieldCompletion(QString)));
+}
+
void SyntaxLineEdit::setSyntaxState(SyntaxState state) {
syntax_state_ = state;
state_style_sheet_ = QString(
@@ -144,3 +175,109 @@ void SyntaxLineEdit::checkInteger(QString number)
setSyntaxState(SyntaxLineEdit::Invalid);
}
}
+
+bool SyntaxLineEdit::isComplexFilter(const QString &filter)
+{
+ bool is_complex = false;
+ for (int i = 0; i < filter.length(); i++) {
+ if (!token_chars_.contains(filter.at(i))) {
+ is_complex = true;
+ break;
+ }
+ }
+ // Don't complete the current filter.
+ if (is_complex && filter.startsWith(text()) && filter.compare(text())) {
+ return true;
+ }
+ return false;
+}
+
+void SyntaxLineEdit::completionKeyPressEvent(QKeyEvent *event)
+{
+ // Forward to the completer if needed...
+ if (completer_ && completer_->popup()->isVisible()) {
+ switch (event->key()) {
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ case Qt::Key_Escape:
+ case Qt::Key_Tab:
+ case Qt::Key_Backtab:
+ event->ignore();
+ return;
+ default:
+ break;
+ }
+ }
+
+ // ...otherwise process the key ourselves.
+ SyntaxLineEdit::keyPressEvent(event);
+
+ if (!completer_ || !completion_model_) return;
+
+ // Do nothing on bare shift.
+ if ((event->modifiers() & Qt::ShiftModifier) && event->text().isEmpty()) return;
+
+ if (event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) {
+ completer_->popup()->hide();
+ return;
+ }
+
+ QPoint token_coords(getTokenUnderCursor());
+
+ QString token_word = text().mid(token_coords.x(), token_coords.y());
+ buildCompletionList(token_word);
+
+ if (completion_model_->stringList().length() < 1) {
+ completer_->popup()->hide();
+ return;
+ }
+
+ QRect cr = cursorRect();
+ cr.setWidth(completer_->popup()->sizeHintForColumn(0)
+ + completer_->popup()->verticalScrollBar()->sizeHint().width());
+ completer_->complete(cr);
+}
+
+void SyntaxLineEdit::completionFocusInEvent(QFocusEvent *event)
+{
+ if (completer_)
+ completer_->setWidget(this);
+ SyntaxLineEdit::focusInEvent(event);
+}
+
+void SyntaxLineEdit::insertFieldCompletion(const QString &completion_text)
+{
+ if (!completer_) return;
+
+ QPoint field_coords(getTokenUnderCursor());
+
+ // Insert only if we have a matching field or if the entry is empty
+ if (field_coords.y() < 1 && !text().isEmpty()) {
+ completer_->popup()->hide();
+ return;
+ }
+
+ QString new_text = text().replace(field_coords.x(), field_coords.y(), completion_text);
+ setText(new_text);
+ setCursorPosition(field_coords.x() + completion_text.length());
+}
+
+QPoint SyntaxLineEdit::getTokenUnderCursor()
+{
+ if (selectionStart() >= 0) return (QPoint(0,0));
+
+ int pos = cursorPosition();
+ int start = pos;
+ int len = 0;
+
+ while (start > 0 && token_chars_.contains(text().at(start -1))) {
+ start--;
+ len++;
+ }
+ while (pos < text().length() && token_chars_.contains(text().at(pos))) {
+ pos++;
+ len++;
+ }
+
+ return QPoint(start, len);
+}
diff --git a/ui/qt/syntax_line_edit.h b/ui/qt/syntax_line_edit.h
index 77edf92e84..585e3b59bb 100644
--- a/ui/qt/syntax_line_edit.h
+++ b/ui/qt/syntax_line_edit.h
@@ -24,6 +24,13 @@
#include <QLineEdit>
+class QCompleter;
+class QStringListModel;
+
+// Autocompletion is partially implemented. Subclasses must:
+// - Provide buildCompletionList
+// - Call setCompletionTokenChars
+
class SyntaxLineEdit : public QLineEdit
{
Q_OBJECT
@@ -39,6 +46,9 @@ public:
QString styleSheet() const;
QString deprecatedToken();
+ void setCompleter(QCompleter *c);
+ QCompleter *completer() const { return completer_; }
+
public slots:
void setStyleSheet(const QString &style_sheet);
@@ -47,12 +57,28 @@ public slots:
void checkFieldName(QString field);
void checkInteger(QString number);
+protected:
+ QCompleter *completer_;
+ QStringListModel *completion_model_;
+ void setCompletionTokenChars(const QString &token_chars) { token_chars_ = token_chars; }
+ bool isComplexFilter(const QString &filter);
+ virtual void buildCompletionList(const QString&) { }
+ // x = Start position, y = length
+ QPoint getTokenUnderCursor();
+
+ void completionKeyPressEvent(QKeyEvent *event);
+ void completionFocusInEvent(QFocusEvent *event);
+
private:
SyntaxState syntax_state_;
QString style_sheet_;
QString state_style_sheet_;
QString deprecated_token_;
QString syntax_error_message_;
+ QString token_chars_;
+
+private slots:
+ void insertFieldCompletion(const QString &completion_text);
signals: