diff options
-rw-r--r-- | ui/capture_ui_utils.h | 2 | ||||
-rw-r--r-- | ui/qt/capture_filter_combo.h | 1 | ||||
-rw-r--r-- | ui/qt/capture_filter_edit.cpp | 59 | ||||
-rw-r--r-- | ui/qt/capture_filter_edit.h | 6 | ||||
-rw-r--r-- | ui/qt/capture_interfaces_dialog.cpp | 189 | ||||
-rw-r--r-- | ui/qt/capture_interfaces_dialog.h | 7 | ||||
-rw-r--r-- | ui/qt/interface_tree.cpp | 110 | ||||
-rw-r--r-- | ui/qt/interface_tree.h | 9 | ||||
-rw-r--r-- | ui/qt/main_welcome.cpp | 36 | ||||
-rw-r--r-- | ui/qt/main_welcome.h | 6 | ||||
-rw-r--r-- | ui/qt/main_window.cpp | 13 |
11 files changed, 278 insertions, 160 deletions
diff --git a/ui/capture_ui_utils.h b/ui/capture_ui_utils.h index 5f6cdcd284..8e7ef65b30 100644 --- a/ui/capture_ui_utils.h +++ b/ui/capture_ui_utils.h @@ -98,6 +98,8 @@ gboolean capture_dev_user_pmode_find(const gchar *if_name, gboolean *pmode); * Find user-specified capture filter that matches interface * name, if any. * + * This is deprecated and should not be used in new code. + * * @param if_name The name of the interface. * * @return The capture filter (must be g_free'd later) or NULL if not found. diff --git a/ui/qt/capture_filter_combo.h b/ui/qt/capture_filter_combo.h index 961ccabd9e..785b6ad36c 100644 --- a/ui/qt/capture_filter_combo.h +++ b/ui/qt/capture_filter_combo.h @@ -34,6 +34,7 @@ public: explicit CaptureFilterCombo(QWidget *parent = 0, bool plain = false); bool addRecentCapture(const char *filter); void writeRecent(FILE *rf); + void setConflict(bool conflict = false) { cf_edit_->setConflict(conflict); } signals: void interfacesChanged(); diff --git a/ui/qt/capture_filter_edit.cpp b/ui/qt/capture_filter_edit.cpp index 7779ad6f5a..0a033f43dc 100644 --- a/ui/qt/capture_filter_edit.cpp +++ b/ui/qt/capture_filter_edit.cpp @@ -126,10 +126,7 @@ CaptureFilterEdit::CaptureFilterEdit(QWidget *parent, bool plain) : 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_); -#endif + setConflict(false); if (!plain_) { bookmark_button_ = new StockIconToolButton(this, "x-capture-filter-bookmark"); @@ -215,7 +212,7 @@ CaptureFilterEdit::CaptureFilterEdit(QWidget *parent, bool plain) : QThread *syntax_thread = new QThread; syntax_worker_ = new CaptureFilterSyntaxWorker; syntax_worker_->moveToThread(syntax_thread); - connect(wsApp, SIGNAL(appInitialized()), this, SLOT(initCaptureFilter())); + connect(wsApp, SIGNAL(appInitialized()), this, SLOT(updateBookmarkMenu())); connect(wsApp, SIGNAL(captureFilterListChanged()), this, SLOT(updateBookmarkMenu())); connect(syntax_thread, SIGNAL(started()), syntax_worker_, SLOT(start())); connect(syntax_thread, SIGNAL(started()), this, SLOT(checkFilter())); @@ -294,12 +291,55 @@ void CaptureFilterEdit::resizeEvent(QResizeEvent *) } } +void CaptureFilterEdit::setConflict(bool conflict) +{ + if (conflict) { + //: This is a very long concept that needs to fit into a short space. + placeholder_text_ = tr("Multiple filters selected. Override them here or leave this blank to preserve them."); + setToolTip(tr("<p>The interfaces you have selected have different capture filters." + " Typing a filter here will override them. Doing nothing will" + " preserve them.</p>")); + } else { + placeholder_text_ = QString(tr("Enter a capture filter %1")).arg(UTF8_HORIZONTAL_ELLIPSIS); + setToolTip(QString()); + } +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + setPlaceholderText(placeholder_text_); +#endif +} + +// XXX Make this private along with setConflict. +QPair<const QString, bool> CaptureFilterEdit::getSelectedFilter() +{ + QString user_filter; + bool filter_conflict = false; +#ifdef HAVE_LIBPCAP + int selected_devices = 0; + + for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + if (device.selected) { + selected_devices++; + if (selected_devices == 1) { + user_filter = device.cfilter; + } else { + if (user_filter.compare(device.cfilter)) { + filter_conflict = true; + } + } + } + } +#endif // HAVE_LIBPCAP + return QPair<const QString, bool>(user_filter, filter_conflict); +} + void CaptureFilterEdit::checkFilter(const QString& filter) { setSyntaxState(Busy); popFilterSyntaxStatus(); bool empty = filter.isEmpty(); + setConflict(false); if (bookmark_button_) { bool match = false; @@ -385,15 +425,6 @@ void CaptureFilterEdit::updateBookmarkMenu() checkFilter(); } -void CaptureFilterEdit::initCaptureFilter() -{ -#ifdef HAVE_LIBPCAP - setText(global_capture_opts.default_options.cfilter); -#endif // HAVE_LIBPCAP - - updateBookmarkMenu(); -} - void CaptureFilterEdit::setFilterSyntaxState(QString filter, int state, QString err_msg) { if (filter.compare(text()) == 0) { // The user hasn't changed the filter diff --git a/ui/qt/capture_filter_edit.h b/ui/qt/capture_filter_edit.h index bb9daf6232..df3c1eb362 100644 --- a/ui/qt/capture_filter_edit.h +++ b/ui/qt/capture_filter_edit.h @@ -34,6 +34,11 @@ class CaptureFilterEdit : public SyntaxLineEdit Q_OBJECT public: explicit CaptureFilterEdit(QWidget *parent = 0, bool plain = false); + void setConflict(bool conflict = false); + // No selections: (QString(), false) + // Selections, same filter: (filter, false) + // Selections, different filters (QString(), true) + static QPair<const QString, bool> getSelectedFilter(); protected: void paintEvent(QPaintEvent *evt); @@ -50,7 +55,6 @@ public slots: void prepareFilter(); private slots: - void initCaptureFilter(); void applyCaptureFilter(); void checkFilter(const QString &filter); void setFilterSyntaxState(QString filter, int state, QString err_msg); diff --git a/ui/qt/capture_interfaces_dialog.cpp b/ui/qt/capture_interfaces_dialog.cpp index 82acc44131..d0c6e5a570 100644 --- a/ui/qt/capture_interfaces_dialog.cpp +++ b/ui/qt/capture_interfaces_dialog.cpp @@ -152,16 +152,19 @@ CaptureInterfacesDialog::CaptureInterfacesDialog(QWidget *parent) : ui->filenameLineEdit->setPlaceholderText(tr("Leave blank to use a temporary file")); #endif - connect(ui->interfaceTree,SIGNAL(itemClicked(QTreeWidgetItem*,int)),this,SLOT(interfaceClicked(QTreeWidgetItem*,int))); - connect(ui->interfaceTree, SIGNAL(itemSelectionChanged()), this, SLOT(interfaceSelected())); + // Changes in interface selections or capture filters should be propagated + // to the main welcome screen where they will be applied to the global + // capture options. + connect(this, SIGNAL(interfacesChanged()), ui->captureFilterComboBox, SIGNAL(interfacesChanged())); connect(ui->captureFilterComboBox, SIGNAL(captureFilterSyntaxChanged(bool)), this, SLOT(updateWidgets())); connect(ui->captureFilterComboBox->lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(filterEdited())); - connect(ui->captureFilterComboBox, SIGNAL(activated(QString)), - this, SLOT(filterEdited())); + connect(ui->captureFilterComboBox->lineEdit(), SIGNAL(textEdited(QString)), + this, SIGNAL(captureFilterTextEdited(QString))); connect(&interface_item_delegate_, SIGNAL(filterChanged(QString)), ui->captureFilterComboBox->lineEdit(), SLOT(setText(QString))); - connect(this, SIGNAL(interfacesChanged()), ui->captureFilterComboBox, SIGNAL(interfacesChanged())); + connect(&interface_item_delegate_, SIGNAL(filterChanged(QString)), + this, SIGNAL(captureFilterTextEdited(QString))); connect(this, SIGNAL(ifsChanged()), this, SLOT(refreshInterfaceList())); connect(wsApp, SIGNAL(localInterfaceListChanged()), this, SLOT(updateLocalInterfaces())); connect(ui->browseButton, SIGNAL(clicked()), this, SLOT(browseButtonClicked())); @@ -169,29 +172,20 @@ CaptureInterfacesDialog::CaptureInterfacesDialog(QWidget *parent) : void CaptureInterfacesDialog::interfaceSelected() { - interface_t *device; + InterfaceTree::updateGlobalDeviceSelections(ui->interfaceTree, col_interface_); + + start_bt_->setEnabled((global_capture_opts.num_selected > 0) ? true: false); + + emit interfacesChanged(); + + updateSelectedFilter(); - if (ui->interfaceTree->selectedItems().isEmpty()) { - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); - device->selected = false; - device->locked = true; - } - global_capture_opts.num_selected = 0; - start_bt_->setEnabled(false); - emit setSelectedInterfaces(); - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); - device->locked = false; - } - } updateWidgets(); } void CaptureInterfacesDialog::filterEdited() { QList<QTreeWidgetItem*> si = ui->interfaceTree->selectedItems(); - if (si.isEmpty()) return; foreach (QTreeWidgetItem *ti, si) { ti->setText(col_filter_, ui->captureFilterComboBox->lineEdit()->text()); @@ -218,41 +212,6 @@ void CaptureInterfacesDialog::updateWidgets() start_bt_->setEnabled(can_capture); } -void CaptureInterfacesDialog::interfaceClicked(QTreeWidgetItem *, int) -{ - guint i; - QString filter = ui->captureFilterComboBox->currentText(); - - global_capture_opts.num_selected = 0; - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); - device->selected = FALSE; - } - - foreach (QTreeWidgetItem *ti, ui->interfaceTree->selectedItems()) - { - QString interface_name = ti->text(col_interface_); - - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); - if (interface_name.compare(device->display_name)) { - continue; - } else { - device->selected = TRUE; - global_capture_opts.num_selected++; - break; - } - } - - start_bt_->setEnabled((global_capture_opts.num_selected > 0) ? true: false); - - if (filter.compare(QString(""))) { - emit interfacesChanged(); - } - emit setSelectedInterfaces(); - } -} - CaptureInterfacesDialog::~CaptureInterfacesDialog() { delete ui; @@ -269,8 +228,9 @@ void CaptureInterfacesDialog::on_capturePromModeCheckBox_toggled(bool checked) prefs.capture_prom_mode = checked; for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) { QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row); - int device_idx = ti->data(col_interface_, Qt::UserRole).toUInt(); - device = &g_array_index(global_capture_opts.all_ifaces, interface_t, device_idx); + QString device_name = ti->data(col_interface_, Qt::UserRole).toString(); + device = getDeviceByName(device_name); + if (!device) continue; // QString device_name = ui->interfaceTree->topLevelItem(row)->text(col_interface_); device->pmode = checked; ti->setText(col_pmode_, checked? tr("enabled"):tr("disabled")); @@ -460,6 +420,8 @@ void CaptureInterfacesDialog::updateInterfaces() ui->cbResolveNetworkNames->setChecked(gbl_resolv_flags.network_name); ui->cbResolveTransportNames->setChecked(gbl_resolv_flags.transport_name); + // Rebuild the interface list without disturbing the main welcome screen. + disconnect(ui->interfaceTree, SIGNAL(itemSelectionChanged()), this, SLOT(interfaceSelected())); ui->interfaceTree->clear(); GList *list; @@ -469,6 +431,7 @@ void CaptureInterfacesDialog::updateInterfaces() #endif gint snaplen; gboolean hassnap, pmode; + QList<QTreeWidgetItem *> selected_interfaces; if (global_capture_opts.all_ifaces->len > 0) { interface_t *device; @@ -484,7 +447,7 @@ void CaptureInterfacesDialog::updateInterfaces() // Traffic sparklines InterfaceTreeWidgetItem *ti = new InterfaceTreeWidgetItem(ui->interfaceTree); ti->setFlags(ti->flags() | Qt::ItemIsEditable); - ti->setData(col_interface_, Qt::UserRole, qVariantFromValue(device_idx)); + ti->setData(col_interface_, Qt::UserRole, QString(device->name)); ti->setData(col_traffic_, Qt::UserRole, qVariantFromValue(&ti->points)); ti->setText(col_interface_, device->display_name); @@ -562,34 +525,20 @@ void CaptureInterfacesDialog::updateInterfaces() #ifdef HAVE_EXTCAP } #endif - // If the capture filter column has text, assume that the user - // has filled it in via selectedIfaceCaptureFilterComboBox. - if (ti->text(col_filter_).isEmpty()) { - gchar* user_cfilter = capture_dev_user_cfilter_find(device->name); - if (user_cfilter) { - g_free(device->cfilter); - device->cfilter = user_cfilter; - } - ti->setText(col_filter_, device->cfilter); - } + ti->setText(col_filter_, device->cfilter); - if (prefs.capture_device && strstr(prefs.capture_device, device->name) != NULL) { - device->selected = TRUE; - global_capture_opts.num_selected++; + if (device->selected) { + selected_interfaces << ti; } - ti->setSelected(device->selected); } } - // col_interface_ = 0, - // col_traffic_, - // col_link_, - // col_pmode_, - // col_snaplen_, - // col_buffer_, - // col_monitor_, - // col_filter_, - // col_num_columns_ + foreach (QTreeWidgetItem *ti, selected_interfaces) { + ti->setSelected(true); + } + connect(ui->interfaceTree, SIGNAL(itemSelectionChanged()), this, SLOT(interfaceSelected())); + updateSelectedFilter(); + // Manually or automatically size some columns as needed. int one_em = fontMetrics().height(); for (int col = 0; col < ui->interfaceTree->topLevelItemCount(); col++) { @@ -622,6 +571,11 @@ void CaptureInterfacesDialog::updateInterfaces() } } +void CaptureInterfacesDialog::showEvent(QShowEvent *) +{ + updateInterfaces(); +} + void CaptureInterfacesDialog::refreshInterfaceList() { updateInterfaces(); @@ -802,12 +756,6 @@ bool CaptureInterfacesDialog::saveOptionsToPreferences() interface_t *device; - // Close the editor if it's open. - QTreeWidgetItem *ti = ui->interfaceTree->currentItem(); - if (ti) { - ui->interfaceTree->setCurrentItem(ti, col_interface_); - } - for (int col = col_link_; col <= col_filter_; col++) { if (ui->interfaceTree->isColumnHidden(col)) { continue; @@ -821,9 +769,9 @@ bool CaptureInterfacesDialog::saveOptionsToPreferences() for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) { QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row); - guint device_idx = ti->data(col_interface_, Qt::UserRole).toUInt(); - device = &g_array_index(global_capture_opts.all_ifaces, interface_t, device_idx); - if (device->active_dlt == -1) { + QString device_name = ti->data(col_interface_, Qt::UserRole).toString(); + device = getDeviceByName(device_name); + if (!device || device->active_dlt == -1) { continue; } link_list << QString("%1(%2)").arg(device->name).arg(device->active_dlt); @@ -839,9 +787,9 @@ bool CaptureInterfacesDialog::saveOptionsToPreferences() for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) { QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row); - guint device_idx = ti->data(col_interface_, Qt::UserRole).toUInt(); - device = &g_array_index(global_capture_opts.all_ifaces, interface_t, device_idx); - if (device->buffer == -1) { + QString device_name = ti->data(col_interface_, Qt::UserRole).toString(); + device = getDeviceByName(device_name); + if (!device || device->buffer == -1) { continue; } buffer_size_list << QString("%1(%2)").arg(device->name).arg(device->buffer); @@ -857,8 +805,9 @@ bool CaptureInterfacesDialog::saveOptionsToPreferences() for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) { QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row); - guint device_idx = ti->data(col_interface_, Qt::UserRole).toUInt(); - device = &g_array_index(global_capture_opts.all_ifaces, interface_t, device_idx); + QString device_name = ti->data(col_interface_, Qt::UserRole).toString(); + device = getDeviceByName(device_name); + if (!device) continue; snaplen_list << QString("%1:%2(%3)") .arg(device->name) .arg(device->has_snaplen) @@ -874,9 +823,9 @@ bool CaptureInterfacesDialog::saveOptionsToPreferences() for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) { QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row); - guint device_idx = ti->data(col_interface_, Qt::UserRole).toUInt(); - device = &g_array_index(global_capture_opts.all_ifaces, interface_t, device_idx); - if (device->pmode == -1) { + QString device_name = ti->data(col_interface_, Qt::UserRole).toString(); + device = getDeviceByName(device_name); + if (!device || device->pmode == -1) { continue; } pmode_list << QString("%1(%2)").arg(device->name).arg(device->pmode); @@ -892,9 +841,9 @@ bool CaptureInterfacesDialog::saveOptionsToPreferences() for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) { QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row); - guint device_idx = ti->data(col_interface_, Qt::UserRole).toUInt(); - device = &g_array_index(global_capture_opts.all_ifaces, interface_t, device_idx); - if (!device->monitor_mode_supported || (device->monitor_mode_supported && !device->monitor_mode_enabled)) { + QString device_name = ti->data(col_interface_, Qt::UserRole).toString(); + device = getDeviceByName(device_name); + if (!device || !device->monitor_mode_supported || (device->monitor_mode_supported && !device->monitor_mode_enabled)) { continue; } monitor_list << device->name; @@ -904,13 +853,18 @@ bool CaptureInterfacesDialog::saveOptionsToPreferences() break; } #endif // HAVE_MONITOR_SETTING + +#if 0 + // The device cfilter should have been applied at this point. + // We shouldn't change it here. case col_filter_: { // XXX Update selected interfaces only? for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) { QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row); - guint device_idx = ti->data(col_interface_, Qt::UserRole).toUInt(); - device = &g_array_index(global_capture_opts.all_ifaces, interface_t, device_idx); + QString device_name = ti->data(col_interface_, Qt::UserRole).toString(); + device = getDeviceByName(device_name); + if (!device) continue; g_free(device->cfilter); if (ti->text(col_filter_).isEmpty()) { device->cfilter = NULL; @@ -919,6 +873,7 @@ bool CaptureInterfacesDialog::saveOptionsToPreferences() } } } +#endif } } if (!prefs.gui_use_pref_save) { @@ -927,6 +882,21 @@ bool CaptureInterfacesDialog::saveOptionsToPreferences() return true; } +void CaptureInterfacesDialog::updateSelectedFilter() +{ + // Should match MainWelcome::interfaceSelected. + QPair <const QString, bool> sf_pair = CaptureFilterEdit::getSelectedFilter(); + const QString user_filter = sf_pair.first; + bool conflict = sf_pair.second; + + if (conflict) { + ui->captureFilterComboBox->lineEdit()->clear(); + ui->captureFilterComboBox->setConflict(true); + } else { + ui->captureFilterComboBox->lineEdit()->setText(user_filter); + } +} + void CaptureInterfacesDialog::on_manage_clicked() { if (saveOptionsToPreferences()) { @@ -951,6 +921,17 @@ void CaptureInterfacesDialog::changeEvent(QEvent* event) QDialog::changeEvent(event); } +interface_t *CaptureInterfacesDialog::getDeviceByName(const QString device_name) +{ + for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); + if (device_name.compare(QString().fromUtf8(device->name)) == 0) { + return device; + } + } + return NULL; +} + // // InterfaceTreeItem // diff --git a/ui/qt/capture_interfaces_dialog.h b/ui/qt/capture_interfaces_dialog.h index 0c38cf310e..e990c4bace 100644 --- a/ui/qt/capture_interfaces_dialog.h +++ b/ui/qt/capture_interfaces_dialog.h @@ -79,6 +79,9 @@ public: void SetTab(int index); void updateInterfaces(); +protected: + virtual void showEvent(QShowEvent *); + private slots: void on_capturePromModeCheckBox_toggled(bool checked); void on_gbStopCaptureAuto_toggled(bool checked); @@ -94,7 +97,6 @@ private slots: void start_button_clicked(); void on_buttonBox_rejected(); void on_buttonBox_helpRequested(); - void interfaceClicked(QTreeWidgetItem *item, int column); void interfaceSelected(); void filterEdited(); void updateWidgets(); @@ -113,6 +115,7 @@ signals: void interfacesChanged(); void ifsChanged(); void interfaceListChanged(); + void captureFilterTextEdited(const QString & text); private: Ui::CaptureInterfacesDialog *ui; @@ -124,7 +127,9 @@ private: QTimer *stat_timer_; InterfaceTreeDelegate interface_item_delegate_; + interface_t *getDeviceByName(const QString device_name); bool saveOptionsToPreferences(); + void updateSelectedFilter(); }; #endif /* HAVE_LIBPCAP */ diff --git a/ui/qt/interface_tree.cpp b/ui/qt/interface_tree.cpp index 3f7fa7d849..67b0c12d8c 100644 --- a/ui/qt/interface_tree.cpp +++ b/ui/qt/interface_tree.cpp @@ -45,7 +45,21 @@ #include <QHeaderView> #include <QTimer> -// To do: +// The interface list and capture filter editor in the main window and +// the capture interfaces dialog should have the following behavior: +// +// - The global capture options are the source of truth for selected +// interfaces. +// - The global capture options are the source of truth for the capture +// filter for an interface. +// - If multiple interfaces with different filters are selected, the +// CaptureFilterEdit should be cleared and show a corresponding +// placeholder message. Device cfilters should not be changed. +// - Entering a filter in a CaptureFilterEdit should update the device +// cfilter for each selected interface. This should happen even when +// conflicting filters are selected, as described above. +// - Interface selections and cfilter changes in CaptureInterfacesDialog +// should be reflected in MainWelcome. #ifdef HAVE_LIBPCAP const int stat_update_interval_ = 1000; // ms @@ -81,7 +95,7 @@ InterfaceTree::InterfaceTree(QWidget *parent) : connect(wsApp, SIGNAL(appInitialized()), this, SLOT(getInterfaceList())); connect(wsApp, SIGNAL(localInterfaceListChanged()), this, SLOT(interfaceListChanged())); - connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(updateSelectedInterfaces())); + connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(selectedInterfaceChanged())); } InterfaceTree::~InterfaceTree() { @@ -181,6 +195,7 @@ void InterfaceTree::display() QList<QTreeWidgetItem *> phys_ifaces; QList<QTreeWidgetItem *> virt_ifaces; + global_capture_opts.num_selected = 0; for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); @@ -192,31 +207,6 @@ void InterfaceTree::display() InterfaceTreeWidgetItem *ti = new InterfaceTreeWidgetItem(); ti->setText(IFTREE_COL_NAME, QString().fromUtf8(device.display_name)); - // To do: - // - Sync with code in CaptureInterfacesDialog. - // - Add more information to the tooltip. - QString tt_str = "<p>"; - if (device.no_addresses > 0) { - tt_str += QString("%1: %2").arg(device.no_addresses > 1 ? tr("Addresses") : tr("Address")).arg(device.addresses); - tt_str.replace('\n', ", "); - } else { - tt_str = tr("No addresses"); - } - tt_str += "<br/>"; - QString cfilter = gchar_free_to_qstring(capture_dev_user_cfilter_find(device.name)); - if (cfilter.isEmpty()) { - tt_str += tr("No capture filter"); - } else { - tt_str += QString("%1: %2") - .arg(tr("Capture filter")) - .arg(cfilter); - } - tt_str += "</p>"; - - for (int col = 0; col < columnCount(); col++) { - ti->setToolTip(col, tt_str); - } - ti->setData(IFTREE_COL_NAME, Qt::UserRole, QString(device.name)); ti->setData(IFTREE_COL_STATS, Qt::UserRole, qVariantFromValue(&ti->points)); #if HAVE_EXTCAP @@ -251,7 +241,8 @@ void InterfaceTree::display() if (!phys_ifaces.isEmpty()) addTopLevelItems(phys_ifaces); if (!virt_ifaces.isEmpty()) addTopLevelItems(virt_ifaces); - setSelectedInterfaces(); + updateSelectedInterfaces(); + updateToolTips(); // XXX Add other device information resizeColumnToContents(IFTREE_COL_NAME); @@ -358,15 +349,19 @@ void InterfaceTree::updateStatistics(void) { #endif // HAVE_LIBPCAP } -void InterfaceTree::updateSelectedInterfaces() +// Update our global device selections based on the given TreeWidget. +// This is shared with CaptureInterfacesDialog. +// Column name_col UserRole data MUST be set to the interface name. +void InterfaceTree::updateGlobalDeviceSelections(QTreeWidget *if_tree, int name_col) { + if (!if_tree) return; #ifdef HAVE_LIBPCAP - QTreeWidgetItemIterator iter(this); + QTreeWidgetItemIterator iter(if_tree); global_capture_opts.num_selected = 0; while (*iter) { - QString device_name = (*iter)->data(IFTREE_COL_NAME, Qt::UserRole).value<QString>(); + QString device_name = (*iter)->data(name_col, Qt::UserRole).value<QString>(); for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); if (device_name.compare(QString().fromUtf8(device.name)) == 0) { @@ -388,18 +383,21 @@ void InterfaceTree::updateSelectedInterfaces() break; } } - iter++; + ++iter; } - emit interfacesUpdated(); #endif // HAVE_LIBPCAP } -void InterfaceTree::setSelectedInterfaces() +// Update selected interfaces based on the global interface list.. +// Must not change any interface data. +// Must not emit itemSelectionChanged. +void InterfaceTree::updateSelectedInterfaces() { #ifdef HAVE_LIBPCAP interface_t *device; QTreeWidgetItemIterator iter(this); + bool blocking = blockSignals(true); while (*iter) { QString device_name = (*iter)->data(IFTREE_COL_NAME, Qt::UserRole).value<QString>(); @@ -412,6 +410,50 @@ void InterfaceTree::setSelectedInterfaces() } iter++; } + blockSignals(blocking); +#endif // HAVE_LIBPCAP +} + +// Update the tooltip for each interface based on the global interface list.. +// Must not change any interface data. +void InterfaceTree::updateToolTips() +{ +#ifdef HAVE_LIBPCAP + QTreeWidgetItemIterator iter(this); + + while (*iter) { + QString device_name = (*iter)->data(IFTREE_COL_NAME, Qt::UserRole).value<QString>(); + for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + if (device_name.compare(QString().fromUtf8(device.name)) == 0) { + // To do: + // - Sync with code in CaptureInterfacesDialog. + // - Add more information to the tooltip. + QString tt_str = "<p>"; + if (device.no_addresses > 0) { + tt_str += QString("%1: %2").arg(device.no_addresses > 1 ? tr("Addresses") : tr("Address")).arg(device.addresses); + tt_str.replace('\n', ", "); + } else { + tt_str = tr("No addresses"); + } + tt_str += "<br/>"; + QString cfilter = device.cfilter; + if (cfilter.isEmpty()) { + tt_str += tr("No capture filter"); + } else { + tt_str += QString("%1: %2") + .arg(tr("Capture filter")) + .arg(cfilter); + } + tt_str += "</p>"; + + for (int col = 0; col < columnCount(); col++) { + (*iter)->setToolTip(col, tt_str); + } + } + } + ++iter; + } #endif // HAVE_LIBPCAP } diff --git a/ui/qt/interface_tree.h b/ui/qt/interface_tree.h index 0fc2e0f7c3..decba6a929 100644 --- a/ui/qt/interface_tree.h +++ b/ui/qt/interface_tree.h @@ -58,6 +58,9 @@ public: void resetColumnCount(); + // Used by CaptureInterfacesDialog. + static void updateGlobalDeviceSelections(QTreeWidget *if_tree, int name_col); + protected: void hideEvent(QHideEvent *evt); void showEvent(QShowEvent *evt); @@ -71,7 +74,6 @@ private: #endif // HAVE_LIBPCAP signals: - void interfacesUpdated(); public slots: // add_interface_to_list @@ -79,13 +81,14 @@ public slots: // change_interface_selection_for_all //void getPoints(int row, QList<int> *pts); void getPoints(int row, PointList *pts); - void setSelectedInterfaces(); void interfaceListChanged(); + void selectedInterfaceChanged() { updateGlobalDeviceSelections(this, IFTREE_COL_NAME); } + void updateSelectedInterfaces(); + void updateToolTips(); private slots: void getInterfaceList(); void updateStatistics(void); - void updateSelectedInterfaces(); }; diff --git a/ui/qt/main_welcome.cpp b/ui/qt/main_welcome.cpp index a789132f78..94ac30f399 100644 --- a/ui/qt/main_welcome.cpp +++ b/ui/qt/main_welcome.cpp @@ -171,8 +171,9 @@ MainWelcome::MainWelcome(QWidget *parent) : connect(welcome_ui_->interfaceTree, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(interfaceClicked(QTreeWidgetItem*,int))); #endif - connect(welcome_ui_->interfaceTree, SIGNAL(interfacesUpdated()), + connect(welcome_ui_->interfaceTree, SIGNAL(itemSelectionChanged()), welcome_ui_->captureFilterComboBox, SIGNAL(interfacesChanged())); + connect(welcome_ui_->interfaceTree, SIGNAL(itemSelectionChanged()), this, SLOT(interfaceSelected())); connect(welcome_ui_->captureFilterComboBox->lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(captureFilterTextEdited(QString))); connect(welcome_ui_->captureFilterComboBox, SIGNAL(pushFilterSyntaxStatus(const QString&)), @@ -242,6 +243,13 @@ void MainWelcome::appInitialized() welcome_ui_->childContainer->setGraphicsEffect(NULL); #endif +#ifdef HAVE_LIBPCAP + welcome_ui_->captureFilterComboBox->lineEdit()->setText(global_capture_opts.default_options.cfilter); +#endif // HAVE_LIBPCAP + + // Trigger interfacesUpdated. + welcome_ui_->interfaceTree->selectedInterfaceChanged(); + delete splash_overlay_; splash_overlay_ = NULL; } @@ -275,6 +283,26 @@ void MainWelcome::captureFilterTextEdited(const QString capture_filter) // update_filter_string(device.name, filter_text); } } + welcome_ui_->interfaceTree->updateToolTips(); +} + +// The interface list selection has changed. At this point the user might +// have entered a filter or we might have pre-filled one from a number of +// sources such as our remote connection, the command line, or a previous +// selection. +// Must not change any interface data. +void MainWelcome::interfaceSelected() +{ + QPair <const QString, bool> sf_pair = CaptureFilterEdit::getSelectedFilter(); + const QString user_filter = sf_pair.first; + bool conflict = sf_pair.second; + + if (conflict) { + welcome_ui_->captureFilterComboBox->lineEdit()->clear(); + welcome_ui_->captureFilterComboBox->setConflict(true); + } else { + welcome_ui_->captureFilterComboBox->lineEdit()->setText(user_filter); + } } void MainWelcome::interfaceDoubleClicked(QTreeWidgetItem *item, int) @@ -382,6 +410,12 @@ void MainWelcome::resizeEvent(QResizeEvent *event) QFrame::resizeEvent(event); } +void MainWelcome::setCaptureFilterText(const QString capture_filter) +{ + welcome_ui_->captureFilterComboBox->lineEdit()->setText(capture_filter); + captureFilterTextEdited(capture_filter); +} + void MainWelcome::changeEvent(QEvent* event) { if (0 != event) diff --git a/ui/qt/main_welcome.h b/ui/qt/main_welcome.h index 4118d0668a..d6d7f13c84 100644 --- a/ui/qt/main_welcome.h +++ b/ui/qt/main_welcome.h @@ -45,6 +45,9 @@ public: const QString captureFilter(); void setCaptureFilter(const QString capture_filter); +public slots: + void interfaceSelected(); + protected: void resizeEvent(QResizeEvent *event); @@ -69,6 +72,9 @@ signals: void showExtcapOptions(QString &device_name); #endif +public slots: + void setCaptureFilterText(const QString capture_filter); + private slots: void appInitialized(); void captureFilterTextEdited(const QString capture_filter); diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index 25f501363a..e604c5c708 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -653,10 +653,19 @@ MainWindow::MainWindow(QWidget *parent) : connect(&capture_interfaces_dialog_, SIGNAL(getPoints(int,PointList*)), this->main_welcome_->getInterfaceTree(), SLOT(getPoints(int,PointList*))); - connect(&capture_interfaces_dialog_, SIGNAL(setSelectedInterfaces()), - this->main_welcome_->getInterfaceTree(), SLOT(setSelectedInterfaces())); + // Changes in interface selections or capture filters should be propagated + // to the main welcome screen where they will be applied to the global + // capture options. connect(&capture_interfaces_dialog_, SIGNAL(interfaceListChanged()), this->main_welcome_->getInterfaceTree(), SLOT(interfaceListChanged())); + connect(&capture_interfaces_dialog_, SIGNAL(interfacesChanged()), + this->main_welcome_, SLOT(interfaceSelected())); + connect(&capture_interfaces_dialog_, SIGNAL(interfacesChanged()), + this->main_welcome_->getInterfaceTree(), SLOT(updateSelectedInterfaces())); + connect(&capture_interfaces_dialog_, SIGNAL(interfacesChanged()), + this->main_welcome_->getInterfaceTree(), SLOT(updateToolTips())); + connect(&capture_interfaces_dialog_, SIGNAL(captureFilterTextEdited(QString)), + this->main_welcome_, SLOT(setCaptureFilterText(QString))); #endif /* Create plugin_if hooks */ |