Initial status bar functionality. Promote the main window's status bar
authorgerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 14 Jan 2012 00:16:16 +0000 (00:16 +0000)
committergerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 14 Jan 2012 00:16:16 +0000 (00:16 +0000)
to a MainStatusBar. Add a "LabelStack" widget, which MainStatusBar uses
to duplicate features in GtkStatusbar. Make the protocol tree a
full-blown ProtoTree widget. Move main_cf_callback from main to
WiresharkApplication. Duplicate a lot of the cf callbacks as signals and
slots. Use Q_UNUSED in a few places.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@40488 f5534014-38df-0310-8fa8-9805f1628bb7

17 files changed:
ui/qt/QtShark.pro
ui/qt/display_filter_edit.cpp
ui/qt/display_filter_edit.h
ui/qt/label_stack.cpp [new file with mode: 0644]
ui/qt/label_stack.h [new file with mode: 0644]
ui/qt/main.cpp
ui/qt/main_status_bar.cpp
ui/qt/main_status_bar.h
ui/qt/main_window.cpp
ui/qt/main_window.h
ui/qt/main_window.ui
ui/qt/packet_list.cpp
ui/qt/packet_list.h
ui/qt/proto_tree.cpp
ui/qt/proto_tree.h
ui/qt/wireshark_application.cpp
ui/qt/wireshark_application.h

index cb5443ee14c64160aeb3748f727e7a6424eda8e5..2f91b73b22d92fc1107c9bd6c08df807bb7baa64 100644 (file)
@@ -105,6 +105,7 @@ SOURCES += \
     recent_file_status.cpp \
     simple_dialog_qt.cpp \
     wireshark_application.cpp \
+    label_stack.cpp
 
 
 unix:SOURCES += ../../capture-pcap-util-unix.c
@@ -137,6 +138,7 @@ HEADERS  += \
     recent_file_status.h \
     simple_dialog_qt.h \
     wireshark_application.h \
+    label_stack.h
 
 
 FORMS += main_window.ui
index ab76014124afd599965c6685cf997e8fb109e7ca..84a1b55a48b1ab5c67187a4520fa23177c38c29e 100644 (file)
@@ -254,11 +254,11 @@ void DisplayFilterEdit::checkFilter(const QString& text)
 
     clearButton->setVisible(!text.isEmpty());
 
+    popFilterSyntaxStatus();
+
     if (fieldNameOnly && (c = proto_check_field_name(text.toUtf8().constData()))) {
         m_syntaxState = Invalid;
-//        if (use_statusbar) {
-//            statusbar_push_filter_msg(" Illegal character in field name: '%c'", c);
-//        }
+        emit pushFilterSyntaxStatus(QString().sprintf("Illegal character in field name: '%c'", c));
     } else if (dfilter_compile(text.toUtf8().constData(), &dfp)) {
         if (dfp != NULL) {
             depr = dfilter_deprecated_tokens(dfp);
@@ -268,30 +268,25 @@ void DisplayFilterEdit::checkFilter(const QString& text)
         } else if (depr) {
             /* You keep using that word. I do not think it means what you think it means. */
             m_syntaxState = Deprecated;
-//            if (use_statusbar) {
-//                /*
-//                 * We're being lazy and only printing the first "problem" token.
-//                 * Would it be better to print all of them?
-//                 */
-//                statusbar_push_temporary_msg(" \"%s\" may have unexpected results (see the User's Guide)",
-//                                      (const char *) g_ptr_array_index(depr, 0));
-//            }
+            /*
+             * We're being lazy and only printing the first "problem" token.
+             * Would it be better to print all of them?
+             */
+            emit pushFilterSyntaxWarning(QString().sprintf("\"%s\" may have unexpected results (see the User's Guide)",
+                                                          (const char *) g_ptr_array_index(depr, 0)));
         } else {
             m_syntaxState = Valid;
         }
         dfilter_free(dfp);
     } else {
         m_syntaxState = Invalid;
-//        if (use_statusbar) {
-//            if (dfilter_error_msg) {
-//                statusbar_push_filter_msg(" Invalid filter: %s", dfilter_error_msg);
-//            } else {
-//                statusbar_push_filter_msg(" Invalid filter");
-//            }
-//        }
+        QString invalidMsg("Invalid filter");
+        if (dfilter_error_msg) {
+            invalidMsg.append(QString().sprintf(": %s", dfilter_error_msg));
+        }
+        emit pushFilterSyntaxStatus(invalidMsg);
     }
 
-    g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: show display filter syntax status in statusbar");
     setStyleSheet(syntaxStyleSheet);
     applyButton->setEnabled(m_syntaxState == Empty || m_syntaxState == Valid);
 
index 2d8bffd81de9675853e1a44525a8628d58955213..721a10e193d9ac1d6941e076508005e8020db91c 100644 (file)
@@ -59,6 +59,9 @@ private:
     QToolButton *applyButton;
 
 signals:
+    void pushFilterSyntaxStatus(QString&);
+    void popFilterSyntaxStatus();
+    void pushFilterSyntaxWarning(QString&);
 
 public slots:
 
