Rename the search type menu items to more accurately reflect what we're
authorGerald Combs <gerald@wireshark.org>
Sat, 15 Dec 2012 01:04:39 +0000 (01:04 -0000)
committerGerald Combs <gerald@wireshark.org>
Sat, 15 Dec 2012 01:04:39 +0000 (01:04 -0000)
actually doing and what users are likely to want to do.  Rename the
search enum values and functions to reflect what we're actually doing
and add a comment explaining why making searches more correct might make
searching worse.  Add a search bar to the Qt main window, thus
continuing the War On Gratuitous Dialogs.

Clear out any previous temporary label stack items before adding a new one.

svn path=/trunk/; revision=46541

18 files changed:
cfile.h
file.c
ui/gtk/find_dlg.c
ui/qt/CMakeLists.txt
ui/qt/Makefile.am
ui/qt/Makefile.common
ui/qt/QtShark.pro
ui/qt/display_filter_edit.cpp
ui/qt/display_filter_edit.h
ui/qt/label_stack.cpp
ui/qt/main_status_bar.cpp
ui/qt/main_window.cpp
ui/qt/main_window.h
ui/qt/main_window.ui
ui/qt/main_window_slots.cpp
ui/qt/search_frame.cpp [new file with mode: 0644]
ui/qt/search_frame.h [new file with mode: 0644]
ui/qt/search_frame.ui [new file with mode: 0644]

diff --git a/cfile.h b/cfile.h
index f5ee3b3a82a05fb113d8edfa4ac46a456ba98713..a23e6febd819574f1b9c60d9844edcf6bd25cad0 100644 (file)
--- a/cfile.h
+++ b/cfile.h
@@ -43,9 +43,9 @@ typedef enum {
 
 /* Character set for text search. */
 typedef enum {
-  SCS_ASCII_AND_UNICODE,
-  SCS_ASCII,
-  SCS_UNICODE
+  SCS_NARROW_AND_WIDE,
+  SCS_NARROW,
+  SCS_WIDE
   /* add EBCDIC when it's implemented */
 } search_charset_t;
 
diff --git a/file.c b/file.c
index 65eb45dd1c1267f600f9189a343758b6d034e11d..d0daf37918ce60be74065b6b83db00a44391e229 100644 (file)
--- a/file.c
+++ b/file.c
@@ -103,11 +103,11 @@ static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
 static void match_subtree_text(proto_node *node, gpointer data);
 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
     void *criterion);
-static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
+static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
     void *criterion);
-static match_result match_ascii(capture_file *cf, frame_data *fdata,
+static match_result match_narrow(capture_file *cf, frame_data *fdata,
     void *criterion);
-static match_result match_unicode(capture_file *cf, frame_data *fdata,
+static match_result match_wide(capture_file *cf, frame_data *fdata,
     void *criterion);
 static match_result match_binary(capture_file *cf, frame_data *fdata,
     void *criterion);
@@ -626,7 +626,7 @@ cf_read(capture_file *cf, gboolean reloading)
         break;
       }
       read_packet(cf, dfcode, create_proto_tree, cinfo, data_offset);
-    } 
+    }
   }
   CATCH(OutOfMemoryError) {
     simple_message_box(ESD_TYPE_ERROR, NULL,
@@ -3111,6 +3111,17 @@ typedef struct {
     size_t        data_len;
 } cbs_t;    /* "Counted byte string" */
 
+
+/*
+ * The current match_* routines only support ASCII case insensitivity and don't
+ * convert UTF-8 inputs to UTF-16 for matching.
+ *
+ * We could modify them to use the GLib Unicode routines or the International
+ * Components for Unicode library but it's not apparent that we could do so
+ * without consuming a lot more CPU and memory or that searching would be
+ * significantly better.
+ */
+
 gboolean
 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
                     search_direction dir)
@@ -3125,14 +3136,14 @@ cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
     /* String search - what type of string? */
     switch (cf->scs_type) {
 
-    case SCS_ASCII_AND_UNICODE:
-      return find_packet(cf, match_ascii_and_unicode, &info, dir);
+    case SCS_NARROW_AND_WIDE:
+      return find_packet(cf, match_narrow_and_wide, &info, dir);
 
-    case SCS_ASCII:
-      return find_packet(cf, match_ascii, &info, dir);
+    case SCS_NARROW:
+      return find_packet(cf, match_narrow, &info, dir);
 
-    case SCS_UNICODE:
-      return find_packet(cf, match_unicode, &info, dir);
+    case SCS_WIDE:
+      return find_packet(cf, match_wide, &info, dir);
 
     default:
       g_assert_not_reached();
@@ -3143,7 +3154,7 @@ cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
 }
 
 static match_result
-match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
+match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
 {
   cbs_t        *info       = criterion;
   const guint8 *ascii_text = info->data;
@@ -3189,7 +3200,7 @@ match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
 }
 
 static match_result
-match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
+match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
 {
   cbs_t        *info       = criterion;
   const guint8 *ascii_text = info->data;
@@ -3234,7 +3245,7 @@ match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
 }
 
 static match_result
-match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
+match_wide(capture_file *cf, frame_data *fdata, void *criterion)
 {
   cbs_t        *info       = criterion;
   const guint8 *ascii_text = info->data;
@@ -3699,7 +3710,7 @@ cf_select_packet(capture_file *cf, int row)
   cf->edt = epan_dissect_new(TRUE, TRUE);
 
   tap_build_interesting(cf->edt);
-  epan_dissect_run(cf->edt, &cf->phdr, cf->pd, cf->current_frame, 
+  epan_dissect_run(cf->edt, &cf->phdr, cf->pd, cf->current_frame,
           NULL);
 
   dfilter_macro_build_ftv_cache(cf->edt->tree);
index e8085ed65c8bbf87e79bb8f6e7468841cc26fa3d..b0c61a02ddf32ccbfef5a37cc9244252df877532 100644 (file)
@@ -276,7 +276,7 @@ find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
   gtk_widget_set_tooltip_text(case_cb, "Search by mixed upper/lower case?");
   gtk_widget_show(case_cb);
 
-  combo_lb = gtk_label_new("Character set:");
+  combo_lb = gtk_label_new("Character width:");
   gtk_box_pack_start(GTK_BOX (string_opt_vb), combo_lb, TRUE, TRUE, 0);
   gtk_misc_set_alignment(GTK_MISC(combo_lb), 0.0f, 0.5f);
   gtk_widget_show(combo_lb);
@@ -287,9 +287,10 @@ find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
 
   combo_cb = gtk_combo_box_text_new();
 
-  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "ASCII Unicode & Non-Unicode");
-  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "ASCII Non-Unicode");
-  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "ASCII Unicode");
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "Narrow & wide");
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "Narrow (UTF-8 / ASCII)");
+  /* UCS-2 might be more accurate but then we'd have to explain why we don't support UTF-16 */
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "Wide (UTF-16)");
 
   gtk_combo_box_set_active(GTK_COMBO_BOX(combo_cb),0);
   gtk_box_pack_start(GTK_BOX (string_opt_vb), combo_cb, TRUE, TRUE, 0);
