Qt: fix use-after-free on error while saving exported packets
[metze/wireshark/wip.git] / ui / qt / main_window_slots.cpp
index 9c5d386759cd96ebcb1e193721a32844aa80f23e..5ffed4b0a52baad3b53aa64f81f5be8ba8c81083 100644 (file)
@@ -4,19 +4,7 @@
  * 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.
+ * SPDX-License-Identifier: GPL-2.0-or-later
  */
 
 #include <config.h>
 #endif
 
 #include "main_window.h"
+
+/*
+ * The generated Ui_MainWindow::setupUi() can grow larger than our configured limit,
+ * so turn off -Wframe-larger-than= for ui_main_window.h.
+ */
+DIAG_OFF(frame-larger-than=)
 #include <ui_main_window.h>
+DIAG_ON(frame-larger-than=)
 
 #ifdef _WIN32
 #include <windows.h>
 #endif
 
+#include "ui/dissect_opts.h"
+
 #ifdef HAVE_LIBPCAP
 #include "ui/capture.h"
 #endif
 
-#include "color_filters.h"
+#include "ui/commandline.h"
+
+#include "epan/color_filters.h"
+#include "epan/export_object.h"
 
 #include "wsutil/file_util.h"
 #include "wsutil/filesystem.h"
-#include "wsutil/str_util.h"
 
 #include "epan/addr_resolv.h"
-#include "epan/dissector_filters.h"
 #include "epan/column.h"
 #include "epan/dfilter/dfilter-macro.h"
+#include "epan/dissector_filters.h"
 #include "epan/epan_dissect.h"
 #include "epan/filter_expressions.h"
 #include "epan/prefs.h"
+#include "epan/plugin_if.h"
 #include "epan/uat.h"
+#include "epan/uat-int.h"
 #include "epan/value_string.h"
 
 #ifdef HAVE_LUA
 #include "ui/recent.h"
 #include "ui/recent_utils.h"
 #include "ui/ssl_key_export.h"
-#include "ui/ui_util.h"
+#include "ui/ws_ui_util.h"
+#include "ui/all_files_wildcard.h"
 #include "ui/qt/simple_dialog.h"
 
+#include <ui/qt/utils/variant_pointer.h>
+#include <ui/qt/widgets/drag_drop_toolbar.h>
+#include "ui/qt/widgets/wireshark_file_dialog.h"
+
 #ifdef HAVE_SOFTWARE_UPDATE
 #include "ui/software_update.h"
 #endif
 #include "bluetooth_hci_summary_dialog.h"
 #include "capture_file_dialog.h"
 #include "capture_file_properties_dialog.h"
-#include "color_utils.h"
+#ifdef HAVE_LIBPCAP
+#include "capture_interfaces_dialog.h"
+#endif
+#include <ui/qt/utils/color_utils.h>
 #include "coloring_rules_dialog.h"
 #include "conversation_dialog.h"
+#include "conversation_colorize_action.h"
 #include "conversation_hash_tables_dialog.h"
 #include "enabled_protocols_dialog.h"
 #include "decode_as_dialog.h"
-#include "display_filter_edit.h"
+#include <ui/qt/widgets/display_filter_edit.h>
 #include "display_filter_expression_dialog.h"
 #include "dissector_tables_dialog.h"
 #include "endpoint_dialog.h"
 #include "expert_info_dialog.h"
+#include "export_object_action.h"
 #include "export_object_dialog.h"
 #include "export_pdu_dialog.h"
-#if HAVE_EXTCAP
 #include "extcap_options_dialog.h"
-#endif
+#include "file_set_dialog.h"
 #include "filter_action.h"
 #include "filter_dialog.h"
+#include "firewall_rules_dialog.h"
 #include "funnel_statistics.h"
 #include "gsm_map_summary_dialog.h"
 #include "iax2_analysis_dialog.h"
+#include "interface_toolbar.h"
 #include "io_graph_dialog.h"
+#include <ui/qt/widgets/additional_toolbar.h>
 #include "lbm_stream_dialog.h"
-#include "lbm_uimflow_dialog.h"
 #include "lbm_lbtrm_transport_dialog.h"
 #include "lbm_lbtru_transport_dialog.h"
 #include "lte_mac_statistics_dialog.h"
 #include "print_dialog.h"
 #include "profile_dialog.h"
 #include "protocol_hierarchy_dialog.h"
-#include "qt_ui_utils.h"
+#include <ui/qt/utils/qt_ui_utils.h>
 #include "resolved_addresses_dialog.h"
 #include "rpc_service_response_time_dialog.h"
 #include "rtp_stream_dialog.h"
 #include "sctp_assoc_analyse_dialog.h"
 #include "sctp_graph_dialog.h"
 #include "sequence_dialog.h"
+#include "show_packet_bytes_dialog.h"
 #include "stats_tree_dialog.h"
-#include "stock_icon.h"
+#include <ui/qt/utils/stock_icon.h>
 #include "supported_protocols_dialog.h"
 #include "tap_parameter_dialog.h"
 #include "tcp_stream_dialog.h"
 #include "voip_calls_dialog.h"
 #include "wireshark_application.h"
 #include "wlan_statistics_dialog.h"
+#include "wireless_timeline.h"
 
 #include <QClipboard>
 #include <QFileInfo>
 #include <QToolBar>
 #include <QDesktopServices>
 #include <QUrl>
-#include <QDebug>
+
+// XXX You must uncomment QT_WINEXTRAS_LIB lines in CMakeList.txt and
+// cmakeconfig.h.in.
+// #if defined(QT_WINEXTRAS_LIB)
+// #include <QWinJumpList>
+// #include <QWinJumpListCategory>
+// #include <QWinJumpListItem>
+// #endif
 
 //
 // Public slots
 //
 
 static const char *dfe_property_ = "display filter expression"; //TODO : Fix Translate
+static const char *dfe_property_label_ = "display_filter_expression_label";
+static const char *dfe_property_expression_ = "display_filter_expression_expr";
 
-// We're too lazy to sublcass QAction.
-static const char *color_number_property_ = "color number";
-
-bool MainWindow::openCaptureFile(QString cf_path, QString read_filter, unsigned int type)
+bool MainWindow::openCaptureFile(QString cf_path, QString read_filter, unsigned int type, gboolean is_tempfile)
 {
     QString file_name = "";
     dfilter_t *rfcode = NULL;
     gchar *err_msg;
     int err;
     gboolean name_param;
+    gboolean ret = true;
 
     // was a file name given as function parameter?
     name_param = !cf_path.isEmpty();
@@ -175,38 +196,21 @@ bool MainWindow::openCaptureFile(QString cf_path, QString read_filter, unsigned
         if (cf_path.isEmpty()) {
             CaptureFileDialog open_dlg(this, capture_file_.capFile(), read_filter);
 
-            switch (prefs.gui_fileopen_style) {
-
-            case FO_STYLE_LAST_OPENED:
-                /* The user has specified that we should start out in the last directory
-                   we looked in.  If we've already opened a file, use its containing
-                   directory, if we could determine it, as the directory, otherwise
-                   use the "last opened" directory saved in the preferences file if
-                   there was one. */
-                /* This is now the default behaviour in file_selection_new() */
-                break;
-
-            case FO_STYLE_SPECIFIED:
-                /* The user has specified that we should always start out in a
-                   specified directory; if they've specified that directory,
-                   start out by showing the files in that dir. */
-                if (prefs.gui_fileopen_dir[0] != '\0')
-                    open_dlg.setDirectory(prefs.gui_fileopen_dir);
-                break;
-            }
-
             if (open_dlg.open(file_name, type)) {
                 cf_path = file_name;
             } else {
-                return false;
+                ret = false;
+                goto finish;
             }
         }
 
-        if (!testCaptureFileClose(false)) {
-            return false;
+        QString before_what(tr(" before opening another file"));
+        if (!testCaptureFileClose(before_what)) {
+            ret = false;
+            goto finish;
         }
 
-        if (dfilter_compile(read_filter.toUtf8().constData(), &rfcode, &err_msg)) {
+        if (dfilter_compile(qUtf8Printable(read_filter), &rfcode, &err_msg)) {
             cf_set_rfcode(CaptureFile::globalCapFile(), rfcode);
         } else {
             /* Not valid.  Tell the user, and go back and run the file
@@ -227,16 +231,18 @@ bool MainWindow::openCaptureFile(QString cf_path, QString read_filter, unsigned
             }
         }
 
+        /* Make the file name available via MainWindow */
+        setMwFileName(cf_path);
+
         /* Try to open the capture file. This closes the current file if it succeeds. */
         CaptureFile::globalCapFile()->window = this;
-        if (cf_open(CaptureFile::globalCapFile(), cf_path.toUtf8().constData(), type, FALSE, &err) != CF_OK) {
+        if (cf_open(CaptureFile::globalCapFile(), qUtf8Printable(cf_path), type, is_tempfile, &err) != CF_OK) {
             /* We couldn't open it; don't dismiss the open dialog box,
                just leave it around so that the user can, after they
                dismiss the alert box popped up for the open error,
                try again. */
             CaptureFile::globalCapFile()->window = NULL;
-            if (rfcode != NULL)
-                dfilter_free(rfcode);
+            dfilter_free(rfcode);
             cf_path.clear();
             continue;
         }
@@ -256,16 +262,22 @@ bool MainWindow::openCaptureFile(QString cf_path, QString read_filter, unsigned
                string and return (without changing the last containing
                directory). */
             capture_file_.setCapFile(NULL);
-            return false;
+            ret = false;
+            goto finish;
         }
         break;
     }
-    // get_dirname overwrites its path. Hopefully this isn't a problem.
+    // get_dirname overwrites its path.
     wsApp->setLastOpenDir(get_dirname(cf_path.toUtf8().data()));
 
     main_ui_->statusBar->showExpert();
 
-    return true;
+finish:
+#ifdef HAVE_LIBPCAP
+    if (global_commandline_info.quit_after_cap)
+        exit(0);
+#endif
+    return ret;
 }
 
 void MainWindow::filterPackets(QString new_filter, bool force)
@@ -290,6 +302,9 @@ void MainWindow::filterPackets(QString new_filter, bool force)
     } else {
         emit displayFilterSuccess(false);
     }
+    if (packet_list_) {
+        packet_list_->resetColumns();
+    }
 }
 
 // A new layout should be applied when it differs from the old layout AND
@@ -302,11 +317,14 @@ void MainWindow::layoutPanes()
     QVector<unsigned> new_layout = QVector<unsigned>() << prefs.gui_layout_type
                                                        << prefs.gui_layout_content_1
                                                        << prefs.gui_layout_content_2
-                                                       << prefs.gui_layout_content_3;
+                                                       << prefs.gui_layout_content_3
+                                                       << recent.packet_list_show
+                                                       << recent.tree_view_show
+                                                       << recent.byte_view_show;
+
     if (cur_layout_ == new_layout) return;
 
     QSplitter *parents[3];
-    int current_row = capture_file_.currentRow();
 
     // Reparent all widgets and add them back in the proper order below.
     // This hides each widget as well.
@@ -383,8 +401,7 @@ void MainWindow::layoutPanes()
     proto_tree_->setVisible(ms_children.contains(proto_tree_) && recent.tree_view_show);
     byte_view_tab_->setVisible(ms_children.contains(byte_view_tab_) && recent.byte_view_show);
 
-    packet_list_->thaw();
-    cf_select_packet(capture_file_.capFile(), current_row);  // XXX Doesn't work for row 0?
+    packet_list_->thaw(true);
     cur_layout_ = new_layout;
 }
 
@@ -406,26 +423,41 @@ void MainWindow::applyRecentPaneGeometry()
     // Force a geometry recalculation
     QWidget *cur_w = main_ui_->mainStack->currentWidget();
     main_ui_->mainStack->setCurrentWidget(&master_split_);
-    QRect geom = master_split_.geometry();
+    QRect geom = main_ui_->mainStack->geometry();
     QList<int> master_sizes = master_split_.sizes();
     QList<int> extra_sizes = extra_split_.sizes();
     main_ui_->mainStack->setCurrentWidget(cur_w);
 
     int master_last_size = master_split_.orientation() == Qt::Vertical ? geom.height() : geom.width();
+    master_last_size -= master_split_.handleWidth() * (master_sizes.length() - 1);
+
     int extra_last_size = extra_split_.orientation() == Qt::Vertical ? geom.height() : geom.width();
+    extra_last_size -= extra_split_.handleWidth();
 
     if (recent.gui_geometry_main_upper_pane > 0) {
-        master_sizes[0] = recent.gui_geometry_main_upper_pane + 1; // Add back mystery pixel
-        master_last_size -= recent.gui_geometry_main_upper_pane + master_split_.handleWidth();
+        master_sizes[0] = recent.gui_geometry_main_upper_pane;
+        master_last_size -= recent.gui_geometry_main_upper_pane;
+    } else {
+        master_sizes[0] = master_last_size / master_sizes.length();
+        master_last_size -= master_last_size / master_sizes.length();
     }
 
     if (recent.gui_geometry_main_lower_pane > 0) {
         if (master_sizes.length() > 2) {
-            master_sizes[1] = recent.gui_geometry_main_lower_pane + 1; // Add back mystery pixel
-            master_last_size -= recent.gui_geometry_main_lower_pane + master_split_.handleWidth();
+            master_sizes[1] = recent.gui_geometry_main_lower_pane;
+            master_last_size -= recent.gui_geometry_main_lower_pane;
         } else if (extra_sizes.length() > 0) {
-            extra_sizes[0] = recent.gui_geometry_main_lower_pane; // No mystery pixel
-            extra_last_size -= recent.gui_geometry_main_lower_pane + extra_split_.handleWidth();
+            extra_sizes[0] = recent.gui_geometry_main_lower_pane;
+            extra_last_size -= recent.gui_geometry_main_lower_pane;
+            extra_sizes.last() = extra_last_size;
+        }
+    } else {
+        if (master_sizes.length() > 2) {
+            master_sizes[1] = master_last_size / 2;
+            master_last_size -= master_last_size / 2;
+        } else {
+            extra_sizes[0] = extra_last_size / 2;
+            extra_last_size -= extra_last_size / 2;
             extra_sizes.last() = extra_last_size;
         }
     }
@@ -449,10 +481,41 @@ void MainWindow::layoutToolbars()
     }
 
     main_ui_->mainToolBar->setToolButtonStyle(tbstyle);
+
+    main_ui_->mainToolBar->setVisible(recent.main_toolbar_show);
+    main_ui_->displayFilterToolBar->setVisible(recent.filter_toolbar_show);
+    main_ui_->wirelessToolBar->setVisible(recent.wireless_toolbar_show);
+    main_ui_->statusBar->setVisible(recent.statusbar_show);
+
+    foreach (QAction *action, main_ui_->menuInterfaceToolbars->actions()) {
+        QToolBar *toolbar = action->data().value<QToolBar *>();
+        if (g_list_find_custom(recent.interface_toolbars, action->text().toUtf8(), (GCompareFunc) strcmp)) {
+            toolbar->setVisible(true);
+        } else {
+            toolbar->setVisible(false);
+        }
+    }
+
+    QList<QToolBar *> toolbars = findChildren<QToolBar *>();
+    foreach (QToolBar *bar, toolbars) {
+        AdditionalToolBar *iftoolbar = dynamic_cast<AdditionalToolBar *>(bar);
+        if (iftoolbar) {
+            bool visible = false;
+            if (g_list_find_custom(recent.gui_additional_toolbars, qUtf8Printable(iftoolbar->menuName()), (GCompareFunc) strcmp))
+                visible = true;
+
+            iftoolbar->setVisible(visible);
+
+        }
+    }
 }
 
 void MainWindow::updatePreferenceActions()
 {
+    main_ui_->actionViewPacketList->setEnabled(prefs_has_layout_pane_content(layout_pane_content_plist));
+    main_ui_->actionViewPacketDetails->setEnabled(prefs_has_layout_pane_content(layout_pane_content_pdetails));
+    main_ui_->actionViewPacketBytes->setEnabled(prefs_has_layout_pane_content(layout_pane_content_pbytes));
+
     main_ui_->actionViewNameResolutionPhysical->setChecked(gbl_resolv_flags.mac_name);
     main_ui_->actionViewNameResolutionNetwork->setChecked(gbl_resolv_flags.network_name);
     main_ui_->actionViewNameResolutionTransport->setChecked(gbl_resolv_flags.transport_name);
@@ -461,7 +524,51 @@ void MainWindow::updatePreferenceActions()
     main_ui_->actionGoAutoScroll->setChecked(prefs.capture_auto_scroll);
 }
 