diff --git a/ui/qt/label_stack.cpp b/ui/qt/label_stack.cpp
new file mode 100644 (file)
index 0000000..82a7885
--- /dev/null
@@ -0,0 +1,103 @@
+/* label_stack.cpp
+ *
+ * $Id: mainStatus_bar.cpp 40378 2012-01-04 22:13:01Z gerald $
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "label_stack.h"
+
+#include <QTimer>
+
+/* Temporary message timeouts */
+#define TEMPORARY_MSG_TIMEOUT (7 * 1000)
+//#define TEMPORARY_FLASH_TIMEOUT (1 * 1000)
+//#define TEMPORARY_FLASH_INTERVAL (TEMPORARY_FLASH_TIMEOUT / 4)
+
+LabelStack::LabelStack(QWidget *parent) :
+    QLabel(parent)
+{
+    m_temporaryCtx = -1;
+    fillLabel();
+}
+
+void LabelStack::setTemporaryContext(int ctx) {
+    m_temporaryCtx = ctx;
+}
+
+void LabelStack::fillLabel() {
+    StackItem *si;
+
+    setStyleSheet(
+            "QLabel {"
+            "  margin-left: 0.5em;"
+            "}"
+            );
+
+    if (m_labels.isEmpty()) {
+        clear();
+        return;
+    }
+
+    si = m_labels.first();
+
+    if (si->ctx == m_temporaryCtx) {
+        setStyleSheet(
+                // Tango "Scarlet Red"
+                "QLabel {"
+                "  margin-left: 0.5em;"
+                "  border-radius: 3px;"
+                "  color: white;"
+                "  background-color: rgba(239, 41, 41, 128);"
+                "}"
+                );
+    }
+
+    setText(si->text);
+}
+
+void LabelStack::pushText(QString &text, int ctx) {
+    StackItem *si = new StackItem;
+    si->text = text;
+    si->ctx = ctx;
+    m_labels.prepend(si);
+
+    if (ctx == m_temporaryCtx) {
+        QTimer::singleShot(TEMPORARY_MSG_TIMEOUT, this, SLOT(popTemporaryText()));
+    }
+
+    fillLabel();
+}
+
+void LabelStack::popText(int ctx) {
+    QMutableListIterator<StackItem *> iter(m_labels);
+
+    while (iter.hasNext()) {
+        if (iter.next()->ctx == ctx) {
+            iter.remove();
+            break;
+        }
+    }
+
+    fillLabel();
+}
+
+void LabelStack::popTemporaryText() {
+    popText(m_temporaryCtx);
+}
diff --git a/ui/qt/label_stack.h b/ui/qt/label_stack.h
new file mode 100644 (file)
index 0000000..60272f7
--- /dev/null
@@ -0,0 +1,58 @@
+/* label_stack.h
+ *
+ * $Id: mainStatus_bar.cpp 40378 2012-01-04 22:13:01Z gerald $
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef LABEL_STACK_H
+#define LABEL_STACK_H
+
+#include <QLabel>
+#include <QStack>
+
+class LabelStack : public QLabel
+{
+    Q_OBJECT
+public:
+    explicit LabelStack(QWidget *parent = 0);
+    void setTemporaryContext(int ctx);
+    void pushText(QString &text, int ctx);
+
+private:
+    typedef struct _StackItem {
+        QString text;
+        int ctx;
+    } StackItem;
+
+    int m_temporaryCtx;
+    QList<StackItem *> m_labels;
+
+    void fillLabel();
+
+signals:
+
+public slots:
+    void popText(int ctx);
+
+private slots:
+    void popTemporaryText();
+};
+
+#endif // LABEL_STACK_H
index bcdbcc28085d12e053b93564d9529968bc7df7c5..60447be151a0b281fa502660c9d75dff952f33f9 100644 (file)
@@ -173,52 +173,10 @@ void pipe_input_set_handler(gint source, gpointer user_data, int *child_process,
 }
 
 static void
-main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
+main_cf_callback(gint event, gpointer data, gpointer user_data )
 {
-    g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: main_cf_callback %d %p", event, data);
-//    switch(event) {
-//    case(cf_cb_file_closing):
-//        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
-//        main_cf_cb_file_closing(data);
-//        break;
-//    case(cf_cb_file_closed):
-//        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
-//        main_cf_cb_file_closed(data);
-//        break;
-//    case(cf_cb_file_read_started):
-//        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
-//        main_cf_cb_file_read_started(data);
-//        break;
-//    case(cf_cb_file_read_finished):
-//        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
-//        main_cf_cb_file_read_finished(data);
-//        break;
-//    case(cf_cb_packet_selected):
-//        main_cf_cb_packet_selected(data);
-//        break;
-//    case(cf_cb_packet_unselected):
-//        main_cf_cb_packet_unselected(data);
-//        break;
-//    case(cf_cb_field_unselected):
-//        main_cf_cb_field_unselected(data);
-//        break;
-//    case(cf_cb_file_save_started):
-//        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
-//        break;
-//    case(cf_cb_file_save_finished):
-//        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
-//        break;
-//    case(cf_cb_file_save_reload_finished):
-//        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
-//        main_cf_cb_file_save_reload_finished(data);
-//        break;
-//    case(cf_cb_file_save_failed):
-//        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
-//        break;
-//    default:
-//        g_warning("main_cf_callback: event %u unknown", event);
-//        g_assert_not_reached();
-//    }
+    Q_UNUSED(user_data);
+    wsApp->captureFileCallback(event, data);
 }
 
 // XXX Copied from gtk/main.c. This should be moved to a common location.
index 4266fb4660ba12b6519d7528847bd8483b6cbfb6..656492134c359e5a37bb8a00767f316bcd4dde85 100644 (file)
 
 #include "main_status_bar.h"
 
+#include "wireshark_application.h"
+
 #include "main_statusbar.h"
+#include "globals.h"
+
+#include <QSplitter>
+
+#ifdef HAVE_LIBPCAP
+#define DEF_READY_MESSAGE " Ready to load or capture"
+#else
+#define DEF_READY_MESSAGE " Ready to load file"
+#endif
+
+// XXX - The GTK+ code assigns priorities to these and pushes/pops accordingly.
+
+enum StatusContext {
+    STATUS_CTX_MAIN,
+    STATUS_CTX_FILE,
+    STATUS_CTX_FIELD,
+    STATUS_CTX_FILTER,
+    STATUS_CTX_TEMPORARY
+};
 
-/* Temporary message timeouts */
-#define TEMPORARY_MSG_TIMEOUT (7 * 1000)
-#define TEMPORARY_FLASH_TIMEOUT (1 * 1000)
-#define TEMPORARY_FLASH_INTERVAL (TEMPORARY_FLASH_TIMEOUT / 4)
+// If we ever add support for multiple windows this will need to be replaced.
+// See also: main_window.cpp
+static MainStatusBar *cur_main_status_bar = NULL;
 
 /*
  * Push a formatted temporary message onto the statusbar.
@@ -44,21 +64,18 @@ statusbar_push_temporary_msg(const gchar *msg_format, ...)
 {
     va_list ap;
     gchar *msg;
-    guint msg_id;
+    QString pushMsg;
+
+    if (!cur_main_status_bar) return;
 
     va_start(ap, msg_format);
     msg = g_strdup_vprintf(msg_format, ap);
     va_end(ap);
 
-    g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: statusbar_push_temporary_msg: %s", msg);
-
-//    msg_id = gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, msg);
+    pushMsg.fromUtf8(msg);
     g_free(msg);
 
-//    flash_time = TEMPORARY_FLASH_TIMEOUT - 1;
-//    g_timeout_add(TEMPORARY_FLASH_INTERVAL, statusbar_flash_temporary_msg, NULL);
-
-//    g_timeout_add(TEMPORARY_MSG_TIMEOUT, statusbar_remove_temporary_msg, GUINT_TO_POINTER(msg_id));
+    cur_main_status_bar->pushTemporaryStatus(pushMsg);
 }
 
 /*
@@ -67,41 +84,109 @@ statusbar_push_temporary_msg(const gchar *msg_format, ...)
 void
 packets_bar_update(void)
 {
-    g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: packets_bar_update");
-//    if(packets_bar) {
-//        /* Remove old status */
-//        if(packets_str) {
-//            gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
-//        } else {
-//            packets_str = g_string_new ("");
-//     }
-
-//        /* Do we have any packets? */
-//        if(cfile.count) {
-//            g_string_printf(packets_str, " Packets: %u Displayed: %u Marked: %u",
-//                            cfile.count, cfile.displayed_count, cfile.marked_count);
-//            if(cfile.drops_known) {
-//                g_string_append_printf(packets_str, " Dropped: %u", cfile.drops);
-//            }
-//            if(cfile.ignored_count > 0) {
-//                g_string_append_printf(packets_str, " Ignored: %u", cfile.ignored_count);
-//            }
-//            if(!cfile.is_tempfile){
-//                /* Loading an existing file */
-//                gulong computed_elapsed = cf_get_computed_elapsed();
-//                g_string_append_printf(packets_str, " Load time: %lu:%02lu.%03lu",
-//                                       computed_elapsed/60000,
-//                                       computed_elapsed%60000/1000,
-//                                       computed_elapsed%1000);
-//            }
-//        } else {
-//            g_string_printf(packets_str, " No Packets");
-//        }
-//        gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, packets_str->str);
-//    }
+    QString packetsStr = QString("");
+
+    if (!cur_main_status_bar) return;
+
+    cur_main_status_bar->popPacketStatus();
+
+    /* Do we have any packets? */
+    if (cfile.count) {
+        packetsStr.append(QString("Packets: %1 Displayed: %2 Marked: %3")
+                          .arg(cfile.count)
+                          .arg(cfile.displayed_count)
+                          .arg(cfile.marked_count));
+        if(cfile.drops_known) {
+            packetsStr.append(QString(" Dropped: %1").arg(cfile.drops));
+        }
+        if(cfile.ignored_count > 0) {
+            packetsStr.append(QString(" Ignored: %1").arg(cfile.ignored_count));
+        }
+        if(!cfile.is_tempfile) {
+            /* Loading an existing file */
+            gulong computed_elapsed = cf_get_computed_elapsed();
+            packetsStr.append(QString().sprintf(" Load time: %lu:%02lu.%03lu",
+                                        computed_elapsed/60000,
+                                        computed_elapsed%60000/1000,
+                                        computed_elapsed%1000));
+        }
+    } else {
+        packetsStr.append("No Packets");
+    }
+
+    cur_main_status_bar->pushPacketStatus(packetsStr);
 }
 
 MainStatusBar::MainStatusBar(QWidget *parent) :
     QStatusBar(parent)
 {
+    QSplitter *splitter = new QSplitter(this);
+    QString readyMsg(DEF_READY_MESSAGE);
+
+    // XXX - Add the expert level icon
+
+    m_infoStatus.setTemporaryContext(STATUS_CTX_TEMPORARY);
+    splitter->addWidget(&m_infoStatus);
+    splitter->addWidget(&m_packetStatus);
+    splitter->addWidget(&m_profileStatus);
+
+    splitter->setStretchFactor(0, 3);
+    splitter->setStretchFactor(1, 3);
+    splitter->setStretchFactor(2, 0);
+
+    addWidget(splitter, 1);
+
+    cur_main_status_bar = this;
+
+    m_infoStatus.pushText(readyMsg, STATUS_CTX_MAIN);
+    packets_bar_update();
+}
+
+void MainStatusBar::pushTemporaryStatus(QString &message) {
+    m_infoStatus.pushText(message, STATUS_CTX_TEMPORARY);
+}
+
+void MainStatusBar::popTemporaryStatus() {
+    m_infoStatus.popText(STATUS_CTX_TEMPORARY);
+}
+
+void MainStatusBar::pushFileStatus(QString &message) {
+    m_infoStatus.pushText(message, STATUS_CTX_FILE);
+}
+
+void MainStatusBar::popFileStatus() {
+    m_infoStatus.popText(STATUS_CTX_FILE);
+}
+
+void MainStatusBar::pushFieldStatus(QString &message) {
+    m_infoStatus.pushText(message, STATUS_CTX_FIELD);
+}
+
+void MainStatusBar::popFieldStatus() {
+    m_infoStatus.popText(STATUS_CTX_FIELD);
+}
+
+void MainStatusBar::pushFilterStatus(QString &message) {
+    m_infoStatus.pushText(message, STATUS_CTX_FILTER);
 }
