aboutsummaryrefslogtreecommitdiffstats
path: root/ui/qt/widgets/display_filter_combo.cpp
blob: bc07bb11d9f6c0929aaf65b2d5ff1892af4f1fec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/* display_filter_combo.cpp
 *
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 1998 Gerald Combs
 *
 * SPDX-License-Identifier: GPL-2.0+*/

#include <stdio.h>

#include <ui/qt/utils/qt_ui_utils.h>
#include "ui/recent_utils.h"
#include "ui/recent.h"

#include <epan/prefs.h>

#include <QHelpEvent>
#include <QStyleOptionComboBox>

#include <ui/qt/widgets/display_filter_edit.h>
#include <ui/qt/widgets/display_filter_combo.h>
#include "wireshark_application.h"

// If we ever add support for multiple windows this will need to be replaced.
static DisplayFilterCombo *cur_display_filter_combo = NULL;

DisplayFilterCombo::DisplayFilterCombo(QWidget *parent) :
    QComboBox(parent)
{
    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 DisplayFilterEdit.
    setAutoCompletion(false);
    setLineEdit(new DisplayFilterEdit(this, DisplayFilterToApply));
    setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
    setAccessibleName(tr("Display filter selector"));
    cur_display_filter_combo = this;
    setStyleSheet(
            "QComboBox {"
#ifdef Q_OS_MAC
            "  border: 1px solid gray;"
#else
            "  border: 1px solid palette(shadow);"
#endif
            "  border-radius: 3px;"
            "  padding: 0px 0px 0px 0px;"
            "  margin-left: 0px;"
            "  min-width: 20em;"
            " }"

            "QComboBox::drop-down {"
            "  subcontrol-origin: padding;"
            "  subcontrol-position: top right;"
            "  width: 14px;"
            "  border-left-width: 0px;"
            " }"

            "QComboBox::down-arrow {"
            "  image: url(:/stock_icons/14x14/x-filter-dropdown.png);"
            " }"

            "QComboBox::down-arrow:on { /* shift the arrow when popup is open */"
            "  top: 1px;"
            "  left: 1px;"
            "}"
            );
    setToolTip(tr("Select from previously used filters."));

    connect(wsApp, SIGNAL(preferencesChanged()), this, SLOT(updateMaxCount()));
}

extern "C" void dfilter_recent_combo_write_all(FILE *rf) {
    if (!cur_display_filter_combo)
        return;

    cur_display_filter_combo->writeRecent(rf);
}

void DisplayFilterCombo::writeRecent(FILE *rf) {
    int i;

    for (i = 0; i < count(); i++) {
        const QByteArray& filter = itemText(i).toUtf8();
        if (!filter.isEmpty()) {
            fprintf(rf, RECENT_KEY_DISPLAY_FILTER ": %s\n", filter.constData());
        }
    }
}

bool DisplayFilterCombo::event(QEvent *event)
{
    switch (event->type()) {
    case QEvent::ToolTip:
    {
        // Only show a tooltip for the arrow.
        QHelpEvent *he = (QHelpEvent *) event;
        QStyleOptionComboBox opt;
        initStyleOption(&opt);
        QRect scr = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxArrow, this);
        if (!scr.contains(he->pos())) {
            return false;
        }
        break;
    }
    default:
        break;
    }
    return QComboBox::event(event);
}

bool DisplayFilterCombo::checkDisplayFilter()
{
    DisplayFilterEdit *df_edit = qobject_cast<DisplayFilterEdit *>(lineEdit());
    bool state = false;

    if (df_edit) state = df_edit->checkFilter();
    return state;
}

void DisplayFilterCombo::applyDisplayFilter()
{
    DisplayFilterEdit *df_edit = qobject_cast<DisplayFilterEdit *>(lineEdit());

    if (df_edit) df_edit->applyDisplayFilter();
}

void DisplayFilterCombo::setDisplayFilter(QString filter)
{
    lineEdit()->setText(filter);
    lineEdit()->setFocus();
}

void DisplayFilterCombo::updateMaxCount()
{
    setMaxCount(prefs.gui_recent_df_entries_max);
}

extern "C" gboolean dfilter_combo_add_recent(const gchar *filter) {
    if (!cur_display_filter_combo)
        return FALSE;

    // Adding an item to a QComboBox also sets its lineEdit. In our case
    // that means we might trigger a temporary status message so we block
    // the lineEdit's signals.
    // Another approach would be to update QComboBox->model directly.
    bool block_state = cur_display_filter_combo->lineEdit()->blockSignals(true);
    cur_display_filter_combo->addItem(filter);
    cur_display_filter_combo->clearEditText();
    cur_display_filter_combo->lineEdit()->blockSignals(block_state);
    return TRUE;
}


/*
 * Editor modelines
 *
 * Local Variables:
 * c-basic-offset: 4
 * tab-width: 8
 * indent-tabs-mode: nil
 * End:
 *
 * ex: set shiftwidth=4 tabstop=8 expandtab:
 * :indentSize=4:tabSize=8:noTabs=true:
 */