@@ -545,7 +546,7 @@ find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
   GtkWidget       *filter_te, *up_rb, *hex_rb, *string_rb, *combo_cb,
                   *case_cb, *packet_data_rb, *decode_data_rb, *summary_data_rb;
   const gchar     *filter_text;
-  search_charset_t scs_type = SCS_ASCII_AND_UNICODE;
+  search_charset_t scs_type = SCS_NARROW_AND_WIDE;
   guint8          *bytes = NULL;
   size_t           nbytes = 0;
   char            *string = NULL;
@@ -570,9 +571,9 @@ find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
   /* Corresponds to the enum in file.c
    * Character set for text search.
    * typedef enum {
-   *   SCS_ASCII_AND_UNICODE,
-   *   SCS_ASCII,
-   *   SCS_UNICODE
+   *   SCS_NARROW_AND_WIDE,
+   *   SCS_NARROW,
+   *   SCS_WIDE
    *   / * add EBCDIC when it's implemented * /
    * } search_charset_t;
    */
@@ -610,12 +611,12 @@ find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
     /*
      * We are - get the character set type.
      */
-    if (string_type == SCS_ASCII_AND_UNICODE)
-      scs_type = SCS_ASCII_AND_UNICODE;
-    else if (string_type == SCS_ASCII)
-      scs_type = SCS_ASCII;
-    else if (string_type == SCS_UNICODE)
-      scs_type = SCS_UNICODE;
+    if (string_type == SCS_NARROW_AND_WIDE)
+      scs_type = SCS_NARROW_AND_WIDE;
+    else if (string_type == SCS_NARROW)
+      scs_type = SCS_NARROW;
+    else if (string_type == SCS_WIDE)
+      scs_type = SCS_WIDE;
     else {
       statusbar_push_temporary_msg("You didn't choose a valid character set.");
       return;
index 09ccaf633ad1c6f0f1f43c63df8812d5da1bdacd..76b8b484d47b17d7dbdf94a23191bb5c891fa782 100644 (file)
@@ -52,6 +52,7 @@ set(QTSHARK_H_SRC
        proto_tree.h
        recent_file_status.h
        simple_dialog_qt.h
+       search_frame.h
        splash_overlay.h
        syntax_line_edit.h
        wireshark_application.h
@@ -95,6 +96,7 @@ set(QTSHARK_CPP_SRC
        recent_file_status.cpp
        simple_dialog_qt.cpp
        sparkline_delegate.cpp
+       search_frame.cpp
        splash_overlay.cpp
        syntax_line_edit.cpp
        wireshark_application.cpp
@@ -113,6 +115,7 @@ set(QTSHARK_UI
        packet_format_group_box.ui
        packet_range_group_box.ui
        print_dialog.ui
+       search_frame.ui
        splash_overlay.ui
 )
 
index f806a56cb5077d8b7367705a72fd173e6521f29e..b7c1e28a183d590097dd9ad45c0fead4392ca1d6 100644 (file)
@@ -116,6 +116,11 @@ print_dialog.h: ui_print_dialog.h
 ui_print_dialog.h: print_dialog.ui
        uic $< -o $@
 
+search_frame.h: ui_search_frame.h
+
+ui_search_frame.h: search_frame.ui
+       uic $< -o $@
+
 splash_overlay.h: ui_splash_overlay.h
 
 ui_splash_overlay.h: splash_overlay.ui
@@ -183,6 +188,7 @@ EXTRA_DIST = \
        packet_range_group_box.ui       \
        print_dialog.ui                 \
        QtShark.pro                     \
+       search_frame.ui                 \
        splash_overlay.ui               \
        display_filter_16.svg           \
        gpl-template.txt
index 148c5361b7a0a5c73067c57811913fd144839ed1..fa268d090d76f99c7b8fb29c53e4bc578c1f4fe6 100644 (file)
@@ -39,6 +39,7 @@ GENERATED_NODIST_HEADER_FILES = \
        ui_packet_format_group_box.h \
        ui_packet_range_group_box.h \
        ui_print_dialog.h \
+       ui_search_frame.h
        ui_splash_overlay.h
 
 # Generated C source files that we want in the distribution.
@@ -103,6 +104,7 @@ MOC_HDRS = \
        recent_file_status.h \
        simple_dialog_qt.h \
        sparkline_delegate.h \
+       search_frame.h \
        splash_overlay.h \
        syntax_line_edit.h \
        wireshark_application.h
@@ -182,6 +184,7 @@ WIRESHARK_QT_SRC = \
        recent_file_status.cpp \
        simple_dialog_qt.cpp \
        sparkline_delegate.cpp \
+       search_frame.cpp \
        splash_overlay.cpp \
        syntax_line_edit.cpp \
        wireshark_application.cpp
index 6ad7729be7a4058d95689f1eb84ef5497e60b2f4..afa1f9692d1f6253e429a415dbace31ea0f3808e 100644 (file)
@@ -187,7 +187,8 @@ FORMS += main_window.ui \
     packet_format_group_box.ui \
     export_object_dialog.ui \
     print_dialog.ui \
-    splash_overlay.ui
+    splash_overlay.ui \
+    search_frame.ui
 
 win32 { ## These should be in config.pri ??
     !isEmpty(PORTAUDIO_DIR) {
@@ -215,7 +216,8 @@ HEADERS += $$HEADERS_WS_C \
     packet_format_group_box.h \
     export_object_dialog.h \
     print_dialog.h \
-    splash_overlay.h
+    splash_overlay.h \
+    search_frame.h
 
 win32 {
     OBJECTS_WS_C = $$SOURCES_WS_C
@@ -427,4 +429,5 @@ SOURCES += \
     sparkline_delegate.cpp \
     splash_overlay.cpp \
     syntax_line_edit.cpp \
-    wireshark_application.cpp
+    wireshark_application.cpp \
+    search_frame.cpp
index ae13d6dc9a60c5f921dcfbe84f48252c3f4c78c3..3afd543f384345607a9cded33f6fc2c631d85ef7 100644 (file)
@@ -23,8 +23,6 @@
 
 #include "config.h"
 
-#include "globals.h"
-
 #include <glib.h>
 
 #include <epan/proto.h>
@@ -268,7 +266,7 @@ void DisplayFilterEdit::checkFilter(const QString& text)
         if (dfp != NULL) {
             depr = dfilter_deprecated_tokens(dfp);
         }
-        if (text.length() < 1) {
+        if (text.isEmpty()) {
             setSyntaxState(Empty);
         } else if (depr) {
             /* You keep using that word. I do not think it means what you think it means. */
index efe69e28b00eaa7517f35be5e7e4dcd93c0372e9..e43c91b5d5cafbcf97a73d6124f4909fd634c348 100644 (file)
@@ -61,8 +61,6 @@ signals:
     void pushFilterSyntaxWarning(QString&);
     void filterPackets(QString& new_filter, bool force);
 
-public slots:
-
 };
 
 #endif // DISPLAYFILTEREDIT_H
index 142d0977168375d75de75e7c321b4b8907faad7f..8480a3eb5e83e34123e810b126c38562019ae0b8 100644 (file)
@@ -79,16 +79,19 @@ void LabelStack::fillLabel() {
 
 void LabelStack::pushText(QString &text, int ctx) {
     StackItem *si = new StackItem;
-    si->text = text;
-    si->ctx = ctx;
-    labels_.prepend(si);
 
     if (ctx == temporary_ctx_) {
+        temporary_timer_.stop();
+        popText(temporary_ctx_);
+
         temporary_epoch_.start();
         temporary_timer_.start(temporary_flash_timeout_);
         emit toggleTemporaryFlash(true);
     }
 
+    si->text = text;
+    si->ctx = ctx;
+    labels_.prepend(si);
     fillLabel();
 }
 
index 894c2ccb51710201e6808986bb4429f030ae1fe6..deaa1829afcd469ded37d6911125a4bce74707ce 100644 (file)
@@ -64,19 +64,15 @@ void
 statusbar_push_temporary_msg(const gchar *msg_format, ...)
 {
     va_list ap;
-    gchar *msg;
-    QString pushMsg;
+    QString push_msg;
 
     if (!cur_main_status_bar_) return;
 
     va_start(ap, msg_format);
-    msg = g_strdup_vprintf(msg_format, ap);
+    push_msg.vsprintf(msg_format, ap);
     va_end(ap);
 
-    pushMsg.fromUtf8(msg);
-    g_free(msg);
-
-    cur_main_status_bar_->pushTemporaryStatus(pushMsg);
+    cur_main_status_bar_->pushTemporaryStatus(push_msg);
 }
 
 /*
index 6101e52fe81e5dcf8e4beb14b685ce7d067fd6be..eec9f720ff0099efcd982e91a0019ad4153c21bd 100644 (file)
@@ -81,8 +81,6 @@ MainWindow::MainWindow(QWidget *parent) :
     pipe_notifier_(NULL)
 #endif
 {
-    QMargins go_to_margins;
-
     gbl_cur_main_window = this;
     main_ui_->setupUi(this);
     setMenusForCaptureFile();
@@ -116,24 +114,26 @@ MainWindow::MainWindow(QWidget *parent) :
     // This property is obsolete in Qt5 so this issue may be fixed in that version.
     main_ui_->displayFilterToolBar->addWidget(df_combo_box_);
 
-    main_ui_->goToFrame->hide();
-    go_to_margins = main_ui_->goToHB->contentsMargins();
-//    go_to_margins.setTop(0);
-//    go_to_margins.setBottom(0);
-    main_ui_->goToHB->setContentsMargins(go_to_margins);
-    // XXX For some reason the cursor is drawn funny with an input mask set
-    // https://bugreports.qt-project.org/browse/QTBUG-7174
-    main_ui_->goToFrame->setStyleSheet(
-                "QFrame {"
+    QString subframe_style(
+                ".QFrame {"
                 "  background: palette(window);"
                 "  padding-top: 0.1em;"
                 "  padding-bottom: 0.1em;"
                 "  border-bottom: 1px solid palette(shadow);"
                 "}"
-                "QLineEdit {"
+                "QLineEdit#goToLineEdit {"
                 "  max-width: 5em;"
                 "}"
                 );
+    main_ui_->goToFrame->hide();
+    // XXX For some reason the cursor is drawn funny with an input mask set
+    // https://bugreports.qt-project.org/browse/QTBUG-7174
+    main_ui_->goToFrame->setStyleSheet(subframe_style);
+
+    main_ui_->searchFrame->hide();
+    main_ui_->searchFrame->setStyleSheet(subframe_style);
+    connect(main_ui_->searchFrame, SIGNAL(pushFilterSyntaxStatus(QString&)),
+            main_ui_->statusBar, SLOT(pushTemporaryStatus(QString&)));
 
 #if defined(Q_WS_MAC)
     foreach (QMenu *menu, main_ui_->menuBar->findChildren<QMenu*>()) {
@@ -205,6 +205,8 @@ MainWindow::MainWindow(QWidget *parent) :
     connect(main_welcome_, SIGNAL(recentFileActivated(QString&)),
             this, SLOT(openCaptureFile(QString&)));
 
+    connect(this, SIGNAL(setCaptureFile(capture_file*)),
+            main_ui_->searchFrame, SLOT(setCaptureFile(capture_file*)));
     connect(this, SIGNAL(setCaptureFile(capture_file*)),
             main_ui_->statusBar, SLOT(setCaptureFile(capture_file*)));
     connect(this, SIGNAL(setCaptureFile(capture_file*)),
@@ -1208,12 +1210,9 @@ void MainWindow::setForCapturedPackets(bool have_captured_packets)
 //    set_menu_sensitivity(ui_manager_packet_list_menu, "/PacketListMenuPopup/Print",
 //                         have_captured_packets);
 
-//    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/FindPacket",
-//                         have_captured_packets);
-//    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/FindNext",
-//                         have_captured_packets);
-//    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/FindPrevious",
-//                         have_captured_packets);
+    main_ui_->actionEditFindPacket->setEnabled(have_captured_packets);
+    main_ui_->actionEditFindNext->setEnabled(have_captured_packets);
+    main_ui_->actionEditFindPrevious->setEnabled(have_captured_packets);
 //    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/ZoomIn",
 //                         have_captured_packets);
 //    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/ZoomOut",
index 0dba4513dfd9093710829406f595f150b93f4eca..e7c8bb52c052252b02a920b62fa9c8ea5f697104 100644 (file)
@@ -200,6 +200,9 @@ private slots:
     void on_actionEditCopyFieldName_triggered();
     void on_actionEditCopyValue_triggered();
     void on_actionEditCopyAsFilter_triggered();
+    void on_actionEditFindPacket_triggered();
+    void on_actionEditFindNext_triggered();
+    void on_actionEditFindPrevious_triggered();
 
     void on_actionGoGoToPacket_triggered();
     void resetPreviousFocus();
index ab8d9c364e022e417983fd189c28bdcd63ca2d85..5c40f891d0ae13e4e1c3ff2487ca2bcdde28abd5 100644 (file)
@@ -77,6 +77,9 @@
      </widget>
     </item>
     <item row="1" column="0">
+     <widget class="SearchFrame" name="searchFrame" native="true"/>
+    </item>
+    <item row="2" column="0">
      <widget class="QStackedWidget" name="mainStack">
       <widget class="MainWelcome" name="welcomePage"/>
       <widget class="QWidget" name="packetPage"/>
      <addaction name="actionEditCopyAsFilter"/>
     </widget>
     <addaction name="menuEditCopy"/>
+    <addaction name="actionEditFindPacket"/>
+    <addaction name="actionEditFindNext"/>
+    <addaction name="actionEditFindPrevious"/>
    </widget>
    <widget class="QMenu" name="menuCapture">
     <property name="title">
     <string>Apply as Column</string>
    </property>
   </action>
+  <action name="actionEditFindPacket">
+   <property name="text">
+    <string>&amp;Find Packet...</string>
+   </property>
+   <property name="toolTip">
+    <string>Find a packet</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+F</string>
+   </property>
+  </action>
+  <action name="actionEditFindNext">
+   <property name="text">
+    <string>Find Ne&amp;xt...</string>
+   </property>
+   <property name="toolTip">
+    <string>Find the next packet</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+N</string>
+   </property>
+  </action>
+  <action name="actionEditFindPrevious">
+   <property name="text">
+    <string>Find Pre&amp;vious...</string>
+   </property>
+   <property name="toolTip">
+    <string>Find the previous packet</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+B</string>
+   </property>
+  </action>
  </widget>
  <layoutdefault spacing="6" margin="11"/>
  <customwidgets>
    <header>main_welcome.h</header>
    <container>1</container>
   </customwidget>
+  <customwidget>
+   <class>SearchFrame</class>
+   <extends>QWidget</extends>
+   <header>search_frame.h</header>
+  </customwidget>
  </customwidgets>
  <resources>
   <include location="../../image/toolbar.qrc"/>
index bc221b133e015f8566b41636845fc82a0bf4cd93..aca621c7435f1483cd26aed475fbe38b021c2dbd 100644 (file)
@@ -320,6 +320,7 @@ void MainWindow::captureFileClosing(const capture_file *cf) {
 
     // Reset expert info indicator
     main_ui_->statusBar->hideExpert();
+    main_ui_->searchFrame->hide();
 //    gtk_widget_show(expert_info_none);
     emit setCaptureFile(NULL);
 }
@@ -945,6 +946,31 @@ void MainWindow::on_actionEditCopyAsFilter_triggered()
     matchSelectedFilter(MatchSelectedReplace, false, true);
 }
 
+void MainWindow::on_actionEditFindPacket_triggered()
+{
+    if (packet_list_->model()->rowCount() < 1) {
+        return;
+    }
+    previous_focus_ = wsApp->focusWidget();
+    connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
+    main_ui_->goToFrame->hide();
+    if (main_ui_->searchFrame->isVisible()) {
+        main_ui_->searchFrame->hide();
+    } else {
+        main_ui_->searchFrame->show();
+    }
+}
+
+void MainWindow::on_actionEditFindNext_triggered()
+{
+    main_ui_->searchFrame->findNext();
+}
+
+void MainWindow::on_actionEditFindPrevious_triggered()
+{
+    main_ui_->searchFrame->findPrevious();
+}
+
 // View Menu
 
 // Expand / collapse slots in proto_tree
@@ -1172,7 +1198,13 @@ void MainWindow::on_actionGoGoToPacket_triggered() {
     }
     previous_focus_ = wsApp->focusWidget();
     connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
-    main_ui_->goToFrame->show();
+
+    main_ui_->searchFrame->hide();
+    if (main_ui_->goToFrame->isVisible()) {
+        main_ui_->goToFrame->hide();
+    } else {
+        main_ui_->goToFrame->show();
+    }
     main_ui_->goToLineEdit->setFocus();
 }
 
diff --git a/ui/qt/search_frame.cpp b/ui/qt/search_frame.cpp
new file mode 100644 (file)
index 0000000..a2b9e13
--- /dev/null
@@ -0,0 +1,373 @@
+/* search_frame.cpp
+ *
+ * $Id: splash_overlay.cpp 45941 2012-11-05 22:43:15Z gerald $
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "search_frame.h"
+#include "ui_search_frame.h"
+
+#include <epan/proto.h>
+#include <epan/strutil.h>
+
+#include "wireshark_application.h"
+#include <QKeyEvent>
+#include <QCheckBox>
+
+const int in_packet_list = 0;
+const int in_proto_tree = 1;
+const int in_bytes = 2;
+
+const int df_search = 0;
+const int hex_search = 1;
+const int string_search = 2;
+
+const int narrow_and_wide_chars = 0;
+const int narrow_chars = 1;
+const int wide_chars = 2;
+
+SearchFrame::SearchFrame(QWidget *parent) :
+    QFrame(parent),
+    sf_ui_(new Ui::SearchFrame),
+    cap_file_(NULL)
+{
+    sf_ui_->setupUi(this);
+
+#ifdef Q_WS_MAC
+    foreach (QWidget *w, findChildren<QWidget *>()) {
+        w->setAttribute(Qt::WA_MacSmallSize, true);
+    }
+#endif
+    sf_ui_->searchTypeComboBox->setCurrentIndex(0);
+    enableWidgets();
+}
+
+SearchFrame::~SearchFrame()
+{
+    delete sf_ui_;
+}
+
+void SearchFrame::show()
+{
+    sf_ui_->searchLineEdit->setFocus();
+    QFrame::show();
+}
+
+void SearchFrame::findNext()
+{
+    if (!cap_file_) return;
+
+    cap_file_->dir = SD_FORWARD;
+    if (isHidden()) {
+        show();
+        return;
+    }
+    on_findButton_clicked();
+}
+
+void SearchFrame::findPrevious()
+{
+    if (!cap_file_) return;
+
+    cap_file_->dir = SD_BACKWARD;
+    if (isHidden()) {
+        show();
+        return;
+    }
+    on_findButton_clicked();
+}
+
+void SearchFrame::setCaptureFile(capture_file *cf)
+{
+    cap_file_ = cf;
+    if (!cf && isVisible()) {
+        hide();
+    }
+    enableWidgets();
+}
+
+void SearchFrame::findFrameWithFilter(QString &filter)
+{
+    show();
+    sf_ui_->searchLineEdit->setText(filter);
+    sf_ui_->searchTypeComboBox->setCurrentIndex(0);
+    enableWidgets();
+}
+
+void SearchFrame::keyPressEvent(QKeyEvent *event)
+{
+    if (wsApp->focusWidget() == sf_ui_->searchLineEdit) {
+        if (event->modifiers() == Qt::NoModifier) {
+            if (event->key() == Qt::Key_Escape) {
+                on_cancelButton_clicked();
+            } else if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
+                on_findButton_clicked();
+            }
+        }
+        return; // searchLineEdit didn't want it and we don't either.
+    }
+}
+
+void SearchFrame::enableWidgets()
+{
+    if (cap_file_) {
+        setEnabled(true);
+    } else {
+        setEnabled(false);
+        return;
+    }
+
+    dfilter_t *dfp = NULL;
+    bool enable = sf_ui_->searchTypeComboBox->currentIndex() == string_search;
+    sf_ui_->searchInComboBox->setEnabled(enable);
+    sf_ui_->caseCheckBox->setEnabled(enable);
+    sf_ui_->charEncodingComboBox->setEnabled(enable);
+
+    switch (sf_ui_->searchTypeComboBox->currentIndex()) {
+    case df_search:
+        // XXX - Merge this with DisplayFitlerEdit::checkFilter
+        if (dfilter_compile(sf_ui_->searchLineEdit->text().toUtf8().constData(), &dfp)) {
+                GPtrArray *depr = NULL;
+                if (dfp != NULL) {
+                    depr = dfilter_deprecated_tokens(dfp);
+                }
+                if (sf_ui_->searchLineEdit->text().isEmpty()) {
+                    sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Empty);
+                } else if (depr) {
+                    /* You keep using that word. I do not think it means what you think it means. */
+                    sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Deprecated);
+                } else {
+                    sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Valid);
+                }
+                dfilter_free(dfp);
+        } else {
+            sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Invalid);
+        }
+        break;
+    case hex_search:
+        if (sf_ui_->searchLineEdit->text().isEmpty()) {
+            sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Invalid);
+        } else {
+            guint8 *bytes = NULL;
+            size_t nbytes;
+            bytes = convert_string_to_hex(sf_ui_->searchLineEdit->text().toUtf8().constData(), &nbytes);
+            if (bytes == NULL)
+                sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Invalid);
+            else {
+              g_free(bytes);
+              sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Valid);
+            }
+        }
+        break;
+    case string_search:
+        if (sf_ui_->searchLineEdit->text().isEmpty()) {
+            sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Invalid);
+        } else {
+            sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Valid);
+        }
+        break;
+    default:
+        QString err_string = tr("No valid search type selected. Please report this to the development team.");
+        emit pushFilterSyntaxStatus(err_string);
+        return;
+    }
+
+    if (sf_ui_->searchLineEdit->text().isEmpty() || sf_ui_->searchLineEdit->syntaxState() == SyntaxLineEdit::Invalid) {
+        sf_ui_->findButton->setEnabled(false);
+    } else {
+        sf_ui_->findButton->setEnabled(true);
+    }
+}
+
+void SearchFrame::on_searchTypeComboBox_currentIndexChanged(int index)
+{
+    Q_UNUSED(index);
+    enableWidgets();
+}
+
+void SearchFrame::on_searchLineEdit_textChanged(const QString &search_string)
+{
+    Q_UNUSED(search_string);
+    enableWidgets();
+}
+
+void SearchFrame::on_findButton_clicked()
+{
+    guint8 *bytes = NULL;
+    size_t nbytes;
+    char *string = NULL;
+    dfilter_t *dfp;
+    gboolean found_packet = FALSE;
+    QString err_string;
+
+    if (!cap_file_) {
+        return;
+    }
+
+    cap_file_->hex = FALSE;
+    cap_file_->string = FALSE;
+    cap_file_->case_type = FALSE;
+    cap_file_->packet_data  = FALSE;
+    cap_file_->decode_data  = FALSE;
+    cap_file_->summary_data = FALSE;
+    cap_file_->scs_type = SCS_NARROW_AND_WIDE;
+
+    switch (sf_ui_->searchTypeComboBox->currentIndex()) {
+    case df_search:
+        if (!dfilter_compile(sf_ui_->searchLineEdit->text().toUtf8().constData(), &dfp)) {
+            err_string = tr("Invalid filter.");
+            emit pushFilterSyntaxStatus(err_string);
+            return;
+        }
+
+        if (dfp == NULL) {
+            err_string = tr("That filter doesn't test anything.");
+            emit pushFilterSyntaxStatus(err_string);
+            return;
+        }
+        break;
+    case hex_search:
+        bytes = convert_string_to_hex(sf_ui_->searchLineEdit->text().toUtf8().constData(), &nbytes);
+        if (bytes == NULL) {
+            err_string = tr("That's not a valid hex string.");
+            emit pushFilterSyntaxStatus(err_string);
+            return;
+        }
+        cap_file_->hex = TRUE;
+        break;
+    case string_search:
+        if (sf_ui_->searchLineEdit->text().isEmpty()) {
+            err_string = tr("You didn't specify any text for which to search.");
+            emit pushFilterSyntaxStatus(err_string);
+            return;
+        }
+        cap_file_->string = TRUE;
+        cap_file_->case_type = sf_ui_->caseCheckBox->isChecked() ? FALSE : TRUE;
+        switch (sf_ui_->charEncodingComboBox->currentIndex()) {
+        case narrow_and_wide_chars:
+            cap_file_->scs_type = SCS_NARROW_AND_WIDE;
+            break;
+        case narrow_chars:
+            cap_file_->scs_type = SCS_NARROW;
+            break;
+        case wide_chars:
+            cap_file_->scs_type = SCS_WIDE;
+            break;
+        default:
+            err_string = tr("No valid character set selected. Please report this to the development team.");
+            emit pushFilterSyntaxStatus(err_string);
+            return;
+        }
+        string = convert_string_case(sf_ui_->searchLineEdit->text().toUtf8().constData(), cap_file_->case_type);
+        break;
+    default:
+        err_string = tr("No valid search type selected. Please report this to the development team.");
+        emit pushFilterSyntaxStatus(err_string);
+        return;
+    }
+
+    switch (sf_ui_->searchInComboBox->currentIndex()) {
+    case in_packet_list:
+        cap_file_->summary_data = TRUE;
+        break;
+    case in_proto_tree:
+        cap_file_->decode_data  = TRUE;
+        break;
+    case in_bytes:
+        cap_file_->packet_data  = TRUE;
+        break;
+    default:
+        err_string = tr("No valid search area selected. Please report this to the development team.");
+        emit pushFilterSyntaxStatus(err_string);
+        return;
+    }
+
+    g_free(cap_file_->sfilter);
+    cap_file_->sfilter = g_strdup(sf_ui_->searchLineEdit->text().toUtf8().constData());
+
+    if (cap_file_->hex) {
+        /* Hex value in packet data */
+        found_packet = cf_find_packet_data(cap_file_, bytes, nbytes, cap_file_->dir);
+        g_free(bytes);
+        if (!found_packet) {
+            /* We didn't find a packet */
+            err_string = tr("No packet contained those bytes.");
+            emit pushFilterSyntaxStatus(err_string);
+            return;
+        }
+    } else if (cap_file_->string) {
+        if (cap_file_->summary_data) {
+            /* String in the Info column of the summary line */
+            found_packet = cf_find_packet_summary_line(cap_file_, string, cap_file_->dir);
+            g_free(string);
+            if (!found_packet) {
+                err_string = tr("No packet contained that string in its Info column.");
+                emit pushFilterSyntaxStatus(err_string);
+                return;
+            }
+        } else if (cap_file_->decode_data) {
+            /* String in the protocol tree headings */
+            found_packet = cf_find_packet_protocol_tree(cap_file_, string, cap_file_->dir);
+            g_free(string);
+            if (!found_packet) {
+                err_string = tr("No packet contained that string in its dissected display.");
+                emit pushFilterSyntaxStatus(err_string);
+                return;
+            }
+        } else if (cap_file_->packet_data && string) {
+            /* String in the ASCII-converted packet data */
+            found_packet = cf_find_packet_data(cap_file_, (guint8 *) string, strlen(string), cap_file_->dir);
+            g_free(string);
+            if (!found_packet) {
+                err_string = tr("No packet contained that string in its converted data.");
+                emit pushFilterSyntaxStatus(err_string);
+                return;
+            }
+        }
+    } else {
+        /* Search via display filter */
+        found_packet = cf_find_packet_dfilter(cap_file_, dfp, cap_file_->dir);
+        dfilter_free(dfp);
+        if (!found_packet) {
+            err_string = tr("No packet matched that filter.");
+            emit pushFilterSyntaxStatus(err_string);
+            g_free(bytes);
+            return;
+        }
+    }
+}
+
+void SearchFrame::on_cancelButton_clicked()
+{
+    hide();
+}
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/search_frame.h b/ui/qt/search_frame.h
new file mode 100644 (file)
index 0000000..c729725
--- /dev/null
@@ -0,0 +1,74 @@
+/* search_frame.h
+ *
+ * $Id: splash_overlay.cpp 45941 2012-11-05 22:43:15Z gerald $
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef SEARCH_FRAME_H
+#define SEARCH_FRAME_H
+
+#include <config.h>
+
+#include <QFrame>
+
+#include "cfile.h"
+
+namespace Ui {
+class SearchFrame;
+}
+
+class SearchFrame : public QFrame
+{
+    Q_OBJECT
+    
+public:
+    explicit SearchFrame(QWidget *parent = 0);
+    ~SearchFrame();
+    void show();
+    void findNext();
+    void findPrevious();
+
+public slots:
+    void setCaptureFile(capture_file *cf);
+    void findFrameWithFilter(QString &filter);
+    
+signals:
+    void pushFilterSyntaxStatus(QString&);
+
+protected:
+    void keyPressEvent(QKeyEvent *event);
+
+private:
+    void enableWidgets();
+
+    Ui::SearchFrame *sf_ui_;
+    capture_file *cap_file_;
+
+private slots:
+    void on_searchTypeComboBox_currentIndexChanged(int index);
+
+    void on_searchLineEdit_textChanged(const QString &search_string);
+
+    void on_findButton_clicked();
+
+    void on_cancelButton_clicked();
+};
+
+#endif // SEARCH_FRAME_H
diff --git a/ui/qt/search_frame.ui b/ui/qt/search_frame.ui
new file mode 100644 (file)
index 0000000..d82c62a
--- /dev/null
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SearchFrame</class>
+ <widget class="QFrame" name="SearchFrame">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1026</width>
+    <height>30</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Frame</string>
+  </property>
+  <property name="frameShape">
+   <enum>QFrame::NoFrame</enum>
+  </property>
+  <property name="frameShadow">
+   <enum>QFrame::Plain</enum>
+  </property>
+  <property name="lineWidth">
+   <number>0</number>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QComboBox" name="searchInComboBox">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Search the Info column of the packet list (summary pane), decoded packet display labels (tree view pane) or the ASCII-converted packet data (hex view pane).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <item>
+      <property name="text">
+       <string>Packet list</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Packet details</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Packet bytes</string>
+      </property>
+     </item>
+    </widget>
+   </item>
+   <item>
+    <spacer name="horizontalSpacer_2">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>40</width>
+       <height>5</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QComboBox" name="charEncodingComboBox">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <item>
+      <property name="text">
+       <string>Narrow &amp; Wide</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Narrow (UTF-8 / ASCII)</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Wide (UTF-16)</string>
+      </property>
+     </item>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="caseCheckBox">
+     <property name="text">
+      <string>Case sensitive</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <spacer name="horizontalSpacer">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>40</width>
+       <height>5</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QComboBox" name="searchTypeComboBox">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <item>
+      <property name="text">
+       <string>Display filter</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Hex value</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>String</string>
+      </property>
+     </item>
+    </widget>
+   </item>
+   <item>
+    <widget class="SyntaxLineEdit" name="searchLineEdit">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+       <horstretch>1</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QToolButton" name="findButton">
+     <property name="text">
+      <string>Find</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QToolButton" name="cancelButton">
+     <property name="text">
+      <string>Cancel</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>SyntaxLineEdit</class>
+   <extends>QLineEdit</extends>
+   <header>syntax_line_edit.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>