+
+void MainStatusBar::popFilterStatus() {
+    m_infoStatus.popText(STATUS_CTX_FILTER);
+}
+
+void MainStatusBar::pushPacketStatus(QString &message) {
+    m_packetStatus.pushText(message, STATUS_CTX_MAIN);
+}
+
+void MainStatusBar::popPacketStatus() {
+    m_packetStatus.popText(STATUS_CTX_MAIN);
+}
+
+void MainStatusBar::pushProfileStatus(QString &message) {
+    m_profileStatus.pushText(message, STATUS_CTX_MAIN);
+}
+
+void MainStatusBar::popProfileStatus() {
+    m_profileStatus.popText(STATUS_CTX_MAIN);
+}
+
index a4e5c074d2ae166a8fb179377c8d0802fee30e7b..3139de739279477805587b502f471f6ddd7bbb09 100644 (file)
@@ -1,4 +1,4 @@
-/* main_status_bar.h
+/* mainStatus_bar.h
  *
  * $Id$
  *
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
-#ifndef MAIN_STATUS_BAR_H
-#define MAIN_STATUS_BAR_H
+#ifndef MAINStatus_BAR_H
+#define MAINStatus_BAR_H
+
+#include "label_stack.h"
 
 #include <QStatusBar>
 
@@ -32,10 +34,26 @@ class MainStatusBar : public QStatusBar
 public:
     explicit MainStatusBar(QWidget *parent = 0);
 
+private:
+    LabelStack m_infoStatus;
+    LabelStack m_packetStatus;
+    LabelStack m_profileStatus;
+
 signals:
 
 public slots:
-
+    void pushTemporaryStatus(QString &message);
+    void popTemporaryStatus();
+    void pushFileStatus(QString &message);
+    void popFileStatus();
+    void pushFieldStatus(QString &message);
+    void popFieldStatus();
+    void pushFilterStatus(QString &message);
+    void popFilterStatus();
+    void pushPacketStatus(QString &message);
+    void popPacketStatus();
+    void pushProfileStatus(QString &message);
+    void popProfileStatus();
 };
 
-#endif // MAIN_STATUS_BAR_H
+#endif // MAINStatus_BAR_H
index ecf83f096a3c8377e291742910ed52c5a5db4657..db15c0a65e3bab1713829730fa2bc776728600a7 100644 (file)
 #include "main_window.h"
 #include "ui_main_window.h"
 
-#include "config.h"
-
-#include <glib.h>
+#include "globals.h"
 
+#include <epan/filesystem.h>
 #include <epan/prefs.h>
 
+#include "main_statusbar.h"
+
 #include "wireshark_application.h"
 #include "packet_list.h"
+#include "proto_tree.h"
 #include "byte_view_tab.h"
 #include "capture_file_dialog.h"
+#include "display_filter_edit.h"
 
 #include "qt_ui_utils.h"
 
@@ -43,8 +46,6 @@
 #include <QToolButton>
 #include <QKeyEvent>
 
-#include "globals.h"
-
 //menu_recent_file_write_all
 
 // If we ever add support for multiple windows this will need to be replaced.
@@ -54,6 +55,7 @@ MainWindow::MainWindow(QWidget *parent) :
     QMainWindow(parent),
     ui(new Ui::MainWindow)
 {
+    capFile = NULL;
     cur_main_window = this;
     ui->setupUi(this);
 
@@ -61,6 +63,10 @@ MainWindow::MainWindow(QWidget *parent) :
     updateRecentFiles();
 
     dfComboBox = new DisplayFilterCombo();
+    const DisplayFilterEdit *dfEdit = dynamic_cast<DisplayFilterEdit *>(dfComboBox->lineEdit());
+    connect(dfEdit, SIGNAL(pushFilterSyntaxStatus(QString&)), ui->statusBar, SLOT(pushFilterStatus(QString&)));
+    connect(dfEdit, SIGNAL(popFilterSyntaxStatus()), ui->statusBar, SLOT(popFilterStatus()));
+    connect(dfEdit, SIGNAL(pushFilterSyntaxWarning(QString&)), ui->statusBar, SLOT(pushTemporaryStatus(QString&)));
 
 #ifdef _WIN32
     // Qt <= 4.7 doesn't seem to style Windows toolbars. If we wanted to be really fancy we could use Blur Behind:
@@ -79,7 +85,7 @@ MainWindow::MainWindow(QWidget *parent) :
 
     PacketList *packetList = new PacketList(splitterV);
 
-    QTreeWidget *protoTree = new QTreeWidget(splitterV);
+    ProtoTree *protoTree = new ProtoTree(splitterV);
     protoTree->setHeaderHidden(true);
 
     ByteViewTab *byteViewTab = new ByteViewTab(splitterV);
@@ -97,7 +103,22 @@ MainWindow::MainWindow(QWidget *parent) :
 
     mainWelcome = new MainWelcome(ui->mainStack);
     ui->mainStack->addWidget(mainWelcome);
-    connect(mainWelcome, SIGNAL(recentFileActivated(QString&)), this, SLOT(openCaptureFile(QString&)));
+    connect(mainWelcome, SIGNAL(recentFileActivated(QString&)),
+            this, SLOT(openCaptureFile(QString&)));
+
+    connect(wsApp, SIGNAL(captureFileReadStarted(const capture_file*)),
+            this, SLOT(captureFileReadStarted(const capture_file*)));
+    connect(wsApp, SIGNAL(captureFileReadFinished(const capture_file*)),
+            this, SLOT(captureFileReadFinished(const capture_file*)));
+    connect(wsApp, SIGNAL(captureFileClosing(const capture_file*)),
+            this, SLOT(captureFileClosing(const capture_file*)));
+    connect(wsApp, SIGNAL(captureFileClosed(const capture_file*)),
+            this, SLOT(captureFileClosed(const capture_file*)));
+
+    connect(protoTree, SIGNAL(protoItemSelected(QString&)),
+            ui->statusBar, SLOT(pushFieldStatus(QString&)));
+    connect(protoTree, SIGNAL(protoItemUnselected()),
+            ui->statusBar, SLOT(popFieldStatus()));
 
     ui->mainStack->setCurrentWidget(mainWelcome);
 }
@@ -107,6 +128,72 @@ MainWindow::~MainWindow()
     delete ui;
 }
 
+void MainWindow::keyPressEvent(QKeyEvent *event) {
+
+    if (event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_Slash) {
+        dfComboBox->setFocus(Qt::ShortcutFocusReason);
+        return;
+    }
+
+    QMainWindow::keyPressEvent(event);
+}
+
+void MainWindow::captureFileReadStarted(const capture_file *cf) {
+    if (cf != capFile) return;
+//    tap_param_dlg_update();
+
+    /* Set up main window for a capture file. */
+//    main_set_for_capture_file(TRUE);
+
+    ui->statusBar->popFileStatus();
+    QString msg = QString().sprintf("Loading: %s", get_basename(cf->filename));
+    ui->statusBar->pushFileStatus(msg);
+}
+
+void MainWindow::captureFileReadFinished(const capture_file *cf) {
+    if (cf != capFile) return;
+
+//    gchar *dir_path;
+
+//    if (!cf->is_tempfile && cf->filename) {
+//        /* Add this filename to the list of recent files in the "Recent Files" submenu */
+//        add_menu_recent_capture_file(cf->filename);
+
+//        /* Remember folder for next Open dialog and save it in recent */
+//     dir_path = get_dirname(g_strdup(cf->filename));
+//        set_last_open_dir(dir_path);
+//        g_free(dir_path);
+//    }
+//    set_display_filename(cf);
+
+//    /* Enable menu items that make sense if you have a capture file you've
+//       finished reading. */
+//    set_menus_for_capture_file(cf);
+
+//    /* Enable menu items that make sense if you have some captured packets. */
+//    set_menus_for_captured_packets(TRUE);
+
+    ui->statusBar->popFileStatus();
+    QString msg = QString().sprintf("%s", get_basename(cf->filename));
+    ui->statusBar->pushFileStatus(msg);
+}
+
+void MainWindow::captureFileClosing(const capture_file *cf) {
+    if (cf != capFile) return;
+
+    /* reset expert info indicator */
+//    status_expert_hide();
+//    gtk_widget_show(expert_info_none);
+}
+
+void MainWindow::captureFileClosed(const capture_file *cf) {
+    if (cf != capFile) return;
+    packets_bar_update();
+
+    ui->statusBar->popFileStatus();
+    capFile = NULL;
+}
+
 void MainWindow::closeCaptureFile() {
     cf_close(&cfile);
     ui->mainStack->setCurrentWidget(mainWelcome);
@@ -144,9 +231,11 @@ void MainWindow::openCaptureFile(QString &cfPath)
              try again. */
             if (rfcode != NULL)
                 dfilter_free(rfcode);
+            capFile = NULL;
             return;
         } else {
             ui->mainStack->setCurrentWidget(splitterV);
+            capFile = &cfile;
             cf_read(&cfile, FALSE);
         }
     }