-void MainWindow::filterAction(QString &action_filter, FilterAction::Action action, FilterAction::ActionType type)
+void MainWindow::updateRecentActions()
+{
+    main_ui_->actionViewMainToolbar->setChecked(recent.main_toolbar_show);
+    main_ui_->actionViewFilterToolbar->setChecked(recent.filter_toolbar_show);
+    main_ui_->actionViewWirelessToolbar->setChecked(recent.wireless_toolbar_show);
+    main_ui_->actionViewStatusBar->setChecked(recent.statusbar_show);
+    main_ui_->actionViewPacketList->setChecked(recent.packet_list_show && prefs_has_layout_pane_content(layout_pane_content_plist));
+    main_ui_->actionViewPacketDetails->setChecked(recent.tree_view_show && prefs_has_layout_pane_content(layout_pane_content_pdetails));
+    main_ui_->actionViewPacketBytes->setChecked(recent.byte_view_show && prefs_has_layout_pane_content(layout_pane_content_pbytes));
+
+    foreach (QAction *action, main_ui_->menuInterfaceToolbars->actions()) {
+        if (g_list_find_custom(recent.interface_toolbars, action->text().toUtf8(), (GCompareFunc) strcmp)) {
+            action->setChecked(true);
+        } else {
+            action->setChecked(false);
+        }
+    }
+
+    foreach (QAction * action, main_ui_->menuAdditionalToolbars->actions()) {
+        ext_toolbar_t * toolbar = VariantPointer<ext_toolbar_t>::asPtr(action->data());
+        bool checked = false;
+        if (toolbar && g_list_find_custom(recent.gui_additional_toolbars, toolbar->name, (GCompareFunc) strcmp))
+            checked = true;
+
+        action->setChecked(checked);
+    }
+
+    foreach (QAction* tda, td_actions.keys()) {
+        if (recent.gui_time_format == td_actions[tda]) {
+            tda->setChecked(true);
+        }
+    }
+    foreach (QAction* tpa, tp_actions.keys()) {
+        if (recent.gui_time_precision == tp_actions[tpa]) {
+            tpa->setChecked(true);
+            break;
+        }
+    }
+    main_ui_->actionViewTimeDisplaySecondsWithHoursAndMinutes->setChecked(recent.gui_seconds_format == TS_SECONDS_HOUR_MIN_SEC);
+
+    main_ui_->actionViewColorizePacketList->setChecked(recent.packet_list_colorize);
+}
+
+// Don't connect to this directly. Connect to or emit fiterAction(...) instead.
+void MainWindow::queuedFilterAction(QString action_filter, FilterAction::Action action, FilterAction::ActionType type)
 {
     QString cur_filter, new_filter;
 
@@ -513,6 +620,15 @@ void MainWindow::filterAction(QString &action_filter, FilterAction::Action actio
         df_combo_box_->lineEdit()->setText(new_filter);
         df_combo_box_->applyDisplayFilter();
         break;
+    case FilterAction::ActionColorize:
+        colorizeWithFilter(new_filter.toUtf8());
+        break;
+    case FilterAction::ActionCopy:
+        wsApp->clipboard()->setText(new_filter);
+        break;
+    case FilterAction::ActionFind:
+        main_ui_->searchFrame->findFrameWithFilter(new_filter);
+        break;
     case FilterAction::ActionPrepare:
         df_combo_box_->lineEdit()->setText(new_filter);
         df_combo_box_->lineEdit()->setFocus();
@@ -523,11 +639,8 @@ void MainWindow::filterAction(QString &action_filter, FilterAction::Action actio
         QDesktopServices::openUrl(QUrl(url));
         break;
     }
-    case FilterAction::ActionCopy:
-        wsApp->clipboard()->setText(new_filter);
-        break;
     default:
-        qDebug() << "FIX FilterAction::Action" << action << "not implemented";
+        g_assert_not_reached();
         break;
     }
 }
@@ -551,16 +664,18 @@ void MainWindow::captureCapturePrepared(capture_session *) {
 #endif // HAVE_LIBPCAP
 }
 
