Add a Busy status to SyntaxLineEdit.

For CaptureFilterEdit it's possible to have an indeterminate state while
we're waiting on name resolution. Add a Busy status to SyntaxLineEdit
and set the text color to a mix of the normal foreground and background
colors (gray on most platforms).

Make the Busy state valid so that we don't have to wait on an
annoyingly-long name resolution to start capturing.

Update the global capture option filters using the main welcome capture
filter when we start a capture instead of when we've finished checking
the filter syntax.

Connect the CaptureFilterEdit returnPressed signal no matter what so
that we can start a capture by pressing return in the welcome screen
CaptureFilterEdit.

Add a fake resolution timeout to the CaptureFilterSyntaxWorker debug
code to make testing the different states easier.

Bug: 11950
Change-Id: I0cf01c0fbc0dd8065cdf5a91f1d6b224291b1ce6
Reviewed-on: https://code.wireshark.org/review/13110
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Gerald Combs <gerald@wireshark.org>
This commit is contained in:
Gerald Combs 2016-01-07 09:27:13 -08:00
parent 35a79ffebb
commit 0ce9ac4137
8 changed files with 89 additions and 50 deletions

View File

@ -176,8 +176,8 @@ CaptureFilterEdit::CaptureFilterEdit(QWidget *parent, bool plain) :
"}"
);
connect(apply_button_, SIGNAL(clicked()), this, SLOT(applyCaptureFilter()));
connect(this, SIGNAL(returnPressed()), this, SLOT(applyCaptureFilter()));
}
connect(this, SIGNAL(returnPressed()), this, SLOT(applyCaptureFilter()));
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
QSize bksz;
@ -267,11 +267,11 @@ void CaptureFilterEdit::resizeEvent(QResizeEvent *)
}
}
void CaptureFilterEdit::checkFilter(const QString& text)
void CaptureFilterEdit::checkFilter(const QString& filter)
{
setSyntaxState(Empty);
setSyntaxState(Busy);
popFilterSyntaxStatus();
bool empty = text.isEmpty();
bool empty = filter.isEmpty();
if (bookmark_button_) {
bookmark_button_->setEnabled(false);
@ -286,9 +286,9 @@ void CaptureFilterEdit::checkFilter(const QString& text)
}
if (empty) {
setFilterSyntaxState(text, Empty, QString());
setFilterSyntaxState(filter, Empty, QString());
} else {
syntax_worker_->checkFilter(text);
syntax_worker_->checkFilter(filter);
}
}
@ -306,8 +306,6 @@ void CaptureFilterEdit::initCaptureFilter()
void CaptureFilterEdit::setFilterSyntaxState(QString filter, int state, QString err_msg)
{
bool valid = (state != Invalid);
if (filter.compare(text()) == 0) { // The user hasn't changed the filter
setSyntaxState((SyntaxState)state);
if (!err_msg.isEmpty()) {
@ -315,43 +313,16 @@ void CaptureFilterEdit::setFilterSyntaxState(QString filter, int state, QString
}
}
#ifdef HAVE_LIBPCAP
if (syntaxState() != Invalid) {
bool valid = (state != Invalid);
if (valid) {
if (bookmark_button_) {
bookmark_button_->setEnabled(true);
}
if (apply_button_) {
apply_button_->setEnabled(true);
}
valid = true;
g_free(global_capture_opts.default_options.cfilter);
if (filter.isEmpty()) {
global_capture_opts.default_options.cfilter = NULL;
} else {
global_capture_opts.default_options.cfilter = qstring_strdup(filter);
}
if (global_capture_opts.num_selected > 0) {
interface_t device;
for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
if (!device.selected) {
continue;
}
// if (device.active_dlt == -1) {
// simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "The link type of interface %s was not specified.", device.name);
// continue; /* Programming error: somehow managed to select an "unsupported" entry */
// }
g_array_remove_index(global_capture_opts.all_ifaces, i);
g_free(device.cfilter);
device.cfilter = qstring_strdup(filter);
g_array_insert_val(global_capture_opts.all_ifaces, i, device);
// update_filter_string(device.name, filter_text);
}
}
}
#endif // HAVE_LIBPCAP
emit captureFilterSyntaxChanged(valid);
}

View File

@ -49,7 +49,7 @@ public slots:
private slots:
void initCaptureFilter();
void applyCaptureFilter();
void checkFilter(const QString &text);
void checkFilter(const QString &filter);
void setFilterSyntaxState(QString filter, int state, QString err_msg);
void bookmarkClicked();

View File

@ -44,8 +44,10 @@ static QMutex pcap_compile_mtx_;
#include <QDebug>
#include <QThread>
#define DEBUG_SYNTAX_CHECK(state1, state2) qDebug() << "CF state" << QThread::currentThreadId() << state1 << "->" << state2 << ":" << filter_text_ << ":" << filter
#define DEBUG_SLEEP_TIME 5000 // ms
#else
#define DEBUG_SYNTAX_CHECK(state1, state2)
#define DEBUG_SLEEP_TIME 0 // ms
#endif
#define DUMMY_SNAPLENGTH 65535
@ -102,6 +104,10 @@ void CaptureFilterSyntaxWorker::start() {
pc_err = pcap_compile(pd, &fcode, filter.toUtf8().constData(), 1 /* Do optimize */, 0);
#endif
#if DEBUG_SLEEP_TIME > 0
QThread::msleep(DEBUG_SLEEP_TIME);
#endif
if (pc_err) {
DEBUG_SYNTAX_CHECK("unknown", "known bad");
state = SyntaxLineEdit::Invalid;

View File

@ -204,6 +204,11 @@ InterfaceTree *MainWelcome::getInterfaceTree()
return welcome_ui_->interfaceTree;
}
const QString MainWelcome::captureFilter()
{
return welcome_ui_->captureFilterComboBox->currentText();
}
void MainWelcome::appInitialized()
{
// XXX Add a "check for updates" link?

View File

@ -42,6 +42,7 @@ public:
explicit MainWelcome(QWidget *parent = 0);
virtual ~MainWelcome();
InterfaceTree *getInterfaceTree();
const QString captureFilter();
protected:
void resizeEvent(QResizeEvent *event);

View File

@ -837,6 +837,36 @@ void MainWindow::startCapture() {
/* XXX - we might need to init other pref data as well... */
// Set our cfilters.
QString capture_filter = main_welcome_->captureFilter();
g_free(global_capture_opts.default_options.cfilter);
if (capture_filter.isEmpty()) {
global_capture_opts.default_options.cfilter = NULL;
} else {
global_capture_opts.default_options.cfilter = qstring_strdup(capture_filter);
}
if (global_capture_opts.num_selected > 0) {
interface_t device;
for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
if (!device.selected) {
continue;
}
// if (device.active_dlt == -1) {
// simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "The link type of interface %s was not specified.", device.name);
// continue; /* Programming error: somehow managed to select an "unsupported" entry */
// }
g_array_remove_index(global_capture_opts.all_ifaces, i);
g_free(device.cfilter);
device.cfilter = qstring_strdup(capture_filter);
g_array_insert_val(global_capture_opts.all_ifaces, i, device);
// update_filter_string(device.name, filter_text);
}
}
/* XXX - can this ever happen? */
if (cap_session_.state != CAPTURE_STOPPED)
return;

View File

@ -39,6 +39,10 @@
#include <QStringListModel>
#include <limits>
// To do:
// - Add indicator icons for syntax states to make things more clear for
// color blind people?
const int max_completion_items_ = 20;
SyntaxLineEdit::SyntaxLineEdit(QWidget *parent) :
@ -46,6 +50,13 @@ SyntaxLineEdit::SyntaxLineEdit(QWidget *parent) :
completer_(NULL),
completion_model_(NULL)
{
// Try to matche QLineEdit's placeholder text color (which sets the
// alpha channel to 50%, which doesn't work in style sheets).
// Setting the foreground color lets us avoid yet another background
// color preference and should hopefully make things easier to
// distinguish for color blind folk.
busy_fg_ = ColorUtils::alphaBlend(palette().text(), palette().base(), 0.5);
setSyntaxState();
setMaxLength(std::numeric_limits<quint32>::max());
}
@ -75,27 +86,41 @@ void SyntaxLineEdit::setSyntaxState(SyntaxState state) {
syntax_state_ = state;
state_style_sheet_ = QString(
"SyntaxLineEdit[syntaxState=\"%1\"] {"
" color: %4;"
" background-color: %5;"
" color: %5;"
" background-color: %7;"
"}"
"SyntaxLineEdit[syntaxState=\"%2\"] {"
" color: %4;"
" background-color: %6;"
" color: %5;"
" background-color: %8;"
"}"
"SyntaxLineEdit[syntaxState=\"%3\"] {"
" color: %4;"
" background-color: %7;"
" color: %5;"
" background-color: %9;"
"}"
"SyntaxLineEdit[syntaxState=\"%4\"] {"
" color: %10;"
" background-color: %6;"
"}"
)
// CSS selectors
.arg(Valid)
.arg(Invalid)
.arg(Deprecated)
.arg("palette(text)") // Foreground
.arg(ColorUtils::fromColorT(&prefs.gui_text_valid).name()) // Valid
.arg(ColorUtils::fromColorT(&prefs.gui_text_invalid).name()) // Invalid
.arg(ColorUtils::fromColorT(&prefs.gui_text_deprecated).name()) // Deprecated
.arg(Busy)
// Normal foreground / background
.arg("palette(text)")
.arg("palette(base)")
// Special foreground / background
.arg(ColorUtils::fromColorT(&prefs.gui_text_valid).name())
.arg(ColorUtils::fromColorT(&prefs.gui_text_invalid).name())
.arg(ColorUtils::fromColorT(&prefs.gui_text_deprecated).name())
.arg(busy_fg_.name())
;
setStyleSheet(style_sheet_);
}

View File

@ -38,7 +38,7 @@ class SyntaxLineEdit : public QLineEdit
Q_ENUMS(SyntaxState)
public:
explicit SyntaxLineEdit(QWidget *parent = 0);
enum SyntaxState { Empty, Invalid, Deprecated, Valid };
enum SyntaxState { Empty, Busy, Invalid, Deprecated, Valid };
SyntaxState syntaxState() const { return syntax_state_; }
void setSyntaxState(SyntaxState state = Empty);
@ -79,6 +79,7 @@ private:
QString deprecated_token_;
QString syntax_error_message_;
QString token_chars_;
QColor busy_fg_;
private slots:
void insertFieldCompletion(const QString &completion_text);