@@ -217,13 +306,3 @@ void MainWindow::updateRecentFiles() {
         }
     }
 }
-
-void MainWindow::keyPressEvent(QKeyEvent *event) {
-
-    if (event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_Slash) {
-        dfComboBox->setFocus(Qt::ShortcutFocusReason);
-        return;
-    }
-
-    QMainWindow::keyPressEvent(event);
-}
index 98c1950ac29c2b78e1ccfa33b4ce9923af941ede..a43d46dee53b51f2f3099a8160abc4d87ecc68e1 100644 (file)
 
 #include <stdio.h>
 
+#include "config.h"
+
+#include <glib.h>
+
+#include "file.h"
+
 #include <QMainWindow>
 #include <QSplitter>
 #include "main_welcome.h"
@@ -54,8 +60,13 @@ private:
     QSplitter *splitterV;
     MainWelcome *mainWelcome;
     DisplayFilterCombo *dfComboBox;
+    capture_file *capFile;
 
 public slots:
+    void captureFileReadStarted(const capture_file *cf);
+    void captureFileReadFinished(const capture_file *cf);
+    void captureFileClosing(const capture_file *cf);
+    void captureFileClosed(const capture_file *cf);
 
 private slots:
     void closeCaptureFile();
index 6ab73243b4df1f8be27f2b8a4fb1ff10bebc79da..5043b1256005e8788831846efe6cc42fc31dbe42 100644 (file)
    <addaction name="actionStopCapture"/>
    <addaction name="separator"/>
   </widget>