-void MainWindow::captureCaptureUpdateStarted(capture_session *) {
+void MainWindow::captureCaptureUpdateStarted(capture_session *session) {
 #ifdef HAVE_LIBPCAP
 
     /* We've done this in "prepared" above, but it will be cleared while
        switching to the next multiple file. */
     setTitlebarForCaptureInProgress();
 
-    setForCaptureInProgress(true);
+    setForCaptureInProgress(true, session->capture_opts->ifaces);
 
     setForCapturedPackets(true);
+#else
+    Q_UNUSED(session)
 #endif // HAVE_LIBPCAP
 }
 void MainWindow::captureCaptureUpdateFinished(capture_session *) {
@@ -575,20 +690,18 @@ void MainWindow::captureCaptureUpdateFinished(capture_session *) {
     /* Enable menu items that make sense if you're not currently running
      a capture. */
     setForCaptureInProgress(false);
+    setMenusForCaptureFile();
 
     setWindowIcon(wsApp->normalIcon());
 
-    if (global_capture_opts.quit_after_cap) {
+    if (global_commandline_info.quit_after_cap) {
         // Command line asked us to quit after capturing.
         // Don't pop up a dialog to ask for unsaved files etc.
         exit(0);
     }
 #endif // HAVE_LIBPCAP
 }
-void MainWindow::captureCaptureFixedStarted(capture_session *) {
-#ifdef HAVE_LIBPCAP
-#endif // HAVE_LIBPCAP
-}
+
 void MainWindow::captureCaptureFixedFinished(capture_session *) {
 #ifdef HAVE_LIBPCAP
 
@@ -598,23 +711,21 @@ void MainWindow::captureCaptureFixedFinished(capture_session *) {
     /* Enable menu items that make sense if you're not currently running
      a capture. */
     setForCaptureInProgress(false);
+    /* There isn't a real capture_file structure yet, so just force disabling
+       menu options.  They will "refresh" when the capture file is reloaded to
+       display packets */
+    setMenusForCaptureFile(true);
 
     setWindowIcon(wsApp->normalIcon());
 
-    if (global_capture_opts.quit_after_cap) {
+    if (global_commandline_info.quit_after_cap) {
         // Command line asked us to quit after capturing.
         // Don't pop up a dialog to ask for unsaved files etc.
         exit(0);
     }
 #endif // HAVE_LIBPCAP
 }
-void MainWindow::captureCaptureStopping(capture_session *) {
-#ifdef HAVE_LIBPCAP
 
-    capture_stopping_ = true;
-    setMenusForCaptureStopping();
-#endif // HAVE_LIBPCAP
-}
 void MainWindow::captureCaptureFailed(capture_session *) {
 #ifdef HAVE_LIBPCAP
     /* Capture isn't stopping any more. */
@@ -623,9 +734,13 @@ void MainWindow::captureCaptureFailed(capture_session *) {
     setForCaptureInProgress(false);
     main_ui_->mainStack->setCurrentWidget(main_welcome_);
 
+    // Reset expert information indicator
+    main_ui_->statusBar->captureFileClosing();
+    main_ui_->statusBar->popFileStatus();
+
     setWindowIcon(wsApp->normalIcon());
 
-    if (global_capture_opts.quit_after_cap) {
+    if (global_commandline_info.quit_after_cap) {
         // Command line asked us to quit after capturing.
         // Don't pop up a dialog to ask for unsaved files etc.
         exit(0);
@@ -633,13 +748,152 @@ void MainWindow::captureCaptureFailed(capture_session *) {
 #endif // HAVE_LIBPCAP
 }
 
-
 // Callbacks from cfile.c and file.c via CaptureFile::captureFileCallback
 
+void MainWindow::captureEventHandler(CaptureEvent ev)
+{
+    switch (ev.captureContext()) {
+
+    case CaptureEvent::File:
+        switch (ev.eventType()) {
+        case CaptureEvent::Opened:
+            captureFileOpened();
+            break;
+        case CaptureEvent::Closing:
+            captureFileClosing();
+            break;
+        case CaptureEvent::Closed:
+            captureFileClosed();
+            break;
+        case CaptureEvent::Started:
+            captureFileReadStarted(tr("Loading"));
+            break;
+        case CaptureEvent::Finished:
+            captureFileReadFinished();
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case CaptureEvent::Reload:
+        switch (ev.eventType()) {
+        case CaptureEvent::Started:
+            captureFileReadStarted(tr("Reloading"));
+            break;
+        case CaptureEvent::Finished:
+            captureFileReadFinished();
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case CaptureEvent::Rescan:
+        switch (ev.eventType()) {
+        case CaptureEvent::Started:
+            setMenusForCaptureFile(true);
+            captureFileReadStarted(tr("Rescanning"));
+            break;
+        case CaptureEvent::Finished:
+            captureFileReadFinished();
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case CaptureEvent::Retap:
+        switch (ev.eventType()) {
+        case CaptureEvent::Started:
+            freeze();
+            break;
+        case CaptureEvent::Finished:
+            thaw();
+            break;
+        case CaptureEvent::Flushed:
+            draw_tap_listeners(FALSE);
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case CaptureEvent::Merge:
+        switch (ev.eventType()) {
+        case CaptureEvent::Started:
+            main_ui_->statusBar->popFileStatus();
+            main_ui_->statusBar->pushFileStatus(tr("Merging files"), QString());
+            break;
+        case CaptureEvent::Finished:
+            main_ui_->statusBar->popFileStatus();
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case CaptureEvent::Save:
+        switch (ev.eventType()) {
+        case CaptureEvent::Started:
+        {
+            QFileInfo file_info(ev.filePath());
+            main_ui_->statusBar->popFileStatus();
+            main_ui_->statusBar->pushFileStatus(tr("Saving %1" UTF8_HORIZONTAL_ELLIPSIS).arg(file_info.baseName()));
+            break;
+        }
+        default:
+            break;
+        }
+        break;
+
+#ifdef HAVE_LIBPCAP
+    case CaptureEvent::Capture:
+        switch (ev.eventType()) {
+        case CaptureEvent::Prepared:
+            captureCapturePrepared(ev.capSession());
+            break;
+        case CaptureEvent::Stopping:
+            capture_stopping_ = true;
+            setMenusForCaptureStopping();
+            break;
+        case CaptureEvent::Failed:
+            captureCaptureFailed(ev.capSession());
+        default:
+            break;
+        }
+        break;
+
+    case CaptureEvent::Update:
+        switch (ev.eventType()) {
+        case CaptureEvent::Started:
+            captureCaptureUpdateStarted(ev.capSession());
+            break;
+        case CaptureEvent::Finished:
+            captureCaptureUpdateFinished(ev.capSession());
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case CaptureEvent::Fixed:
+        switch (ev.eventType()) {
+        case CaptureEvent::Finished:
+            captureCaptureFixedFinished(ev.capSession());
+            break;
+        default:
+            break;
+        }
+        break;
+#endif
+    }
+}
+
 void MainWindow::captureFileOpened() {
     if (capture_file_.window() != this) return;
 
-    file_set_dialog_.fileOpened(capture_file_.capFile());
+    file_set_dialog_->fileOpened(capture_file_.capFile());
     setMenusForFileSet(true);
     emit setCaptureFile(capture_file_.capFile());
 }
@@ -655,6 +909,9 @@ void MainWindow::captureFileReadStarted(const QString &action) {
     QString msgtip = QString();
     main_ui_->statusBar->pushFileStatus(msg, msgtip);
     main_ui_->mainStack->setCurrentWidget(&master_split_);
+    main_ui_->actionAnalyzeReloadLuaPlugins->setEnabled(false);
+    main_ui_->wirelessTimelineWidget->captureFileReadStarted(capture_file_.capFile());
+
     WiresharkApplication::processEvents();
 }
 
@@ -666,44 +923,37 @@ void MainWindow::captureFileReadFinished() {
         add_menu_recent_capture_file(capture_file_.capFile()->filename);
 
         /* Remember folder for next Open dialog and save it in recent */
-        dir_path = get_dirname(g_strdup(capture_file_.capFile()->filename));
-        wsApp->setLastOpenDir(dir_path);
+        dir_path = g_strdup(capture_file_.capFile()->filename);
+        wsApp->setLastOpenDir(get_dirname(dir_path));
         g_free(dir_path);
     }
 
     /* Update the appropriate parts of the main window. */
     updateForUnsavedChanges();
 
+    /* enable wireless timeline if capture allows it */
+    main_ui_->wirelessTimelineWidget->captureFileReadFinished();
+
     /* Enable menu items that make sense if you have some captured packets. */
     setForCapturedPackets(true);
 
     main_ui_->statusBar->setFileName(capture_file_);
+    main_ui_->actionAnalyzeReloadLuaPlugins->setEnabled(true);
 
     packet_list_->captureFileReadFinished();
 
     emit setDissectedCaptureFile(capture_file_.capFile());
 }
 
-void MainWindow::captureFileRetapStarted()
-{
-    // XXX Push a status message?
-    freeze();
-}
-
-void MainWindow::captureFileRetapFinished()
-{
-    thaw();
-}
-
 void MainWindow::captureFileClosing() {
     setMenusForCaptureFile(true);
     setForCapturedPackets(false);
-    setMenusForSelectedPacket();
     setForCaptureInProgress(false);
 
     // Reset expert information indicator
     main_ui_->statusBar->captureFileClosing();
     main_ui_->searchFrame->animatedHide();
+    main_ui_->goToFrame->animatedHide();
 //    gtk_widget_show(expert_info_none);
     emit setCaptureFile(NULL);
     emit setDissectedCaptureFile(NULL);
@@ -712,50 +962,83 @@ void MainWindow::captureFileClosing() {
 void MainWindow::captureFileClosed() {
     packets_bar_update();
 
-    file_set_dialog_.fileClosed();
+    file_set_dialog_->fileClosed();
     setMenusForFileSet(false);
     setWindowModified(false);
 
     // Reset expert information indicator
     main_ui_->statusBar->captureFileClosing();
-
     main_ui_->statusBar->popFileStatus();
 
-    setTitlebarForSelectedTreeRow();
+    setWSWindowTitle();
+    setWindowIcon(wsApp->normalIcon());
+    setMenusForSelectedPacket();
     setMenusForSelectedTreeRow();
 
+#ifdef HAVE_LIBPCAP
     if (!global_capture_opts.multi_files_on)
         main_ui_->mainStack->setCurrentWidget(main_welcome_);
+#endif
 }
 
-void MainWindow::captureFileSaveStarted(const QString &file_path)
+struct filter_expression_data
 {
-    QFileInfo file_info(file_path);
-    main_ui_->statusBar->popFileStatus();
-    main_ui_->statusBar->pushFileStatus(tr("Saving %1" UTF8_HORIZONTAL_ELLIPSIS).arg(file_info.baseName()));
+    MainWindow* window;
+    bool actions_added;
+};
+
+gboolean MainWindow::filter_expression_add_action(const void *key _U_, void *value, void *user_data)
+{
+    filter_expression_t* fe = (filter_expression_t*)value;
+    struct filter_expression_data* data = (filter_expression_data*)user_data;
+
+    if (!fe->enabled)
+        return FALSE;
+
+    QAction *dfb_action = new QAction(fe->label, data->window->filter_expression_toolbar_);
+    if (strlen(fe->comment) > 0)
+    {
+        QString tooltip = QString("%1\n%2").arg(fe->comment).arg(fe->expression);
+        dfb_action->setToolTip(tooltip);
+    }
+    else
+    {
+        dfb_action->setToolTip(fe->expression);
+    }
+    dfb_action->setData(fe->expression);
+    dfb_action->setProperty(dfe_property_, true);
+    dfb_action->setProperty(dfe_property_label_, QString(fe->label));
+    dfb_action->setProperty(dfe_property_expression_, QString(fe->expression));
+
+    if (data->actions_added) {
+        QFrame *sep = new QFrame();
+        sep->setEnabled(false);
+        data->window->filter_expression_toolbar_->addWidget(sep);
+    }
+    data->window->filter_expression_toolbar_->addAction(dfb_action);
+    connect(dfb_action, SIGNAL(triggered()), data->window, SLOT(displayFilterButtonClicked()));
+    data->actions_added = true;
+    return FALSE;
 }
 
 void MainWindow::filterExpressionsChanged()
 {
-    // Recreate filter buttons
-    foreach (QAction *act, main_ui_->displayFilterToolBar->actions()) {
-        // Permanent actions shouldn't have data
-        if (act->property(dfe_property_).isValid()) {
-            main_ui_->displayFilterToolBar->removeAction(act);
-            delete act;
-        }
-    }
+    struct filter_expression_data data;
+
+    data.window = this;
+    data.actions_added = false;
+
+    // Hiding and showing seems to be the only way to get the layout to
+    // work correctly in some cases. See bug 14121 for details.
+    setUpdatesEnabled(false);
+    filter_expression_toolbar_->hide();
+    filter_expression_toolbar_->clear();
 
     // XXX Add a context menu for removing and changing buttons.
-    for (struct filter_expression *fe = *pfilter_expression_head; fe != NULL; fe = fe->next) {
-        if (!fe->enabled) continue;
-        QAction *dfb_action = new QAction(fe->label, main_ui_->displayFilterToolBar);
-        dfb_action->setToolTip(fe->expression);
-        dfb_action->setData(fe->expression);
-        dfb_action->setProperty(dfe_property_, true);
-        main_ui_->displayFilterToolBar->addAction(dfb_action);
-        connect(dfb_action, SIGNAL(triggered()), this, SLOT(displayFilterButtonClicked()));
-    }
+    filter_expression_iterate_expressions(filter_expression_add_action, &data);
+
+    filter_expression_toolbar_->show();
+    setUpdatesEnabled(true);
 }
 
 //
@@ -766,7 +1049,7 @@ void MainWindow::filterExpressionsChanged()
 
 void MainWindow::startCapture() {
 #ifdef HAVE_LIBPCAP
-    interface_options interface_opts;
+    interface_options *interface_opts;
     guint i;
 
     /* did the user ever select a capture interface before? */
@@ -777,8 +1060,6 @@ void MainWindow::startCapture() {
         return;
     }
 
-    main_ui_->mainStack->setCurrentWidget(&master_split_);
-
     // Ideally we should have disabled the start capture
     // toolbar buttons and menu items. This may not be the
     // case, e.g. with QtMacExtras.
@@ -789,6 +1070,8 @@ void MainWindow::startCapture() {
         return;
     }
 
+    main_ui_->mainStack->setCurrentWidget(&master_split_);
+
     /* XXX - we might need to init other pref data as well... */
 
     /* XXX - can this ever happen? */
@@ -803,13 +1086,11 @@ void MainWindow::startCapture() {
     collect_ifaces(&global_capture_opts);
 
     CaptureFile::globalCapFile()->window = this;
-    if (capture_start(&global_capture_opts, &cap_session_, main_window_update)) {
+    info_data_.ui.ui = this;
+    if (capture_start(&global_capture_opts, &cap_session_, &info_data_, main_window_update)) {
         capture_options *capture_opts = cap_session_.capture_opts;
         GString *interface_names;
 
-        /* enable autoscroll timer as needed. */
-        packet_list_->setAutoScroll(main_ui_->actionGoAutoScroll->isChecked());
-
         /* Add "interface name<live capture in progress>" on main status bar */
         interface_names = get_iface_list_string(capture_opts, 0);
         if (strlen (interface_names->str) > 0) {
@@ -825,12 +1106,28 @@ void MainWindow::startCapture() {
 
         /* The capture succeeded, which means the capture filter syntax is
          valid; add this capture filter to the recent capture filter list. */
+        QByteArray filter_ba;
         for (i = 0; i < global_capture_opts.ifaces->len; i++) {
-            interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
-            if (interface_opts.cfilter) {
-//              cfilter_combo_add_recent(interface_opts.cfilter);
+            interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i);
+            if (interface_opts->cfilter) {
+                recent_add_cfilter(interface_opts->name, interface_opts->cfilter);
+                if (filter_ba.isEmpty()) {
+                    filter_ba = interface_opts->cfilter;
+                } else {
+                    /* Not the first selected interface; is its capture filter
+                       the same as the one the other interfaces we've looked
+                       at have? */
+                    if (strcmp(interface_opts->cfilter, filter_ba.constData()) != 0) {
+                      /* No, so not all selected interfaces have the same capture
+                         filter. */
+                        filter_ba.clear();
+                    }
+                }
             }
         }
+        if (!filter_ba.isEmpty()) {
+            recent_add_cfilter(NULL, filter_ba.constData());
+        }
     } else {
         CaptureFile::globalCapFile()->window = NULL;
     }
@@ -888,7 +1185,7 @@ void MainWindow::pipeTimeout() {
 
 void MainWindow::pipeActivated(int source) {
 #ifdef _WIN32
-    Q_UNUSED(source);
+    Q_UNUSED(source)
 #else
     g_assert(source == pipe_source_);
 
@@ -901,7 +1198,11 @@ void MainWindow::pipeActivated(int source) {
 #endif // _WIN32
 }
 
-void MainWindow::pipeNotifierDestroyed() {
+void MainWindow::pipeNotifierDestroyed()
+{
+    /* Pop the "<live capture in progress>" message off the status bar. */
+    main_ui_->statusBar->setFileName(capture_file_);
+
 #ifdef _WIN32
     pipe_timer_ = NULL;
 #else
@@ -919,15 +1220,10 @@ void MainWindow::stopCapture() {
     capture_stop(&cap_session_);
 #endif // HAVE_LIBPCAP
 
-    /* Pop the "<live capture in progress>" message off the status bar. */
-    main_ui_->statusBar->setFileName(capture_file_);
-
-    /* disable autoscroll timer if any. */
-    packet_list_->setAutoScroll(false);
 }
 
 // Keep focus rects from showing through the welcome screen. Primarily for
-// OS X.
+// macOS.
 void MainWindow::mainStackChanged(int)
 {
     for (int i = 0; i < main_ui_->mainStack->count(); i++) {
@@ -941,7 +1237,7 @@ void MainWindow::mainStackChanged(int)
  * Add the capture filename (with an absolute path) to the "Recent Files" menu.
  */
 // XXX - We should probably create a RecentFile class.
-void MainWindow::updateRecentFiles() {
+void MainWindow::updateRecentCaptures() {
     QAction *ra;
     QMenu *recentMenu = main_ui_->menuOpenRecentCaptureFile;
     QString action_cf_name;
@@ -949,9 +1245,26 @@ void MainWindow::updateRecentFiles() {
     if (!recentMenu) {
         return;
     }
-
     recentMenu->clear();
 
+#if 0
+#if defined(QT_WINEXTRAS_LIB)
+     QWinJumpList recent_jl(this);
+     QWinJumpListCategory *recent_jlc = recent_jl.recent();
+     if (recent_jlc) {
+         recent_jlc->clear();
+         recent_jlc->setVisible(true);
+     }
+#endif
+#endif
+#if defined(Q_OS_MAC)
+    if (!dock_menu_) {
+        dock_menu_ = new QMenu();
+        dock_menu_->setAsDockMenu();
+    }
+    dock_menu_->clear();
+#endif
+
     /* Iterate through the actions in menuOpenRecentCaptureFile,
      * removing special items, a maybe duplicate entry and every item above count_max */
     int shortcut = Qt::Key_0;
@@ -969,6 +1282,31 @@ void MainWindow::updateRecentFiles() {
         }
         ra->setText(action_cf_name);
         connect(ra, SIGNAL(triggered()), this, SLOT(recentActionTriggered()));
+
+/* This is slow, at least on my VM here. The added links also open Wireshark
+ * in a new window. It might make more sense to add a recent item when we
+ * open a capture file. */
+#if 0
+#if defined(QT_WINEXTRAS_LIB)
+     if (recent_jlc) {
+         QFileInfo fi(ri->filename);
+         QWinJumpListItem *jli = recent_jlc->addLink(
+             fi.fileName(),
+             QApplication::applicationFilePath(),
+             QStringList() << "-r" << ri->filename
+         );
+         // XXX set icon
+         jli->setWorkingDirectory(QDir::toNativeSeparators(QApplication::applicationDirPath()));
+     }
+#endif
+#endif
+#if defined(Q_OS_MAC)
+        QAction *rda = new QAction(dock_menu_);
+        QFileInfo fi(ri->filename);
+        rda->setText(fi.fileName());
+        dock_menu_->insertAction(NULL, rda);
+        connect(rda, SIGNAL(triggered()), ra, SLOT(trigger()));
+#endif
     }
 
     if (recentMenu->actions().count() > 0) {
@@ -981,7 +1319,7 @@ void MainWindow::updateRecentFiles() {
         ra = new QAction(recentMenu);
         ra->setText(tr("Clear Menu"));
         recentMenu->insertAction(NULL, ra);
-        connect(ra, SIGNAL(triggered()), wsApp, SLOT(clearRecentItems()));
+        connect(ra, SIGNAL(triggered()), wsApp, SLOT(clearRecentCaptures()));
     } else {
         if (main_ui_->actionDummyNoFilesFound) {
             recentMenu->addAction(main_ui_->actionDummyNoFilesFound);
@@ -1000,7 +1338,7 @@ void MainWindow::recentActionTriggered() {
 
 void MainWindow::setMenusForSelectedPacket()
 {
-    gboolean is_ip = FALSE, is_tcp = FALSE, is_udp = FALSE, is_sctp = FALSE, is_ssl = FALSE, is_rtp = FALSE, is_lte_rlc = FALSE;
+    gboolean is_ip = FALSE, is_tcp = FALSE, is_udp = FALSE, is_sctp = FALSE, is_ssl = FALSE, is_rtp = FALSE, is_lte_rlc = FALSE, is_http = FALSE;
 
     /* Making the menu context-sensitive allows for easier selection of the
        desired item and has the added benefit, with large captures, of
@@ -1011,6 +1349,10 @@ void MainWindow::setMenusForSelectedPacket()
     bool have_frames = false;
     /* A frame is selected */
     bool frame_selected = false;
+    /* A visible packet comes after this one in the selection history */
+    bool next_selection_history = false;
+    /* A visible packet comes before this one in the selection history */
+    bool previous_selection_history = false;
     /* We have marked frames.  (XXX - why check frame_selected?) */
     bool have_marked = false;
     /* We have a marked frame other than the current frame (i.e.,
@@ -1039,21 +1381,24 @@ void MainWindow::setMenusForSelectedPacket()
 
     if (capture_file_.capFile()) {
         frame_selected = capture_file_.capFile()->current_frame != NULL;
+        next_selection_history = packet_list_->haveNextHistory();
+        previous_selection_history = packet_list_->havePreviousHistory();
         have_frames = capture_file_.capFile()->count > 0;
-        have_marked = frame_selected && capture_file_.capFile()->marked_count > 0;
+        have_marked = capture_file_.capFile()->marked_count > 0;
         another_is_marked = have_marked &&
-                !(capture_file_.capFile()->marked_count == 1 && capture_file_.capFile()->current_frame->flags.marked);
+                !(capture_file_.capFile()->marked_count == 1 && frame_selected && capture_file_.capFile()->current_frame->flags.marked);
         have_filtered = capture_file_.capFile()->displayed_count > 0 && capture_file_.capFile()->displayed_count != capture_file_.capFile()->count;
         have_ignored = capture_file_.capFile()->ignored_count > 0;
         have_time_ref = capture_file_.capFile()->ref_time_count > 0;
-        another_is_time_ref = frame_selected && have_time_ref &&
-                !(capture_file_.capFile()->ref_time_count == 1 && capture_file_.capFile()->current_frame->flags.ref_time);
+        another_is_time_ref = have_time_ref &&
+                !(capture_file_.capFile()->ref_time_count == 1 && frame_selected && capture_file_.capFile()->current_frame->flags.ref_time);
 
         if (capture_file_.capFile()->edt)
         {
             proto_get_frame_protocols(capture_file_.capFile()->edt->pi.layers,
                                       &is_ip, &is_tcp, &is_udp, &is_sctp,
                                       &is_ssl, &is_rtp, &is_lte_rlc);
+            is_http = proto_is_frame_protocol(capture_file_.capFile()->edt->pi.layers, "http");
         }
     }
 
@@ -1066,11 +1411,8 @@ void MainWindow::setMenusForSelectedPacket()
     main_ui_->actionEditNextMark->setEnabled(another_is_marked);
     main_ui_->actionEditPreviousMark->setEnabled(another_is_marked);
 
-#ifdef WANT_PACKET_EDITOR
-//    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/EditPacket",
-//                         frame_selected);
-#endif // WANT_PACKET_EDITOR
     main_ui_->actionEditPacketComment->setEnabled(frame_selected && wtap_dump_can_write(capture_file_.capFile()->linktypes, WTAP_COMMENT_PER_PACKET));
+    main_ui_->actionDeleteAllPacketComments->setEnabled((capture_file_.capFile() != NULL) && wtap_dump_can_write(capture_file_.capFile()->linktypes, WTAP_COMMENT_PER_PACKET));
 
     main_ui_->actionEditIgnorePacket->setEnabled(frame_selected);
     main_ui_->actionEditIgnoreAllDisplayed->setEnabled(have_filtered);
@@ -1084,6 +1426,8 @@ void MainWindow::setMenusForSelectedPacket()
     main_ui_->actionEditTimeShift->setEnabled(have_frames);
 
     main_ui_->actionGoGoToLinkedPacket->setEnabled(false);
+    main_ui_->actionGoNextHistoryPacket->setEnabled(next_selection_history);
+    main_ui_->actionGoPreviousHistoryPacket->setEnabled(previous_selection_history);
 
     main_ui_->actionAnalyzeAAFSelected->setEnabled(have_filter_expr);
     main_ui_->actionAnalyzeAAFNotSelected->setEnabled(have_filter_expr);
@@ -1102,64 +1446,32 @@ void MainWindow::setMenusForSelectedPacket()
     main_ui_->actionAnalyzeFollowTCPStream->setEnabled(is_tcp);
     main_ui_->actionAnalyzeFollowUDPStream->setEnabled(is_udp);
     main_ui_->actionAnalyzeFollowSSLStream->setEnabled(is_ssl);
+    main_ui_->actionAnalyzeFollowHTTPStream->setEnabled(is_http);
 
     foreach (QAction *cc_action, cc_actions) {
         cc_action->setEnabled(frame_selected);
     }
-    main_ui_->actionViewColorizeNewConversationRule->setEnabled(frame_selected);
+    main_ui_->actionViewColorizeNewColoringRule->setEnabled(frame_selected);
 
     main_ui_->actionViewColorizeResetColorization->setEnabled(tmp_color_filters_used());
 
-    main_ui_->actionViewColorizeNewConversationRule->setEnabled(frame_selected);
-
     main_ui_->actionViewShowPacketInNewWindow->setEnabled(frame_selected);
     main_ui_->actionViewEditResolvedName->setEnabled(frame_selected && is_ip);
 
-    main_ui_->menuConversationFilter->clear();
+    emit packetInfoChanged(capture_file_.packetInfo());
 
-    packet_list_->conversationMenu()->clear();
-    packet_list_->colorizeMenu()->clear();
-
-    for (GList *conv_filter_list_entry = conv_filter_list; conv_filter_list_entry; conv_filter_list_entry = g_list_next(conv_filter_list_entry)) {
-        // Main menu items
-        conversation_filter_t* conv_filter = (conversation_filter_t *)conv_filter_list_entry->data;
-        QAction *conv_action = main_ui_->menuConversationFilter->addAction(conv_filter->display_name);
-
-        bool enable = false;
-        QString filter;
-        if (capture_file_.capFile()->edt) {
-            enable = conv_filter->is_filter_valid(&capture_file_.capFile()->edt->pi);
-            filter = gchar_free_to_qstring(conv_filter->build_filter_string(&capture_file_.capFile()->edt->pi));
-        }
-        conv_action->setEnabled(enable);
-        conv_action->setData(filter);
-        connect(conv_action, SIGNAL(triggered()), this, SLOT(applyConversationFilter()));
+//    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/NameResolution/ResolveName",
+//                         frame_selected && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
+//                                            gbl_resolv_flags.transport_name));
 
-        // Packet list context menu items
-        packet_list_->conversationMenu()->addAction(conv_action);
+    main_ui_->actionToolsFirewallAclRules->setEnabled(frame_selected);
 
-        QMenu *submenu = packet_list_->colorizeMenu()->addMenu(conv_action->text());
-        int i = 1;
-        foreach (QAction *cc_action, cc_actions) {
-            QAction *colorize_action = submenu->addAction(cc_action->icon(), cc_action->text());
-            colorize_action->setProperty(color_number_property_, i++);
-            colorize_action->setData(filter);
-            colorize_action->setEnabled(enable);
-            connect(colorize_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
-        }
+    main_ui_->actionStatisticsTcpStreamRoundTripTime->setEnabled(is_tcp);
+    main_ui_->actionStatisticsTcpStreamStevens->setEnabled(is_tcp);
+    main_ui_->actionStatisticsTcpStreamTcptrace->setEnabled(is_tcp);
+    main_ui_->actionStatisticsTcpStreamThroughput->setEnabled(is_tcp);
+    main_ui_->actionStatisticsTcpStreamWindowScaling->setEnabled(is_tcp);
 
-        QAction *conv_rule_action = submenu->addAction(main_ui_->actionViewColorizeNewConversationRule->text());
-        conv_rule_action->setData(conv_action->data());
-        conv_rule_action->setEnabled(enable);
-        connect(conv_rule_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
-    }
-
-//    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/NameResolution/ResolveName",
-//                         frame_selected && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
-//                                            gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns));
-//    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ToolsMenu/FirewallACLRules",
-//                         frame_selected);
-    main_ui_->menuTcpStreamGraphs->setEnabled(is_tcp);
     main_ui_->actionSCTPAnalyseThisAssociation->setEnabled(is_sctp);
     main_ui_->actionSCTPShowAllAssociations->setEnabled(is_sctp);
     main_ui_->actionSCTPFilterThisAssociation->setEnabled(is_sctp);
@@ -1167,22 +1479,20 @@ void MainWindow::setMenusForSelectedPacket()
     main_ui_->actionTelephonyLteRlcGraph->setEnabled(is_lte_rlc);
 }
 
-void MainWindow::setMenusForSelectedTreeRow(field_info *fi) {
+void MainWindow::setMenusForSelectedTreeRow(FieldInformation *finfo) {
 
     bool can_match_selected = false;
     bool is_framenum = false;
     bool have_field_info = false;
     bool have_subtree = false;
     bool can_open_url = false;
-    QString field_filter;
+    bool have_packet_bytes = false;
+    QByteArray field_filter;
     int field_id = -1;
 
-    QList<QAction *> cc_actions = QList<QAction *>()
-            << main_ui_->actionViewColorizeConversation1 << main_ui_->actionViewColorizeConversation2
-            << main_ui_->actionViewColorizeConversation3 << main_ui_->actionViewColorizeConversation4
-            << main_ui_->actionViewColorizeConversation5 << main_ui_->actionViewColorizeConversation6
-            << main_ui_->actionViewColorizeConversation7 << main_ui_->actionViewColorizeConversation8
-            << main_ui_->actionViewColorizeConversation9 << main_ui_->actionViewColorizeConversation10;
+    field_info * fi = 0;
+    if ( finfo )
+        fi = finfo->fieldInfo();
 
     if (capture_file_.capFile()) {
         capture_file_.capFile()->finfo_selected = fi;
@@ -1190,6 +1500,10 @@ void MainWindow::setMenusForSelectedTreeRow(field_info *fi) {
         if (fi && fi->tree_type != -1) {
             have_subtree = true;
         }
+
+        if (fi && fi->ds_tvb) {
+            have_packet_bytes = true;
+        }
     }
 
     if (capture_file_.capFile() != NULL && fi != NULL) {
@@ -1204,7 +1518,7 @@ void MainWindow::setMenusForSelectedTreeRow(field_info *fi) {
         }
 
         char *tmp_field = proto_construct_match_selected_string(fi, capture_file_.capFile()->edt);
-        field_filter = QString(tmp_field);
+        field_filter = tmp_field;
         wmem_free(NULL, tmp_field);
 
         field_id = fi->hfinfo->id;
@@ -1239,7 +1553,11 @@ void MainWindow::setMenusForSelectedTreeRow(field_info *fi) {
     main_ui_->actionEditCopyValue->setEnabled(can_match_selected);
     main_ui_->actionEditCopyAsFilter->setEnabled(can_match_selected);
 
+    main_ui_->actionAnalyzeShowPacketBytes->setEnabled(have_packet_bytes);
+    main_ui_->actionFileExportPacketBytes->setEnabled(have_packet_bytes);
+
     main_ui_->actionViewExpandSubtrees->setEnabled(have_subtree);
+    main_ui_->actionViewCollapseSubtrees->setEnabled(have_subtree);
 
     main_ui_->actionGoGoToLinkedPacket->setEnabled(is_framenum);
 
@@ -1255,41 +1573,12 @@ void MainWindow::setMenusForSelectedTreeRow(field_info *fi) {
     // don't clobber anything we may have set in setMenusForSelectedPacket.
     if (!proto_tree_ || !proto_tree_->hasFocus()) return;
 
-    main_ui_->menuConversationFilter->clear();
-    for (GList *conv_filter_list_entry = conv_filter_list; conv_filter_list_entry; conv_filter_list_entry = g_list_next(conv_filter_list_entry)) {
-        conversation_filter_t* conv_filter = (conversation_filter_t *)conv_filter_list_entry->data;
-        QAction *conv_action = main_ui_->menuConversationFilter->addAction(conv_filter->display_name);
-
-        bool enable = false;
-        QString filter;
-        if (capture_file_.capFile() && capture_file_.capFile()->edt) {
-            enable = conv_filter->is_filter_valid(&capture_file_.capFile()->edt->pi);
-            filter = conv_filter->build_filter_string(&capture_file_.capFile()->edt->pi);
-        }
-        conv_action->setEnabled(enable);
-        conv_action->setData(filter);
-        connect(conv_action, SIGNAL(triggered()), this, SLOT(applyConversationFilter()));
-    }
-
-    proto_tree_->colorizeMenu()->clear();
-    int i = 1;
-    foreach (QAction *cc_action, cc_actions) {
-        QAction *colorize_action = proto_tree_->colorizeMenu()->addAction(cc_action->icon(), cc_action->text());
-        colorize_action->setProperty(color_number_property_, i++);
-        colorize_action->setData(field_filter);
-        colorize_action->setEnabled(!field_filter.isEmpty());
-        connect(colorize_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
-    }
-
-    QAction *conv_rule_action = proto_tree_->colorizeMenu()->addAction(main_ui_->actionViewColorizeNewConversationRule->text());
-    conv_rule_action->setData(field_filter);
-    conv_rule_action->setEnabled(!field_filter.isEmpty());
-    connect(conv_rule_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
+    emit packetInfoChanged(capture_file_.packetInfo());
+    emit fieldFilterChanged(field_filter);
 
 //    set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ResolveName",
 //                         frame_selected && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
-//                                            gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns));
-
+//                                            gbl_resolv_flags.transport_name));
 
     main_ui_->actionAnalyzeAAFSelected->setEnabled(can_match_selected);
     main_ui_->actionAnalyzeAAFNotSelected->setEnabled(can_match_selected);
@@ -1325,30 +1614,60 @@ void MainWindow::captureFilterSyntaxChanged(bool valid)
     interfaceSelectionChanged();
 }
 
-void MainWindow::startInterfaceCapture(bool valid)
+void MainWindow::startInterfaceCapture(bool valid, const QString capture_filter)
 {
     capture_filter_valid_ = valid;
+    main_welcome_->setCaptureFilter(capture_filter);
+    // The interface tree will update the selected interfaces via its timer
+    // so no need to do anything here.
     startCapture();
 }
 
+void MainWindow::applyGlobalCommandLineOptions()
+{
+    if (global_dissect_options.time_format != TS_NOT_SET) {
+        foreach (QAction* tda, td_actions.keys()) {
+            if (global_dissect_options.time_format == td_actions[tda]) {
+                tda->setChecked(true);
+                recent.gui_time_format = global_dissect_options.time_format;
+                timestamp_set_type(global_dissect_options.time_format);
+                break;
+            }
+        }
+    }
+    if (global_commandline_info.full_screen) {
+        this->showFullScreen();
+    }
+}
+
 void MainWindow::redissectPackets()
 {
-    if (capture_file_.capFile())
+    if (capture_file_.capFile()) {
         cf_redissect_packets(capture_file_.capFile());
-    main_ui_->statusBar->expertUpdate();
+        main_ui_->statusBar->expertUpdate();
+    }
 
     proto_free_deregistered_fields();
 }
 
-void MainWindow::fieldsChanged()
+void MainWindow::checkDisplayFilter()
 {
-    color_filters_reload();
-    tap_listeners_dfilter_recompile();
-
     if (!df_combo_box_->checkDisplayFilter()) {
         g_free(CaptureFile::globalCapFile()->dfilter);
         CaptureFile::globalCapFile()->dfilter = NULL;
     }
+}
+
+void MainWindow::fieldsChanged()
+{
+    gchar *err_msg = NULL;
+    if (!color_filters_reload(&err_msg, color_filter_add_cb)) {
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
+        g_free(err_msg);
+    }
+    tap_listeners_dfilter_recompile();
+
+    emit checkDisplayFilter();
 
     if (have_custom_cols(&CaptureFile::globalCapFile()->cinfo)) {
         // Recreate packet list columns according to new/changed/deleted fields
@@ -1358,12 +1677,40 @@ void MainWindow::fieldsChanged()
     emit reloadFields();
 }
 
+void MainWindow::reloadLuaPlugins()
+{
+#ifdef HAVE_LUA
+    if (wsApp->isReloadingLua())
+        return;
+
+    wsApp->setReloadingLua(true);
+
+    wslua_reload_plugins(NULL, NULL);
+    funnel_statistics_reload_menus();
+    reloadDynamicMenus();
+    closePacketDialogs();
+
+    // Preferences may have been deleted so close all widgets using prefs
+    proto_tree_->closeContextMenu();
+    main_ui_->preferenceEditorFrame->animatedHide();
+
+    wsApp->readConfigurationFiles(true);
+
+    prefs_apply_all();
+    fieldsChanged();
+    redissectPackets();
+
+    wsApp->setReloadingLua(false);
+    SimpleDialog::displayQueuedMessages();
+#endif
+}
+
 void MainWindow::showAccordionFrame(AccordionFrame *show_frame, bool toggle)
 {
     QList<AccordionFrame *>frame_list = QList<AccordionFrame *>()
             << main_ui_->goToFrame << main_ui_->searchFrame
             << main_ui_->addressEditorFrame << main_ui_->columnEditorFrame
-            << main_ui_->preferenceEditorFrame;
+            << main_ui_->preferenceEditorFrame << main_ui_->filterExpressionFrame;
 
     frame_list.removeAll(show_frame);
     foreach (AccordionFrame *af, frame_list) af->animatedHide();
@@ -1381,8 +1728,8 @@ void MainWindow::showColumnEditor(int column)
 {
     previous_focus_ = wsApp->focusWidget();
     connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
-    showAccordionFrame(main_ui_->columnEditorFrame);
     main_ui_->columnEditorFrame->editColumn(column);
+    showAccordionFrame(main_ui_->columnEditorFrame);
 }
 
 void MainWindow::showPreferenceEditor()
@@ -1464,6 +1811,9 @@ void MainWindow::setFeaturesEnabled(bool enabled)
     if(enabled)
     {
         main_ui_->statusBar->clearMessage();
+#ifdef HAVE_LIBPCAP
+        main_ui_->actionGoAutoScroll->setChecked(auto_scroll_live);
+#endif
     }
     else
     {
@@ -1486,20 +1836,19 @@ void MainWindow::on_actionDisplayFilterExpression_triggered()
 void MainWindow::on_actionNewDisplayFilterExpression_triggered()
 {
     main_ui_->filterExpressionFrame->addExpression(df_combo_box_->lineEdit()->text());
-    showAccordionFrame(main_ui_->filterExpressionFrame);
 }
 
-// On Qt4 + OS X with unifiedTitleAndToolBarOnMac set it's possible to make
-// the main window obnoxiously wide.
-
 void MainWindow::displayFilterButtonClicked()
 {
     QAction *dfb_action = qobject_cast<QAction*>(sender());
 
-    if (dfb_action) {
-        df_combo_box_->lineEdit()->setText(dfb_action->data().toString());
+    if (!dfb_action)
+        return;
+
+    df_combo_box_->setDisplayFilter(dfb_action->data().toString());
+    // Holding down the Shift key will only prepare filter.
+    if (!(QApplication::keyboardModifiers() & Qt::ShiftModifier)) {
         df_combo_box_->applyDisplayFilter();
-        df_combo_box_->lineEdit()->setFocus();
     }
 }
 
@@ -1514,8 +1863,8 @@ void MainWindow::openTapParameterDialog(const QString cfg_str, const QString arg
     TapParameterDialog *tp_dialog = TapParameterDialog::showTapParameterStatistics(*this, capture_file_, cfg_str, arg, userdata);
     if (!tp_dialog) return;
 
-    connect(tp_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
-            this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
+    connect(tp_dialog, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
+            this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
     connect(tp_dialog, SIGNAL(updateFilter(QString)),
             df_combo_box_->lineEdit(), SLOT(setText(QString)));
     tp_dialog->show();
@@ -1530,6 +1879,17 @@ void MainWindow::openTapParameterDialog()
     openTapParameterDialog(cfg_str, NULL, NULL);
 }
 
+#ifdef HAVE_SOFTWARE_UPDATE
+void MainWindow::softwareUpdateRequested() {
+    // We could call testCaptureFileClose here, but that would give us yet
+    // another dialog. Just try again later.
+    if (capture_file_.capFile() && capture_file_.capFile()->state != FILE_CLOSED) {
+        wsApp->rejectSoftwareUpdate();
+    }
+}
+#endif
+
+
 // File Menu
 
 void MainWindow::on_actionFileOpen_triggered()
@@ -1548,13 +1908,14 @@ void MainWindow::on_actionFileImportFromHexDump_triggered()
 }
 
 void MainWindow::on_actionFileClose_triggered() {
-    if (testCaptureFileClose())
+    QString before_what(tr(" before closing the file"));
+    if (testCaptureFileClose(before_what))
         main_ui_->mainStack->setCurrentWidget(main_welcome_);
 }
 
 void MainWindow::on_actionFileSave_triggered()
 {
-    saveCaptureFile(capture_file_.capFile(), FALSE);
+    saveCaptureFile(capture_file_.capFile(), false);
 }
 
 void MainWindow::on_actionFileSaveAs_triggered()
@@ -1564,7 +1925,7 @@ void MainWindow::on_actionFileSaveAs_triggered()
 
 void MainWindow::on_actionFileSetListFiles_triggered()
 {
-    file_set_dialog_.exec();
+    file_set_dialog_->show();
 }
 
 void MainWindow::on_actionFileSetNextFile_triggered()
@@ -1617,16 +1978,21 @@ void MainWindow::on_actionFileExportAsPDML_triggered()
     exportDissections(export_type_pdml);
 }
 
+void MainWindow::on_actionFileExportAsJSON_triggered()
+{
+    exportDissections(export_type_json);
+}
+
 void MainWindow::on_actionFileExportPacketBytes_triggered()
 {
     QString file_name;
 
     if (!capture_file_.capFile() || !capture_file_.capFile()->finfo_selected) return;
 
-    file_name = QFileDialog::getSaveFileName(this,
+    file_name = WiresharkFileDialog::getSaveFileName(this,
                                              wsApp->windowTitleString(tr("Export Selected Packet Bytes")),
                                              wsApp->lastOpenDir().canonicalPath(),
-                                             tr("Raw data (*.bin *.dat *.raw);;Any File (*.*)")
+                                             tr("Raw data (*.bin *.dat *.raw);;All Files (" ALL_FILES_WILDCARD ")")
                                              );
 
     if (file_name.length() > 0) {
@@ -1635,25 +2001,32 @@ void MainWindow::on_actionFileExportPacketBytes_triggered()
 
         data_p = tvb_get_ptr(capture_file_.capFile()->finfo_selected->ds_tvb, 0, -1) +
                 capture_file_.capFile()->finfo_selected->start;
-        fd = ws_open(file_name.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
+        fd = ws_open(qUtf8Printable(file_name), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
         if (fd == -1) {
-            open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE);
+            open_failure_alert_box(qUtf8Printable(file_name), errno, TRUE);
             return;
         }
         if (ws_write(fd, data_p, capture_file_.capFile()->finfo_selected->length) < 0) {
-            write_failure_alert_box(file_name.toUtf8().constData(), errno);
+            write_failure_alert_box(qUtf8Printable(file_name), errno);
             ws_close(fd);
             return;
         }
         if (ws_close(fd) < 0) {
-            write_failure_alert_box(file_name.toUtf8().constData(), errno);
+            write_failure_alert_box(qUtf8Printable(file_name), errno);
             return;
         }
 
         /* Save the directory name for future file dialogs. */
-        wsApp->setLastOpenDir(&file_name);
+        wsApp->setLastOpenDir(file_name);
     }
 }
+
+void MainWindow::on_actionAnalyzeShowPacketBytes_triggered()
+{
+    ShowPacketBytesDialog *spbd = new ShowPacketBytesDialog(*this, capture_file_);
+    spbd->show();
+}
+
 void MainWindow::on_actionFileExportPDU_triggered()
 {
     ExportPDUDialog *exportpdu_dialog = new ExportPDUDialog(this);
@@ -1690,21 +2063,20 @@ void MainWindow::on_actionFileExportSSLSessionKeys_triggered()
         return;
     }
 
-    save_title.append(wsApp->windowTitleString(tr("Export SSL Session Keys (%1 key%2").
-            arg(keylist_len).arg(plurality(keylist_len, "", "s"))));
-    file_name = QFileDialog::getSaveFileName(this,
+    save_title.append(wsApp->windowTitleString(tr("Export SSL Session Keys (%Ln key(s))", "", keylist_len)));
+    file_name = WiresharkFileDialog::getSaveFileName(this,
                                              save_title,
                                              wsApp->lastOpenDir().canonicalPath(),
-                                             tr("SSL Session Keys (*.keys *.txt);;Any File (*.*)")
+                                             tr("SSL Session Keys (*.keys *.txt);;All Files (" ALL_FILES_WILDCARD ")")
                                              );
     if (file_name.length() > 0) {
         gchar *keylist;
         int fd;
 
         keylist = ssl_export_sessions();
-        fd = ws_open(file_name.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
+        fd = ws_open(qUtf8Printable(file_name), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
         if (fd == -1) {
-            open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE);
+            open_failure_alert_box(qUtf8Printable(file_name), errno, TRUE);
             g_free(keylist);
             return;
         }
@@ -1713,69 +2085,39 @@ void MainWindow::on_actionFileExportSSLSessionKeys_triggered()
          * _write().  Presumably this string will be <= 4GiB long....
          */
         if (ws_write(fd, keylist, (unsigned int)strlen(keylist)) < 0) {
-            write_failure_alert_box(file_name.toUtf8().constData(), errno);
+            write_failure_alert_box(qUtf8Printable(file_name), errno);
             ws_close(fd);
             g_free(keylist);
             return;
         }
         if (ws_close(fd) < 0) {
-            write_failure_alert_box(file_name.toUtf8().constData(), errno);
+            write_failure_alert_box(qUtf8Printable(file_name), errno);
             g_free(keylist);
             return;
         }
 
         /* Save the directory name for future file dialogs. */
-        wsApp->setLastOpenDir(&file_name);
+        wsApp->setLastOpenDir(file_name);
         g_free(keylist);
     }
 }
 
-void MainWindow::on_actionFileExportObjectsDICOM_triggered()
-{
-    new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Dicom);
-}
-
 void MainWindow::on_actionStatisticsHpfeeds_triggered()
 {
     openStatisticsTreeDialog("hpfeeds");
 }
 
-void MainWindow::on_actionFileExportObjectsHTTP_triggered()
-{
-    new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Http);
-}
-
-void MainWindow::on_actionFileExportObjectsSMB_triggered()
-{
-    new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Smb);
-}
-
-void MainWindow::on_actionFileExportObjectsTFTP_triggered()
-{
-    new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Tftp);
-}
-
 void MainWindow::on_actionFilePrint_triggered()
 {
-    PrintDialog pdlg(this, capture_file_.capFile());
+    capture_file *cf = capture_file_.capFile();
+    g_return_if_fail(cf);
 
+    PrintDialog pdlg(this, cf);
     pdlg.exec();
 }
 
 // Edit Menu
 
-void MainWindow::recursiveCopyProtoTreeItems(QTreeWidgetItem *item, QString &clip, int ident_level) {
-    if (!item->isExpanded()) return;
-
-    for (int i_item = 0; i_item < item->childCount(); i_item += 1) {
-        clip.append(QString("    ").repeated(ident_level));
-        clip.append(item->child(i_item)->text(0));
-        clip.append("\n");
-
-        recursiveCopyProtoTreeItems(item->child(i_item), clip, ident_level + 1);
-    }
-}
-
 // XXX This should probably be somewhere else.
 void MainWindow::actionEditCopyTriggered(MainWindow::CopySelected selection_type)
 {
@@ -1806,20 +2148,11 @@ void MainWindow::actionEditCopyTriggered(MainWindow::CopySelected selection_type
         }
         break;
     case CopyAllVisibleItems:
-        for (int i_item = 0; i_item < proto_tree_->topLevelItemCount(); i_item += 1) {
-            clip.append(proto_tree_->topLevelItem(i_item)->text(0));
-            clip.append("\n");
-
-            recursiveCopyProtoTreeItems(proto_tree_->topLevelItem(i_item), clip, 1);
-        }
-
+        clip = proto_tree_->toString();
         break;
     case CopyAllVisibleSelectedTreeItems:
-        if (proto_tree_->selectedItems().count() > 0) {
-            clip.append(proto_tree_->currentItem()->text(0));
-            clip.append("\n");
-
-            recursiveCopyProtoTreeItems(proto_tree_->currentItem(), clip, 1);
+        if (proto_tree_->selectionModel()->hasSelection()) {
+            clip = proto_tree_->toString(proto_tree_->selectionModel()->selectedIndexes().first());
         }
         break;
     }
@@ -1870,12 +2203,15 @@ void MainWindow::on_actionEditCopyAsFilter_triggered()
 
 void MainWindow::on_actionEditFindPacket_triggered()
 {
-    if (packet_list_->model()->rowCount() < 1) {
+    if (packet_list_->packetListModel()->rowCount() < 1) {
         return;
     }
     previous_focus_ = wsApp->focusWidget();
     connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
-    showAccordionFrame(main_ui_->searchFrame, true);
+    if (! main_ui_->searchFrame->isVisible()) {
+        showAccordionFrame(main_ui_->searchFrame, true);
+    }
+    main_ui_->searchFrame->setFocus();
 }
 
 void MainWindow::on_actionEditFindNext_triggered()
@@ -1893,6 +2229,7 @@ void MainWindow::on_actionEditMarkPacket_triggered()
     freeze();
     packet_list_->markFrame();
     thaw();
+    setMenusForSelectedPacket();
 }
 
 void MainWindow::on_actionEditMarkAllDisplayed_triggered()
@@ -1900,6 +2237,7 @@ void MainWindow::on_actionEditMarkAllDisplayed_triggered()
     freeze();
     packet_list_->markAllDisplayedFrames(true);
     thaw();
+    setMenusForSelectedPacket();
 }
 
 void MainWindow::on_actionEditUnmarkAllDisplayed_triggered()
@@ -1907,6 +2245,7 @@ void MainWindow::on_actionEditUnmarkAllDisplayed_triggered()
     freeze();
     packet_list_->markAllDisplayedFrames(false);
     thaw();
+    setMenusForSelectedPacket();
 }
 
 void MainWindow::on_actionEditNextMark_triggered()
@@ -1926,6 +2265,7 @@ void MainWindow::on_actionEditIgnorePacket_triggered()
     freeze();
     packet_list_->ignoreFrame();
     thaw();
+    setMenusForSelectedPacket();
 }
 
 void MainWindow::on_actionEditIgnoreAllDisplayed_triggered()
@@ -1933,6 +2273,7 @@ void MainWindow::on_actionEditIgnoreAllDisplayed_triggered()
     freeze();
     packet_list_->ignoreAllDisplayedFrames(true);
     thaw();
+    setMenusForSelectedPacket();
 }
 
 void MainWindow::on_actionEditUnignoreAllDisplayed_triggered()
@@ -1940,16 +2281,19 @@ void MainWindow::on_actionEditUnignoreAllDisplayed_triggered()
     freeze();
     packet_list_->ignoreAllDisplayedFrames(false);
     thaw();
+    setMenusForSelectedPacket();
 }
 
 void MainWindow::on_actionEditSetTimeReference_triggered()
 {
     packet_list_->setTimeReference();
+    setMenusForSelectedPacket();
 }
 
 void MainWindow::on_actionEditUnsetAllTimeReferences_triggered()
 {
     packet_list_->unsetAllTimeReferences();
+    setMenusForSelectedPacket();
 }
 
 void MainWindow::on_actionEditNextTimeReference_triggered()
@@ -1975,47 +2319,55 @@ void MainWindow::on_actionEditTimeShift_triggered()
 
 void MainWindow::on_actionEditPacketComment_triggered()
 {
-    PacketCommentDialog pc_dialog(this, packet_list_->packetComment());
+    PacketCommentDialog pc_dialog(capture_file_.capFile()->current_frame->num, this, packet_list_->packetComment());
     if (pc_dialog.exec() == QDialog::Accepted) {
         packet_list_->setPacketComment(pc_dialog.text());
         updateForUnsavedChanges();
     }
 }
 
-void MainWindow::on_actionEditConfigurationProfiles_triggered()
+void MainWindow::on_actionDeleteAllPacketComments_triggered()
 {
-    ProfileDialog cp_dialog;
+    QMessageBox msg_dialog;
 
-    cp_dialog.exec();
+    msg_dialog.setIcon(QMessageBox::Question);
+    msg_dialog.setText(tr("Are you sure you want to remove all packet comments?"));
+
+    msg_dialog.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
+    msg_dialog.setDefaultButton(QMessageBox::Ok);
+
+    if (msg_dialog.exec() == QMessageBox::Ok)
+    {
+        /* XXX Do we need a wait/hourglass for large files? */
+        packet_list_->deleteAllPacketComments();
+        updateForUnsavedChanges();
+    }
 }
 
-void MainWindow::showPreferencesDialog(PreferencesDialog::PreferencesPane start_pane)
+void MainWindow::on_actionEditConfigurationProfiles_triggered()
 {
-    PreferencesDialog pref_dialog(this);
-
-    pref_dialog.setPane(start_pane);
-    pref_dialog.exec();
+    ProfileDialog cp_dialog;
 
-    // Emitting PacketDissectionChanged directly from a QDialog can cause
-    // problems on OS X.
-    wsApp->flushAppSignals();
+    cp_dialog.exec();
 }
 
-void MainWindow::showPreferencesDialog(QString module_name)
+void MainWindow::showPreferencesDialog(QString pane_name)
 {
     PreferencesDialog pref_dialog(this);
 
-    pref_dialog.setPane(module_name);
+    saveWindowGeometry();  // Save in case the layout panes are rearranged
+
+    pref_dialog.setPane(pane_name);
     pref_dialog.exec();
 
     // Emitting PacketDissectionChanged directly from a QDialog can cause
-    // problems on OS X.
+    // problems on macOS.
     wsApp->flushAppSignals();
 }
 
 void MainWindow::on_actionEditPreferences_triggered()
 {
-    showPreferencesDialog();
+    showPreferencesDialog(PrefsModel::APPEARANCE_PREFERENCE_TREE_NAME);
 }
 
 // View Menu
@@ -2051,6 +2403,38 @@ void MainWindow::showHideMainWidgets(QAction *action)
     } else if (widget == byte_view_tab_) {
         recent.byte_view_show = show;
         main_ui_->actionViewPacketBytes->setChecked(show);
+    } else {
+        foreach (QAction *action, main_ui_->menuInterfaceToolbars->actions()) {
+            QToolBar *toolbar = action->data().value<QToolBar *>();
+            if (widget == toolbar) {
+                GList *entry = g_list_find_custom(recent.interface_toolbars, action->text().toUtf8(), (GCompareFunc) strcmp);
+                if (show && !entry) {
+                    recent.interface_toolbars = g_list_append(recent.interface_toolbars, g_strdup(action->text().toUtf8()));
+                } else if (!show && entry) {
+                    recent.interface_toolbars = g_list_remove(recent.interface_toolbars, entry->data);
+                }
+                action->setChecked(show);
+            }
+        }
+
+        ext_toolbar_t * toolbar = VariantPointer<ext_toolbar_t>::asPtr(action->data());
+        if (toolbar) {
+            GList *entry = g_list_find_custom(recent.gui_additional_toolbars, toolbar->name, (GCompareFunc) strcmp);
+            if (show && !entry) {
+                recent.gui_additional_toolbars = g_list_append(recent.gui_additional_toolbars, g_strdup(toolbar->name));
+            } else if (!show && entry) {
+                recent.gui_additional_toolbars = g_list_remove(recent.gui_additional_toolbars, entry->data);
+            }
+            action->setChecked(show);
+
+            QList<QToolBar *> toolbars = findChildren<QToolBar *>();
+            foreach (QToolBar *bar, toolbars) {
+                AdditionalToolBar *iftoolbar = dynamic_cast<AdditionalToolBar *>(bar);
+                if (iftoolbar && iftoolbar->menuName().compare(toolbar->name) == 0) {
+                    iftoolbar->setVisible(show);
+                }
+            }
+        }
     }
 
     if (widget) {
@@ -2058,8 +2442,6 @@ void MainWindow::showHideMainWidgets(QAction *action)
     }
 }
 
-Q_DECLARE_METATYPE(ts_type)
-
 void MainWindow::setTimestampFormat(QAction *action)
 {
     if (!action) {
@@ -2069,18 +2451,17 @@ void MainWindow::setTimestampFormat(QAction *action)
     if (recent.gui_time_format != tsf) {
         timestamp_set_type(tsf);
         recent.gui_time_format = tsf;
+
+        if (packet_list_) {
+            packet_list_->resetColumns();
+        }
         if (capture_file_.capFile()) {
             /* This call adjusts column width */
             cf_timestamp_auto_precision(capture_file_.capFile());
         }
-        if (packet_list_) {
-            packet_list_->columnsChanged();
-        }
     }
 }
 
-Q_DECLARE_METATYPE(ts_precision)
-
 void MainWindow::setTimestampPrecision(QAction *action)
 {
     if (!action) {
@@ -2091,13 +2472,14 @@ void MainWindow::setTimestampPrecision(QAction *action)
         /* the actual precision will be set in packet_list_queue_draw() below */
         timestamp_set_precision(tsp);
         recent.gui_time_precision = tsp;
+
+        if (packet_list_) {
+            packet_list_->resetColumns();
+        }
         if (capture_file_.capFile()) {
             /* This call adjusts column width */
             cf_timestamp_auto_precision(capture_file_.capFile());
         }
-        if (packet_list_) {
-            packet_list_->columnsChanged();
-        }
     }
 }
 
@@ -2110,13 +2492,13 @@ void MainWindow::on_actionViewTimeDisplaySecondsWithHoursAndMinutes_triggered(bo
     }
     timestamp_set_seconds_type(recent.gui_seconds_format);
 
+    if (packet_list_) {
+        packet_list_->resetColumns();
+    }
     if (capture_file_.capFile()) {
         /* This call adjusts column width */
         cf_timestamp_auto_precision(capture_file_.capFile());
     }
-    if (packet_list_) {
-        packet_list_->columnsChanged();
-    }
 }
 
 void MainWindow::on_actionViewEditResolvedName_triggered()
@@ -2139,8 +2521,9 @@ void MainWindow::setNameResolution()
     gbl_resolv_flags.transport_name = main_ui_->actionViewNameResolutionTransport->isChecked() ? TRUE : FALSE;
 
     if (packet_list_) {
-        packet_list_->columnsChanged();
+        packet_list_->resetColumns();
     }
+    wsApp->emitAppSignal(WiresharkApplication::NameResolutionChanged);
 }
 
 void MainWindow::on_actionViewNameResolutionPhysical_triggered()
@@ -2160,14 +2543,7 @@ void MainWindow::on_actionViewNameResolutionTransport_triggered()
 
 void MainWindow::zoomText()
 {
-    // Scale by 10%, rounding to nearest half point, minimum 1 point.
-    // XXX Small sizes repeat. It might just be easier to create a map of multipliers.
-    mono_font_ = QFont(wsApp->monospaceFont());
-    qreal zoom_size = wsApp->monospaceFont().pointSize() * 2 * qPow(1.1, recent.gui_zoom_level);
-    zoom_size = qRound(zoom_size) / 2.0;
-    zoom_size = qMax(zoom_size, 1.0);
-    mono_font_.setPointSizeF(zoom_size);
-    emit monospaceFontChanged(mono_font_);
+    wsApp->zoomTextFont(recent.gui_zoom_level);
 }
 
 void MainWindow::on_actionViewZoomIn_triggered()
@@ -2190,7 +2566,7 @@ void MainWindow::on_actionViewNormalSize_triggered()
 
 void MainWindow::on_actionViewColorizePacketList_triggered(bool checked) {
     recent.packet_list_colorize = checked;
-    color_filters_enable(checked);
+    packet_list_recolor_packets();
     packet_list_->packetListModel()->resetColorized();
 }
 
@@ -2199,44 +2575,22 @@ void MainWindow::on_actionViewColoringRules_triggered()
     ColoringRulesDialog coloring_rules_dialog(this);
     connect(&coloring_rules_dialog, SIGNAL(accepted()),
             packet_list_, SLOT(recolorPackets()));
+    connect(&coloring_rules_dialog, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
+            this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
     coloring_rules_dialog.exec();
 }
 
 // actionViewColorizeConversation1 - 10
 void MainWindow::colorizeConversation(bool create_rule)
 {
-    QAction *cc_action = qobject_cast<QAction *>(sender());
-    if (!cc_action) return;
+    QAction *colorize_action = qobject_cast<QAction *>(sender());
+    if (!colorize_action) return;
 
     if (capture_file_.capFile() && capture_file_.capFile()->current_frame) {
-        packet_info *pi = &capture_file_.capFile()->edt->pi;
-        guint8 cc_num = cc_action->data().toUInt();
-        gchar *filter = NULL;
-
-        const conversation_filter_t *color_filter = find_conversation_filter("tcp");
-        if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
-            filter = color_filter->build_filter_string(pi);
-        if (filter == NULL) {
-            color_filter = find_conversation_filter("udp");
-            if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
-                filter = color_filter->build_filter_string(pi);
-        }
-        if (filter == NULL) {
-            color_filter = find_conversation_filter("ip");
-            if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
-                filter = color_filter->build_filter_string(pi);
-        }
+        packet_info *pi = capture_file_.packetInfo();
+        guint8 cc_num = colorize_action->data().toUInt();
+        gchar *filter = conversation_filter_from_packet(pi);
         if (filter == NULL) {
-            color_filter = find_conversation_filter("ipv6");
-            if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
-                filter = color_filter->build_filter_string(pi);
-        }
-        if (filter == NULL) {
-            color_filter = find_conversation_filter("eth");
-            if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
-                filter = color_filter->build_filter_string(pi);
-        }
-        if( filter == NULL ) {
             main_ui_->statusBar->pushTemporaryStatus(tr("Unable to build conversation filter."));
             return;
         }
@@ -2245,35 +2599,60 @@ void MainWindow::colorizeConversation(bool create_rule)
             ColoringRulesDialog coloring_rules_dialog(this, filter);
             connect(&coloring_rules_dialog, SIGNAL(accepted()),
                     packet_list_, SLOT(recolorPackets()));
+            connect(&coloring_rules_dialog, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
+                    this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
             coloring_rules_dialog.exec();
         } else {
-            color_filters_set_tmp(cc_num, filter, FALSE);
+            gchar *err_msg = NULL;
+            if (!color_filters_set_tmp(cc_num, filter, FALSE, &err_msg)) {
+                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
+                g_free(err_msg);
+            }
             packet_list_->recolorPackets();
         }
     }
     setMenusForSelectedPacket();
 }
 
-void MainWindow::colorizeWithFilter()
+void MainWindow::colorizeActionTriggered()
 {
-    QAction *colorize_action = qobject_cast<QAction *>(sender());
-    if (!colorize_action) return;
+    QByteArray filter;
+    int color_number = -1;
 
-    QString filter = colorize_action->data().toString();
-    if (filter.isEmpty()) return;
+    ConversationAction *conv_action = qobject_cast<ConversationAction *>(sender());
+    if (conv_action) {
+        filter = conv_action->filter();
+        color_number = conv_action->colorNumber();
+    } else {
+        ColorizeAction *colorize_action = qobject_cast<ColorizeAction *>(sender());
+        if (colorize_action) {
+            filter = colorize_action->filter();
+            color_number = colorize_action->colorNumber();
+        }
+    }
 
-    bool ok = false;
-    int color_number = colorize_action->property(color_number_property_).toInt(&ok);
+    colorizeWithFilter(filter, color_number);
+}
 
-    if (ok) {
+void MainWindow::colorizeWithFilter(QByteArray filter, int color_number)
+{
+    if (filter.isEmpty()) return;
+
+    if (color_number > 0) {
         // Assume "Color X"
-        color_filters_set_tmp(color_number, filter.toUtf8().constData(), FALSE);
+        gchar *err_msg = NULL;
+        if (!color_filters_set_tmp(color_number, filter.constData(), FALSE, &err_msg)) {
+            simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
+            g_free(err_msg);
+        }
         packet_list_->recolorPackets();
     } else {
         // New coloring rule
         ColoringRulesDialog coloring_rules_dialog(window(), filter);
         connect(&coloring_rules_dialog, SIGNAL(accepted()),
                 packet_list_, SLOT(recolorPackets()));
+        connect(&coloring_rules_dialog, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
+                this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
         coloring_rules_dialog.exec();
     }
     main_ui_->actionViewColorizeResetColorization->setEnabled(tmp_color_filters_used());
@@ -2281,16 +2660,28 @@ void MainWindow::colorizeWithFilter()
 
 void MainWindow::on_actionViewColorizeResetColorization_triggered()
 {
-    color_filters_reset_tmp();
+    gchar *err_msg = NULL;
+    if (!color_filters_reset_tmp(&err_msg)) {
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
+        g_free(err_msg);
+    }
     packet_list_->recolorPackets();
     setMenusForSelectedPacket();
 }
 
-void MainWindow::on_actionViewColorizeNewConversationRule_triggered()
+void MainWindow::on_actionViewColorizeNewColoringRule_triggered()
 {
     colorizeConversation(true);
 }
 
+void MainWindow::on_actionViewResetLayout_triggered()
+{
+    recent.gui_geometry_main_upper_pane = 0;
+    recent.gui_geometry_main_lower_pane = 0;
+
+    applyRecentPaneGeometry();
+}
+
 void MainWindow::on_actionViewResizeColumns_triggered()
 {
     for (int col = 0; col < packet_list_->packetListModel()->columnCount(); col++) {
@@ -2309,7 +2700,7 @@ void MainWindow::openPacketDialog(bool from_reference)
         if (framenum == 0)
             return;
 
-        fdata = frame_data_sequence_find(capture_file_.capFile()->frames, framenum);
+        fdata = frame_data_sequence_find(capture_file_.capFile()->provider.frames, framenum);
     } else {
         fdata = capture_file_.capFile()->current_frame;
     }
@@ -2318,11 +2709,9 @@ void MainWindow::openPacketDialog(bool from_reference)
     if (fdata) {
         PacketDialog *packet_dialog = new PacketDialog(*this, capture_file_, fdata);
 
-        connect(this, SIGNAL(monospaceFontChanged(QFont)),
-                packet_dialog, SIGNAL(monospaceFontChanged(QFont)));
         connect(this, SIGNAL(closePacketDialogs()),
                 packet_dialog, SLOT(close()));
-        zoomText(); // Emits monospaceFontChanged
+        zoomText(); // Emits wsApp->zoomMonospaceFont(QFont)
 
         packet_dialog->show();
     }
@@ -2359,13 +2748,27 @@ void MainWindow::on_actionContextShowLinkedPacketInNewWindow_triggered()
 
 void MainWindow::on_actionViewReload_triggered()
 {
-    cf_reload(CaptureFile::globalCapFile());
+    capture_file *cf = CaptureFile::globalCapFile();
+
+    if (cf->unsaved_changes) {
+        QString before_what(tr(" before reloading the file"));
+        if (!testCaptureFileClose(before_what, Reload))
+            return;
+    }
+
+    cf_reload(cf);
 }
 
 void MainWindow::on_actionViewReload_as_File_Format_or_Capture_triggered()
 {
     capture_file *cf = CaptureFile::globalCapFile();
 
+    if (cf->unsaved_changes) {
+        QString before_what(tr(" before reloading the file"));
+        if (!testCaptureFileClose(before_what, Reload))
+            return;
+    }
+
     if (cf->open_type == WTAP_TYPE_AUTO)
         cf->open_type = open_info_name_to_type("MIME Files Format");
     else /* TODO: This should be latest format chosen by user */
@@ -2402,10 +2805,9 @@ void MainWindow::matchFieldFilter(FilterAction::Action action, FilterAction::Act
         return;
     }
 
-    filterAction(field_filter, action, filter_type);
+    emit filterAction(field_filter, action, filter_type);
 }
 
-static FilterDialog *display_filter_dlg_ = NULL;
 void MainWindow::on_actionAnalyzeDisplayFilters_triggered()
 {
     if (!display_filter_dlg_) {
@@ -2425,7 +2827,7 @@ void MainWindow::on_actionAnalyzeDisplayFilterMacros_triggered()
 
     uat_dlg.exec();
     // Emitting PacketDissectionChanged directly from a QDialog can cause
-    // problems on OS X.
+    // problems on macOS.
     wsApp->flushAppSignals();
 }
 
@@ -2433,8 +2835,7 @@ void MainWindow::on_actionAnalyzeCreateAColumn_triggered()
 {
     gint colnr = 0;
 
-    if ( capture_file_.capFile() != 0 && capture_file_.capFile()->finfo_selected != 0 )
-    {
+    if (capture_file_.capFile() != 0 && capture_file_.capFile()->finfo_selected != 0) {
         colnr = column_prefs_add_custom(COL_CUSTOM, capture_file_.capFile()->finfo_selected->hfinfo->name,
                     capture_file_.capFile()->finfo_selected->hfinfo->abbrev,0);
 
@@ -2447,14 +2848,33 @@ void MainWindow::on_actionAnalyzeCreateAColumn_triggered()
 
 void MainWindow::applyConversationFilter()
 {
-    QAction *cfa = qobject_cast<QAction*>(sender());
-    if (!cfa) return;
+    ConversationAction *conv_action = qobject_cast<ConversationAction*>(sender());
+    if (!conv_action) return;
+
+    packet_info *pinfo = capture_file_.packetInfo();
+    if (!pinfo) return;
+
+    QByteArray conv_filter = conv_action->filter();
+    if (conv_filter.isEmpty()) return;
+
+    if (conv_action->isFilterValid(pinfo)) {
+
+        df_combo_box_->lineEdit()->setText(conv_filter);
+        df_combo_box_->applyDisplayFilter();
+    }
+}
+
+void MainWindow::applyExportObject()
+{
+    ExportObjectAction *export_action = qobject_cast<ExportObjectAction*>(sender());
+    if (!export_action)
+        return;
+
+    ExportObjectDialog* export_dialog = new ExportObjectDialog(*this, capture_file_, export_action->exportObject());
 
-    QString new_filter = cfa->data().toString();
-    if (new_filter.isEmpty()) return;
+    connect(export_dialog->getExportObjectView(), SIGNAL(goToPacket(int)),
+            packet_list_, SLOT(goToPacket(int)));
 
-    df_combo_box_->lineEdit()->setText(new_filter);
-    df_combo_box_->applyDisplayFilter();
 }
 
 // XXX We could probably create the analyze and prepare actions
@@ -2526,7 +2946,7 @@ void MainWindow::on_actionAnalyzeEnabledProtocols_triggered()
     enable_proto_dialog.exec();
 
     // Emitting PacketDissectionChanged directly from a QDialog can cause
-    // problems on OS X.
+    // problems on macOS.
     wsApp->flushAppSignals();
 }
 
@@ -2539,50 +2959,31 @@ void MainWindow::on_actionAnalyzeDecodeAs_triggered()
     }
 
     DecodeAsDialog da_dialog(this, capture_file_.capFile(), create_new);
-    connect(this, SIGNAL(setCaptureFile(capture_file*)),
-            &da_dialog, SLOT(setCaptureFile(capture_file*)));
     da_dialog.exec();
 
     // Emitting PacketDissectionChanged directly from a QDialog can cause
-    // problems on OS X.
+    // problems on macOS.
     wsApp->flushAppSignals();
 }
 
-#ifdef HAVE_LUA
 void MainWindow::on_actionAnalyzeReloadLuaPlugins_triggered()
 {
-    if (wsApp->isReloadingLua())
-        return;
-
-    wsApp->setReloadingLua(true);
-
-    wslua_reload_plugins(NULL, NULL);
-    funnel_statistics_reload_menus();
-    reloadDynamicMenus();
-    closePacketDialogs();
-
-    // Preferences may have been deleted so close all widgets using prefs
-    proto_tree_->closeContextMenu();
-    main_ui_->preferenceEditorFrame->animatedHide();
-
-    char *gdp_path, *dp_path;
-    (void) wsApp->readConfigurationFiles(&gdp_path, &dp_path);
-
-    fieldsChanged();
-    redissectPackets();
-
-    wsApp->setReloadingLua(false);
-    SimpleDialog::displayQueuedMessages();
+    reloadLuaPlugins();
 }
-#endif
 
-void MainWindow::openFollowStreamDialog(follow_type_t type) {
+void MainWindow::openFollowStreamDialog(follow_type_t type, int stream_num) {
     FollowStreamDialog *fsd = new FollowStreamDialog(*this, capture_file_, type);
     connect(fsd, SIGNAL(updateFilter(QString, bool)), this, SLOT(filterPackets(QString, bool)));
     connect(fsd, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
 
     fsd->show();
-    fsd->follow(getFilter());
+    if (stream_num >= 0) {
+        // If a specific conversation was requested, then ignore any previous
+        // display filters and display all related packets.
+        fsd->follow("", true, stream_num);
+    } else {
+        fsd->follow(getFilter());
+    }
 }
 
 void MainWindow::on_actionAnalyzeFollowTCPStream_triggered()
@@ -2600,6 +3001,11 @@ void MainWindow::on_actionAnalyzeFollowSSLStream_triggered()
     openFollowStreamDialog(FOLLOW_SSL);
 }
 
+void MainWindow::on_actionAnalyzeFollowHTTPStream_triggered()
+{
+    openFollowStreamDialog(FOLLOW_HTTP);
+}
+
 void MainWindow::openSCTPAllAssocsDialog()
 {
     SCTPAllAssocsDialog *sctp_dialog = new SCTPAllAssocsDialog(this, capture_file_.capFile());
@@ -2660,8 +3066,8 @@ void MainWindow::on_actionSCTPFilterThisAssociation_triggered()
 void MainWindow::statCommandWlanStatistics(const char *arg, void *)
 {
     WlanStatisticsDialog *wlan_stats_dlg = new WlanStatisticsDialog(*this, capture_file_, arg);
-    connect(wlan_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
-            this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
+    connect(wlan_stats_dlg, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
+            this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
     wlan_stats_dlg->show();
 }
 
@@ -2678,10 +3084,10 @@ void MainWindow::statCommandExpertInfo(const char *, void *)
 
     expert_dialog->setDisplayFilter(df_edit->text());
 
-    connect(expert_dialog, SIGNAL(goToPacket(int, int)),
+    connect(expert_dialog->getExpertInfoView(), SIGNAL(goToPacket(int, int)),
             packet_list_, SLOT(goToPacket(int, int)));
-    connect(expert_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
-            this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
+    connect(expert_dialog, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
+            this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
 
     expert_dialog->show();
 }
@@ -2699,8 +3105,6 @@ void MainWindow::on_actionAnalyzeExpertInfo_triggered()
 void MainWindow::on_actionStatisticsFlowGraph_triggered()
 {
     SequenceDialog *sequence_dialog = new SequenceDialog(*this, capture_file_);
-    connect(sequence_dialog, SIGNAL(goToPacket(int)),
-            packet_list_, SLOT(goToPacket(int)));
     sequence_dialog->show();
 }
 
@@ -2711,7 +3115,9 @@ void MainWindow::openTcpStreamDialog(int graph_type)
             packet_list_, SLOT(goToPacket(int)));
     connect(this, SIGNAL(setCaptureFile(capture_file*)),
             stream_dialog, SLOT(setCaptureFile(capture_file*)));
-    stream_dialog->show();
+    if (stream_dialog->result() == QDialog::Accepted) {
+        stream_dialog->show();
+    }
 }
 
 void MainWindow::on_actionStatisticsTcpStreamStevens_triggered()
@@ -2743,8 +3149,8 @@ void MainWindow::on_actionStatisticsTcpStreamWindowScaling_triggered()
 void MainWindow::statCommandMulticastStatistics(const char *arg, void *)
 {
     MulticastStatisticsDialog *mcast_stats_dlg = new MulticastStatisticsDialog(*this, capture_file_, arg);
-    connect(mcast_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
-            this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
+    connect(mcast_stats_dlg, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
+            this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
     mcast_stats_dlg->show();
 }
 
@@ -2826,16 +3232,6 @@ void MainWindow::on_actionStatistics29WestUIM_Streams_triggered()
     stream_dialog->show();
 }
 
-void MainWindow::on_actionStatistics29WestUIM_Stream_Flow_Graph_triggered()
-{
-    LBMUIMFlowDialog * uimflow_dialog = new LBMUIMFlowDialog(this, capture_file_.capFile());
-    connect(uimflow_dialog, SIGNAL(goToPacket(int)),
-            packet_list_, SLOT(goToPacket(int)));
-    connect(this, SIGNAL(setCaptureFile(capture_file*)),
-            uimflow_dialog, SLOT(setCaptureFile(capture_file*)));
-    uimflow_dialog->show();
-}
-
 void MainWindow::on_actionStatistics29WestLBTRM_triggered()
 {
     LBMLBTRMTransportDialog * lbtrm_dialog = new LBMLBTRMTransportDialog(this, capture_file_.capFile());
@@ -2889,10 +3285,10 @@ void MainWindow::on_actionStatisticsCollectd_triggered()
 void MainWindow::statCommandConversations(const char *arg, void *userdata)
 {
     ConversationDialog *conv_dialog = new ConversationDialog(*this, capture_file_, GPOINTER_TO_INT(userdata), arg);
-    connect(conv_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
-            this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
-    connect(conv_dialog, SIGNAL(openFollowStreamDialog(follow_type_t)),
-            this, SLOT(openFollowStreamDialog(follow_type_t)));
+    connect(conv_dialog, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
+            this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
+    connect(conv_dialog, SIGNAL(openFollowStreamDialog(follow_type_t,int)),
+            this, SLOT(openFollowStreamDialog(follow_type_t,int)));
     connect(conv_dialog, SIGNAL(openTcpStreamGraph(int)),
             this, SLOT(openTcpStreamDialog(int)));
     conv_dialog->show();
@@ -2907,8 +3303,8 @@ void MainWindow::on_actionStatisticsConversations_triggered()
 void MainWindow::statCommandEndpoints(const char *arg, void *userdata)
 {
     EndpointDialog *endp_dialog = new EndpointDialog(*this, capture_file_, GPOINTER_TO_INT(userdata), arg);
-    connect(endp_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
-            this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
+    connect(endp_dialog, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
+            this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
     connect(endp_dialog, SIGNAL(openFollowStreamDialog(follow_type_t)),
             this, SLOT(openFollowStreamDialog(follow_type_t)));
     connect(endp_dialog, SIGNAL(openTcpStreamGraph(int)),
@@ -2941,6 +3337,11 @@ void MainWindow::on_actionStatisticsHTTPLoadDistribution_triggered()
     openStatisticsTreeDialog("http_srv");
 }
 
+void MainWindow::on_actionStatisticsHTTPRequestSequences_triggered()
+{
+    openStatisticsTreeDialog("http_seq");
+}
+
 void MainWindow::on_actionStatisticsPacketLengths_triggered()
 {
     openStatisticsTreeDialog("plen");
@@ -3024,8 +3425,8 @@ void MainWindow::on_actionTelephonyISUPMessages_triggered()
 void MainWindow::statCommandLteMacStatistics(const char *arg, void *)
 {
     LteMacStatisticsDialog *lte_mac_stats_dlg = new LteMacStatisticsDialog(*this, capture_file_, arg);
-    connect(lte_mac_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
-            this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
+    connect(lte_mac_stats_dlg, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
+            this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
     lte_mac_stats_dlg->show();
 }
 
@@ -3037,8 +3438,8 @@ void MainWindow::on_actionTelephonyLteMacStatistics_triggered()
 void MainWindow::statCommandLteRlcStatistics(const char *arg, void *)
 {
     LteRlcStatisticsDialog *lte_rlc_stats_dlg = new LteRlcStatisticsDialog(*this, capture_file_, arg);
-    connect(lte_rlc_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
-            this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
+    connect(lte_rlc_stats_dlg, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
+            this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
     // N.B. It is necessary for the RLC Statistics window to launch the RLC graph in this way, to ensure
     // that the goToPacket() signal/slot connection gets set up...
     connect(lte_rlc_stats_dlg, SIGNAL(launchRLCGraph(bool, guint16, guint8, guint16, guint16, guint8)),
@@ -3078,6 +3479,11 @@ void MainWindow::on_actionTelephonyMtp3Summary_triggered()
     mtp3s_dialog->show();
 }
 
+void MainWindow::on_actionTelephonyOsmuxPacketCounter_triggered()
+{
+    openStatisticsTreeDialog("osmux");
+}
+
 void MainWindow::on_actionTelephonyRTPStreams_triggered()
 {
     RtpStreamDialog *rtp_stream_dialog = new  RtpStreamDialog(*this, capture_file_);
@@ -3118,7 +3524,7 @@ void MainWindow::on_actionTelephonySipFlows_triggered()
     openVoipCallsDialog(true);
 }
 
-// Bluetooth Menu
+// Wireless Menu
 
 void MainWindow::on_actionBluetoothATT_Server_Attributes_triggered()
 {
@@ -3132,7 +3538,7 @@ void MainWindow::on_actionBluetoothATT_Server_Attributes_triggered()
 
 void MainWindow::on_actionBluetoothDevices_triggered()
 {
-    BluetoothDevicesDialog *bluetooth_devices_dialog = new BluetoothDevicesDialog(*this, capture_file_);
+    BluetoothDevicesDialog *bluetooth_devices_dialog = new BluetoothDevicesDialog(*this, capture_file_, packet_list_);
     connect(bluetooth_devices_dialog, SIGNAL(goToPacket(int)),
             packet_list_, SLOT(goToPacket(int)));
     connect(bluetooth_devices_dialog, SIGNAL(updateFilter(QString, bool)),
@@ -3150,6 +3556,15 @@ void MainWindow::on_actionBluetoothHCI_Summary_triggered()
     bluetooth_hci_summary_dialog->show();
 }
 
+// Tools Menu
+
+void MainWindow::on_actionToolsFirewallAclRules_triggered()
+{
+    FirewallRulesDialog *firewall_rules_dialog = new FirewallRulesDialog(*this, capture_file_);
+    firewall_rules_dialog->show();
+}
+
+
 // Help Menu
 void MainWindow::on_actionHelpContents_triggered() {
 
@@ -3252,7 +3667,7 @@ void MainWindow::on_actionHelpAbout_triggered()
 }
 
 void MainWindow::on_actionGoGoToPacket_triggered() {
-    if (packet_list_->model()->rowCount() < 1) {
+    if (packet_list_->packetListModel()->rowCount() < 1) {
         return;
     }
     previous_focus_ = wsApp->focusWidget();
@@ -3283,25 +3698,12 @@ void MainWindow::goToConversationFrame(bool go_next) {
     dfilter_t *dfcode       = NULL;
     gboolean   found_packet = FALSE;
     packet_info *pi = &(capture_file_.capFile()->edt->pi);
-    conversation_filter_t* conv_filter;
 
     /* Try to build a conversation
      * filter in the order TCP, UDP, IP, Ethernet and apply the
      * coloring */
-    conv_filter = find_conversation_filter("tcp");
-    if ((conv_filter != NULL) && (conv_filter->is_filter_valid(pi)))
-        filter = conv_filter->build_filter_string(pi);
-    conv_filter = find_conversation_filter("udp");
-    if ((conv_filter != NULL) && (conv_filter->is_filter_valid(pi)))
-        filter = conv_filter->build_filter_string(pi);
-    conv_filter = find_conversation_filter("ip");
-    if ((conv_filter != NULL) && (conv_filter->is_filter_valid(pi)))
-        filter = conv_filter->build_filter_string(pi);
-    conv_filter = find_conversation_filter("ipv6");
-    if ((conv_filter != NULL) && (conv_filter->is_filter_valid(pi)))
-        filter = conv_filter->build_filter_string(pi);
-
-    if( filter == NULL ) {
+    filter = conversation_filter_from_packet(pi);
+    if (filter == NULL) {
         main_ui_->statusBar->pushTemporaryStatus(tr("Unable to build conversation filter."));
         g_free(filter);
         return;
@@ -3337,7 +3739,7 @@ void MainWindow::on_actionGoPreviousConversationPacket_triggered()
 
 void MainWindow::on_actionGoAutoScroll_toggled(bool checked)
 {
-    packet_list_->setAutoScroll(checked);
+    packet_list_->setVerticalAutoScroll(checked);
 }
 
 void MainWindow::resetPreviousFocus() {
@@ -3403,7 +3805,7 @@ void MainWindow::on_actionCaptureStart_triggered()
 
     /* XXX - will closing this remove a temporary file? */
     QString before_what(tr(" before starting a new capture"));
-    if (testCaptureFileClose(FALSE, before_what)) {
+    if (testCaptureFileClose(before_what)) {
         startCapture();
     } else {
         // simply clicking the button sets it to 'checked' even though we've
@@ -3420,12 +3822,14 @@ void MainWindow::on_actionCaptureStop_triggered()
 
 void MainWindow::on_actionCaptureRestart_triggered()
 {
+    QString before_what(tr(" before restarting the capture"));
+    if (!testCaptureFileClose(before_what, Restart))
+        return;
+
 /* TODO: GTK use only this: capture_restart(&cap_session_); */
-    captureStop();
     startCapture();
 }
 
-static FilterDialog *capture_filter_dlg_ = NULL;
 void MainWindow::on_actionCaptureCaptureFilters_triggered()
 {
     if (!capture_filter_dlg_) {
@@ -3453,34 +3857,57 @@ void MainWindow::on_actionStatisticsResolvedAddresses_triggered()
 void MainWindow::on_actionStatisticsProtocolHierarchy_triggered()
 {
     ProtocolHierarchyDialog *phd = new ProtocolHierarchyDialog(*this, capture_file_);
-    connect(phd, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
-            this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
+    connect(phd, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
+            this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
     phd->show();
 }
 
-#ifdef HAVE_LIBPCAP
 void MainWindow::on_actionCaptureOptions_triggered()
 {
-    connect(&capture_interfaces_dialog_, SIGNAL(setFilterValid(bool)), this, SLOT(startInterfaceCapture(bool)));
-    capture_interfaces_dialog_.SetTab(0);
-    capture_interfaces_dialog_.updateInterfaces();
-
-    if (capture_interfaces_dialog_.isMinimized() == true)
-    {
-        capture_interfaces_dialog_.showNormal();
+#ifdef HAVE_LIBPCAP
+    if (!capture_interfaces_dialog_) {
+        capture_interfaces_dialog_ = new CaptureInterfacesDialog(this);
+
+        connect(capture_interfaces_dialog_, SIGNAL(startCapture()), this, SLOT(startCapture()));
+        connect(capture_interfaces_dialog_, SIGNAL(stopCapture()), this, SLOT(stopCapture()));
+
+        connect(capture_interfaces_dialog_, SIGNAL(getPoints(int,PointList*)),
+                this->main_welcome_->getInterfaceFrame(), SLOT(getPoints(int,PointList*)));
+        connect(capture_interfaces_dialog_, SIGNAL(interfacesChanged()),
+                this->main_welcome_, SLOT(interfaceSelected()));
+        connect(capture_interfaces_dialog_, SIGNAL(interfacesChanged()),
+                this->main_welcome_->getInterfaceFrame(), SLOT(updateSelectedInterfaces()));
+        connect(capture_interfaces_dialog_, SIGNAL(interfaceListChanged()),
+                this->main_welcome_->getInterfaceFrame(), SLOT(interfaceListChanged()));
+        connect(capture_interfaces_dialog_, SIGNAL(captureFilterTextEdited(QString)),
+                this->main_welcome_, SLOT(setCaptureFilterText(QString)));
+        // Propagate selection changes from main UI to dialog.
+        connect(this->main_welcome_, SIGNAL(interfacesChanged()),
+                capture_interfaces_dialog_, SLOT(interfaceSelected()));
+
+        connect(capture_interfaces_dialog_, SIGNAL(setFilterValid(bool, const QString)),
+                this, SLOT(startInterfaceCapture(bool, const QString)));
     }
-    else
-    {
-        capture_interfaces_dialog_.show();
+    capture_interfaces_dialog_->setTab(0);
+    capture_interfaces_dialog_->updateInterfaces();
+
+    if (capture_interfaces_dialog_->isMinimized()) {
+        capture_interfaces_dialog_->showNormal();
+    } else {
+        capture_interfaces_dialog_->show();
     }
 
-    capture_interfaces_dialog_.raise();
-    capture_interfaces_dialog_.activateWindow();
+    capture_interfaces_dialog_->raise();
+    capture_interfaces_dialog_->activateWindow();
+#endif
 }
 
+#ifdef HAVE_LIBPCAP
 void MainWindow::on_actionCaptureRefreshInterfaces_triggered()
 {
+    main_ui_->actionCaptureRefreshInterfaces->setEnabled(false);
     wsApp->refreshLocalInterfaces();
+    main_ui_->actionCaptureRefreshInterfaces->setEnabled(true);
 }
 #endif
 
@@ -3490,21 +3917,16 @@ void MainWindow::externalMenuItem_triggered()
     QVariant v;
     ext_menubar_t * entry = NULL;
 
-    if ( QObject::sender() != NULL)
-    {
+    if (QObject::sender()) {
         triggerAction = (QAction *)QObject::sender();
         v = triggerAction->data();
 
-        if ( v.canConvert<void *>())
-        {
+        if (v.canConvert<void *>()) {
             entry = (ext_menubar_t *)v.value<void *>();
 
-            if ( entry->type == EXT_MENUBAR_ITEM )
-            {
+            if (entry->type == EXT_MENUBAR_ITEM) {
                 entry->callback(EXT_MENUBAR_QT_GUI, (gpointer) ((void *)main_ui_), entry->user_data);
-            }
-            else
-            {
+            } else {
                 QDesktopServices::openUrl(QUrl(QString((gchar *)entry->user_data)));
             }
         }
@@ -3513,86 +3935,30 @@ void MainWindow::externalMenuItem_triggered()
 
 void MainWindow::gotoFrame(int packet_num)
 {
-    if ( packet_num > 0 )
-    {
+    if (packet_num > 0) {
         packet_list_->goToPacket(packet_num);
     }
 }
 
-#ifdef HAVE_EXTCAP
 void MainWindow::extcap_options_finished(int result)
 {
-    if ( result == QDialog::Accepted )
-    {
+    if (result == QDialog::Accepted) {
         startCapture();
     }
-    this->main_welcome_->getInterfaceTree()->interfaceListChanged();
+    this->main_welcome_->getInterfaceFrame()->interfaceListChanged();
 }
 
 void MainWindow::showExtcapOptionsDialog(QString &device_name)
 {
     ExtcapOptionsDialog * extcap_options_dialog = ExtcapOptionsDialog::createForDevice(device_name, this);
+    extcap_options_dialog->setModal(true);
     /* The dialog returns null, if the given device name is not a valid extcap device */
-    if ( extcap_options_dialog != NULL )
-    {
+    if (extcap_options_dialog) {
         connect(extcap_options_dialog, SIGNAL(finished(int)),
                 this, SLOT(extcap_options_finished(int)));
         extcap_options_dialog->show();
     }
 }
-#endif
-
-// Q_DECLARE_METATYPE(field_info *) called in proto_tree.h
-
-void MainWindow::on_actionContextCopyBytesHexTextDump_triggered()
-{
-    QAction *ca = qobject_cast<QAction*>(sender());
-    if (!ca) return;
-
-    field_info *fi = ca->data().value<field_info *>();
-
-    byte_view_tab_->copyData(ByteViewTab::copyDataHexTextDump, fi);
-}
-
-void MainWindow::on_actionContextCopyBytesHexDump_triggered()
-{
-    QAction *ca = qobject_cast<QAction*>(sender());
-    if (!ca) return;
-
-    field_info *fi = ca->data().value<field_info *>();
-
-    byte_view_tab_->copyData(ByteViewTab::copyDataHexDump, fi);
-}
-
-void MainWindow::on_actionContextCopyBytesPrintableText_triggered()
-{
-    QAction *ca = qobject_cast<QAction*>(sender());
-    if (!ca) return;
-
-    field_info *fi = ca->data().value<field_info *>();
-
-    byte_view_tab_->copyData(ByteViewTab::copyDataPrintableText, fi);
-}
-
-void MainWindow::on_actionContextCopyBytesHexStream_triggered()
-{
-    QAction *ca = qobject_cast<QAction*>(sender());
-    if (!ca) return;
-
-    field_info *fi = ca->data().value<field_info *>();
-
-    byte_view_tab_->copyData(ByteViewTab::copyDataHexStream, fi);
-}
-
-void MainWindow::on_actionContextCopyBytesBinary_triggered()
-{
-    QAction *ca = qobject_cast<QAction*>(sender());
-    if (!ca) return;
-
-    field_info *fi = ca->data().value<field_info *>();
-
-    byte_view_tab_->copyData(ByteViewTab::copyDataBinary, fi);
-}
 
 void MainWindow::on_actionContextWikiProtocolPage_triggered()
 {
@@ -3635,6 +4001,207 @@ void MainWindow::on_actionContextFilterFieldReference_triggered()
     QDesktopServices::openUrl(dfref_url);
 }
 
+void MainWindow::on_actionViewFullScreen_triggered(bool checked)
+{
+    if (checked) {
+        // Save the state for future restore
+        was_maximized_ = this->isMaximized();
+        this->showFullScreen();
+    } else {
+        // Restore the previous state
+        if (was_maximized_)
+            this->showMaximized();
+        else
+            this->showNormal();
+    }
+}
+
+void MainWindow::activatePluginIFToolbar(bool)
+{
+    QAction *sendingAction = dynamic_cast<QAction *>(sender());
+    if (!sendingAction || !sendingAction->data().isValid())
+        return;
+
+    ext_toolbar_t *toolbar = VariantPointer<ext_toolbar_t>::asPtr(sendingAction->data());
+
+    QList<QToolBar *> toolbars = findChildren<QToolBar *>();
+    foreach (QToolBar *bar, toolbars) {
+        AdditionalToolBar *iftoolbar = dynamic_cast<AdditionalToolBar *>(bar);
+        if (iftoolbar && iftoolbar->menuName().compare(toolbar->name) == 0) {
+            if (iftoolbar->isVisible()) {
+                iftoolbar->setVisible(false);
+                sendingAction->setChecked(true);
+            } else {
+                iftoolbar->setVisible(true);
+                sendingAction->setChecked(true);
+            }
+        }
+    }
+}
+
+void MainWindow::filterToolbarCustomMenuHandler(const QPoint& pos)
+{
+    QAction * filterAction = filter_expression_toolbar_->actionAt(pos);
+    if ( ! filterAction )
+        return;
+
+    QMenu * filterMenu = new QMenu(this);
+
+    QAction *actFilter = filterMenu->addAction(tr("Filter Button Preferences..."));
+    connect(actFilter, SIGNAL(triggered()), this, SLOT(filterToolbarShowPreferences()));
+    actFilter->setProperty(dfe_property_label_, filterAction->property(dfe_property_label_));
+    actFilter->setProperty(dfe_property_expression_, filterAction->property(dfe_property_expression_));
+    actFilter->setData(filterAction->data());
+    filterMenu->addSeparator();
+    QAction * actEdit = filterMenu->addAction(tr("Edit"));
+    connect(actEdit, SIGNAL(triggered()), this, SLOT(filterToolbarEditFilter()));
+    actEdit->setProperty(dfe_property_label_, filterAction->property(dfe_property_label_));
+    actEdit->setProperty(dfe_property_expression_, filterAction->property(dfe_property_expression_));
+    actEdit->setData(filterAction->data());
+    QAction * actDisable = filterMenu->addAction(tr("Disable"));
+    connect(actDisable, SIGNAL(triggered()), this, SLOT(filterToolbarDisableFilter()));
+    actDisable->setProperty(dfe_property_label_, filterAction->property(dfe_property_label_));
+    actDisable->setProperty(dfe_property_expression_, filterAction->property(dfe_property_expression_));
+    actDisable->setData(filterAction->data());
+    QAction * actRemove = filterMenu->addAction(tr("Remove"));
+    connect(actRemove, SIGNAL(triggered()), this, SLOT(filterToolbarRemoveFilter()));
+    actRemove->setProperty(dfe_property_label_, filterAction->property(dfe_property_label_));
+    actRemove->setProperty(dfe_property_expression_, filterAction->property(dfe_property_expression_));
+    actRemove->setData(filterAction->data());
+
+    filterMenu->exec(filter_expression_toolbar_->mapToGlobal(pos));
+}
+
+void MainWindow::filterToolbarShowPreferences()
+{
+    emit showPreferencesDialog(PrefsModel::FILTER_BUTTONS_PREFERENCE_TREE_NAME);
+}
+
+int MainWindow::uatRowIndexForFilterExpression(QString label, QString expression)
+{
+    int result = -1;
+
+    if ( expression.length() == 0 )
+        return result;
+
+    UatModel * uatModel = new UatModel(this, "Display expressions");
+
+    QModelIndex rowIndex;
+
+    if ( label.length() > 0 )
+    {
+        for ( int cnt = 0; cnt < uatModel->rowCount() && ! rowIndex.isValid(); cnt++ )
+        {
+            if ( uatModel->data(uatModel->index(cnt, 1), Qt::DisplayRole).toString().compare(label) == 0 &&
+                    uatModel->data(uatModel->index(cnt, 2), Qt::DisplayRole).toString().compare(expression) == 0 )
+            {
+                rowIndex = uatModel->index(cnt, 2);
+            }
+        }
+    }
+    else
+    {
+        rowIndex = uatModel->findRowForColumnContent(((QAction *)sender())->data(), 2);
+    }
+
+    if ( rowIndex.isValid() )
+        result = rowIndex.row();
+
+    delete uatModel;
+
+    return result;
+}
+
+void MainWindow::filterToolbarEditFilter()
+{
+    if ( ! sender() )
+        return;
+
+    QString label = ((QAction *)sender())->property(dfe_property_label_).toString();
+    QString expr = ((QAction *)sender())->property(dfe_property_expression_).toString();
+
+    int idx = uatRowIndexForFilterExpression(label, expr);
+
+    if ( idx > -1 )
+        main_ui_->filterExpressionFrame->editExpression(idx);
+}
+
+void MainWindow::filterDropped(QString description, QString filter)
+{
+    gchar* err = NULL;
+    if ( filter.length() == 0 )
+        return;
+
+    filter_expression_new(qUtf8Printable(description),
+            qUtf8Printable(filter), qUtf8Printable(description), TRUE);
+
+    uat_save(uat_get_table_by_name("Display expressions"), &err);
+    g_free(err);
+
+    filterExpressionsChanged();
+}
+
+void MainWindow::filterToolbarDisableFilter()
+{
+    gchar* err = NULL;
+
+    QString label = ((QAction *)sender())->property(dfe_property_label_).toString();
+    QString expr = ((QAction *)sender())->property(dfe_property_expression_).toString();
+
+    int idx = uatRowIndexForFilterExpression(label, expr);
+    UatModel * uatModel = new UatModel(this, "Display expressions");
+
+    QModelIndex rowIndex = uatModel->index(idx, 0);
+    if ( rowIndex.isValid() ) {
+        uatModel->setData(rowIndex, QVariant::fromValue(false));
+
+        uat_save(uat_get_table_by_name("Display expressions"), &err);
+        g_free(err);
+        filterExpressionsChanged();
+    }
+}
+
+void MainWindow::filterToolbarRemoveFilter()
+{
+    gchar* err = NULL;
+    UatModel * uatModel = new UatModel(this, "Display expressions");
+
+    QString label = ((QAction *)sender())->property(dfe_property_label_).toString();
+    QString expr = ((QAction *)sender())->property(dfe_property_expression_).toString();
+
+    int idx = uatRowIndexForFilterExpression(label, expr);
+
+    QModelIndex rowIndex = uatModel->index(idx, 0);
+    if ( rowIndex.isValid() ) {
+        uatModel->removeRow(rowIndex.row());
+
+        uat_save(uat_get_table_by_name("Display expressions"), &err);
+        g_free(err);
+        filterExpressionsChanged();
+    }
+}
+
+void MainWindow::filterToolbarActionMoved(QAction* action, int oldPos, int newPos)
+{
+    gchar* err = NULL;
+    if ( oldPos == newPos )
+        return;
+
+    QString label = action->property(dfe_property_label_).toString();
+    QString expr = action->property(dfe_property_expression_).toString();
+
+    int idx = uatRowIndexForFilterExpression(label, expr);
+
+    if ( idx > -1 && oldPos > -1 && newPos > -1 )
+    {
+        uat_t * table = uat_get_table_by_name("Display expressions");
+        uat_move_index(table, oldPos, newPos);
+        uat_save(table, &err);
+
+        g_free(err);
+    }
+}
+
 #ifdef _MSC_VER
 #pragma warning(pop)
 #endif