-  <widget class="QStatusBar" name="statusBar"/>
+  <widget class="MainStatusBar" name="statusBar"/>
   <widget class="QToolBar" name="utilityToolBar">
    <property name="windowTitle">
     <string>toolBar</string>
   </action>
  </widget>
  <layoutdefault spacing="6" margin="11"/>
+ <customwidgets>
+  <customwidget>
+   <class>MainStatusBar</class>
+   <extends>QStatusBar</extends>
+   <header>main_status_bar.h</header>
+  </customwidget>
+ </customwidgets>
  <resources>
   <include location="toolbar.qrc"/>
  </resources>
index 0b8e0844b2b07f33070dd32f8c1c14888b6f1ac7..a00bbc63b82723ae7761093d3b0994852ae604f4 100644 (file)
@@ -41,6 +41,7 @@
 #include "ui_util.h"
 #include "globals.h"
 #include "qt_ui_utils.h"
+#include "main_statusbar.h"
 
 #include "gtk/recent.h"
 
@@ -56,8 +57,11 @@ static gboolean enable_color;
 static PacketList *cur_packet_list = NULL;
 
 guint
-new_packet_list_append(column_info *cinfo _U_, frame_data *fdata, packet_info *pinfo _U_)
+new_packet_list_append(column_info *cinfo, frame_data *fdata, packet_info *pinfo)
 {
+    Q_UNUSED(cinfo);
+    Q_UNUSED(pinfo);
+
     if (!cur_packet_list)
         return 0;
 
@@ -200,7 +204,7 @@ new_packet_list_thaw(void)
 //     /* Remove extra reference added by new_packet_list_freeze() */
 //     g_object_unref(packetlist);
 
-//     packets_bar_update();
+        packets_bar_update();
 }
 
 void
@@ -288,7 +292,7 @@ PacketList::PacketList(QWidget *parent) :
     m_byteViewTab = NULL;
 }
 
-void PacketList::setProtoTree (QTreeWidget *protoTree) {
+void PacketList::setProtoTree (ProtoTree *protoTree) {
     m_protoTree = protoTree;
 }
 
@@ -301,6 +305,7 @@ PacketListModel *PacketList::packetListModel() const {
 }
 
 void PacketList::showEvent (QShowEvent *event) {
+    Q_UNUSED(event);
 //    g_log(NULL, G_LOG_LEVEL_DEBUG, "cols: %d", cfile.cinfo.num_cols);
     for (int i = 0; i < cfile.cinfo.num_cols; i++) {
         int fmt, col_width;
@@ -321,8 +326,6 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS
     QTreeView::selectionChanged(selected, deselected);
 
     if (m_protoTree) {
-        // Connect signals between the proto tree and byte views.
-
         int row = selected.first().top();
         cf_select_packet(&cfile, row);
 
@@ -330,10 +333,9 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS
             return;
         }
 
-        proto_tree_draw(cfile.edt->tree, m_protoTree);
+        m_protoTree->fillProtocolTree(cfile.edt->tree);
     }
 
-    g_log(NULL, G_LOG_LEVEL_DEBUG, "bvt: %p", m_byteViewTab);
     if (m_byteViewTab && cfile.edt) {
         GSList *src_le;
         data_source *source;
@@ -350,6 +352,7 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS
     }
 
     if (m_protoTree && m_byteViewTab) {
+        // Connect signals between the proto tree and byte views.
         connect(m_protoTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
                 m_byteViewTab, SLOT(protoTreeItemChanged(QTreeWidgetItem*)));
     }
@@ -369,7 +372,6 @@ void PacketList::clear() {
 //      * Reset the sort column, use packetlist as model in case the list is frozen.
 //      */
     cur_packet_list->sortByColumn(0, Qt::AscendingOrder);
-
 }
 
 void new_packet_list_recent_write_all(FILE *rf) {
index 5f78a86a8fd1bae7e2ae50baaebbfc01848ab784..5bd6e5fd744cb4532080a6d99527594c434dc48f 100644 (file)
@@ -25,6 +25,7 @@
 #define PACKET_LIST_H
 
 #include "packet_list_model.h"
+#include "proto_tree.h"
 #include "byte_view_tab.h"
 
 #include <QTreeView>
@@ -37,7 +38,7 @@ class PacketList : public QTreeView
 public:
     explicit PacketList(QWidget *parent = 0);
     PacketListModel *packetListModel() const;
-    void setProtoTree(QTreeWidget *protoTree);
+    void setProtoTree(ProtoTree *protoTree);
     void setByteViewTab(ByteViewTab *byteViewTab);
     void clear();
     void writeRecent(FILE *rf);
@@ -48,7 +49,7 @@ protected:
 
 private:
     PacketListModel *m_packet_list_model;
-    QTreeWidget *m_protoTree;
+    ProtoTree *m_protoTree;
     ByteViewTab *m_byteViewTab;
 
 signals:
index 74cedbeaac2fc151dcf1ee9750941a779acbb35d..4d7b5d424ec0dcbb05a13da20d3889e65412e631 100644 (file)
@@ -21,6 +21,8 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+#include <stdio.h>
+
 #include "proto_tree.h"
 #include "monospace_font.h"
 
@@ -36,17 +38,6 @@ QColor        expert_color_error      ( 0xff, 0x5c, 0x5c );        /* pale red *
 QColor        expert_color_foreground ( 0x00, 0x00, 0x00 );        /* black */
 QColor        hidden_proto_item       ( 0x44, 0x44, 0x44 );        /* gray */
 
-static void
-proto_tree_draw_node(proto_node *node, gpointer data);
-
-void proto_tree_draw(proto_tree *protocol_tree, QTreeWidget *protoTree) {
-    // Clear out previous tree
-    protoTree->clear();
-    protoTree->setFont(get_monospace_font());
-
-    proto_tree_children_foreach(protocol_tree, proto_tree_draw_node, protoTree->invisibleRootItem());
-}
-
 /* Fill a single protocol tree item with its string value and set its color. */
 static void
 proto_tree_draw_node(proto_node *node, gpointer data)
@@ -152,4 +143,76 @@ ProtoTree::ProtoTree(QWidget *parent) :
     QTreeWidget(parent)
 {
     setAccessibleName("Packet details");
+    setFont(get_monospace_font());
+
+    connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
+            this, SLOT(updateSelectionStatus(QTreeWidgetItem*)));
+}
+
+void ProtoTree::clear() {
+    updateSelectionStatus(NULL);
+    QTreeWidget::clear();
+}
+
+void ProtoTree::fillProtocolTree(proto_tree *protocol_tree) {
+    // Clear out previous tree
+    clear();
+
+    proto_tree_children_foreach(protocol_tree, proto_tree_draw_node, invisibleRootItem());
+}
+
+void ProtoTree::updateSelectionStatus(QTreeWidgetItem* item) {
+
+    if (item) {
+        field_info *fi;
+        QVariant v;
+        QString itemInfo;
+        int finfo_length;
+
+        v = item->data(0, Qt::UserRole);
+        fi = (field_info *) v.value<void *>();
+        if (!fi || !fi->hfinfo) return;
+
+        if (fi->hfinfo->blurb != NULL && fi->hfinfo->blurb[0] != '\0') {
+            itemInfo.append(QString().fromUtf8(fi->hfinfo->blurb));
+        } else {
+            itemInfo.append(QString().fromUtf8(fi->hfinfo->name));
+        }
+
+        if (!itemInfo.isEmpty()) {
+            itemInfo.append(" (" + QString().fromUtf8(fi->hfinfo->abbrev) + ")");
+
+            finfo_length = fi->length + fi->appendix_length;
+            if (finfo_length == 1) {
+                itemInfo.append(", 1 byte");
+            } else if (finfo_length > 1) {
+                itemInfo.append(QString(", %1 bytes").arg(finfo_length));
+            }
+
+            emit protoItemUnselected();
+            emit protoItemSelected(itemInfo);
+        } // else the GTK+ version pushes an empty string as described below.
+        /*
+         * Don't show anything if the field name is zero-length;
+         * the pseudo-field for "proto_tree_add_text()" is such
+         * a field, and we don't want "Text (text)" showing up
+         * on the status line if you've selected such a field.
+         *
+         * XXX - there are zero-length fields for which we *do*
+         * want to show the field name.
+         *
+         * XXX - perhaps the name and abbrev field should be null
+         * pointers rather than null strings for that pseudo-field,
+         * but we'd have to add checks for null pointers in some
+         * places if we did that.
+         *
+         * Or perhaps protocol tree items added with
+         * "proto_tree_add_text()" should have -1 as the field index,
+         * with no pseudo-field being used, but that might also
+         * require special checks for -1 to be added.
+         */
+
+    } else {
+        emit protoItemUnselected();
+    }
 }
index 7afd278df9052dbdae55dd54e59a74f3ddbcfdfe..64fb8d3cd9ea0dca61c14990838e2de7d85dbffd 100644 (file)
 
 #include <QTreeWidget>
 
-void proto_tree_draw(proto_tree *protocol_tree, QTreeWidget *protoTree);
 
 class ProtoTree : public QTreeWidget
 {
     Q_OBJECT
 public:
     explicit ProtoTree(QWidget *parent = 0);
+    void fillProtocolTree(proto_tree *protocol_tree);
+    void clear();
+
+private:
 
 signals:
+    void protoItemSelected(QString &);
+    void protoItemUnselected();
 
 public slots:
+    void updateSelectionStatus(QTreeWidgetItem*);
 
 };
 
index 2918a4d20fc2a2f7ac296aaaf15cac5693b0b65c..b2b0981f0ee5757afc68d79c52f78edeac3279a7 100644 (file)
@@ -31,6 +31,8 @@
 
 #include "qt_ui_utils.h"
 
+#include "file.h"
+#include "log.h"
 #include "recent_file_status.h"
 
 #include <QDir>
@@ -176,6 +178,55 @@ void WiresharkApplication::refreshRecentFiles(void) {
     }
 }
 
+void WiresharkApplication::captureFileCallback(int event, void * data)
+{
+    capture_file *cf = (capture_file *) data;
+
+    switch(event) {
+
+    case(cf_cb_file_closing):
+        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
+        emit captureFileClosing(cf);
+        break;
+    case(cf_cb_file_closed):
+        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
+        emit captureFileClosed(cf);
+        break;
+    case(cf_cb_file_read_started):
+        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
+        emit captureFileReadStarted(cf);
+        break;
+    case(cf_cb_file_read_finished):
+        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
+        emit captureFileReadFinished(cf);
+        break;
+
+    case(cf_cb_packet_selected):
+    case(cf_cb_packet_unselected):
+    case(cf_cb_field_unselected):
+        // Pure signals and slots
+        break;
+
+//    case(cf_cb_file_save_started): // data = string
+//        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
+//        break;
+//    case(cf_cb_file_save_finished):
+//        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
+//        break;
+//    case(cf_cb_file_save_reload_finished):
+//        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
+//        main_cf_cb_file_save_reload_finished(data);
+//        break;
+//    case(cf_cb_file_save_failed):
+//        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
+//        break;
+    default:
+        g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: main_cf_callback %d %p", event, data);
+//        g_warning("main_cf_callback: event %u unknown", event);
+//        g_assert_not_reached();
+    }
+}
+
 void WiresharkApplication::clearRecentItems() {
     recent_item_status *ri;
 
index f4601076c9af33210cab751c3cb766a446d2deaf..25cf33ea54f1e898db15c121e92a284e239c92e4 100644 (file)
 #ifndef WIRESHARK_APPLICATION_H
 #define WIRESHARK_APPLICATION_H
 
+#include "config.h"
+
+#include <glib.h>
+
+#include "file.h"
+
 #include <QApplication>
 #include <QList>
 #include <QFileInfo>
@@ -49,6 +55,7 @@ public:
     explicit WiresharkApplication(int &argc,  char **argv);
     QList<recent_item_status *> recent_item_list() const;
     void addRecentItem(const QString &filename, qint64 size, bool accessible);
+    void captureFileCallback(int event, void * data);
 
 private:
     QTimer *recentTimer;
@@ -56,6 +63,11 @@ private:
 signals:
     void updateRecentItemStatus(const QString &filename, qint64 size, bool accessible);
 
+    void captureFileReadStarted(const capture_file *cf);
+    void captureFileReadFinished(const capture_file *cf);
+    void captureFileClosing(const capture_file *cf);
+    void captureFileClosed(const capture_file *cf);
+
 public slots:
     void clearRecentItems();