aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ui/gtk/packet_list.c2
-rw-r--r--ui/gtk/prefs_column.c58
-rw-r--r--ui/gtk/prefs_column.h16
-rw-r--r--ui/preference_utils.c57
-rw-r--r--ui/preference_utils.h22
-rw-r--r--ui/qt/CMakeLists.txt3
-rw-r--r--ui/qt/Makefile.am2
-rw-r--r--ui/qt/Makefile.common4
-rw-r--r--ui/qt/QtShark.pro9
-rw-r--r--ui/qt/column_preferences_frame.cpp440
-rw-r--r--ui/qt/column_preferences_frame.h76
-rw-r--r--ui/qt/column_preferences_frame.ui94
-rw-r--r--ui/qt/main_window.cpp2
-rw-r--r--ui/qt/main_window.h1
-rw-r--r--ui/qt/main_window_slots.cpp20
-rw-r--r--ui/qt/preferences_dialog.cpp6
-rw-r--r--ui/qt/preferences_dialog.ui11
-rw-r--r--ui/qt/wireshark_application.cpp3
-rw-r--r--ui/qt/wireshark_application.h2
19 files changed, 747 insertions, 81 deletions
diff --git a/ui/gtk/packet_list.c b/ui/gtk/packet_list.c
index 45bd85af89..477c2b55ac 100644
--- a/ui/gtk/packet_list.c
+++ b/ui/gtk/packet_list.c
@@ -597,7 +597,7 @@ packet_list_set_all_columns_visible (void)
static void
packet_list_remove_column (gint col_id, GtkTreeViewColumn *col _U_)
{
- column_prefs_remove(col_id);
+ column_prefs_remove_nth(col_id);
if (!prefs.gui_use_pref_save) {
prefs_main_write();
diff --git a/ui/gtk/prefs_column.c b/ui/gtk/prefs_column.c
index 3c2b868f29..3e0504b133 100644
--- a/ui/gtk/prefs_column.c
+++ b/ui/gtk/prefs_column.c
@@ -33,7 +33,9 @@
#include <epan/column.h>
#include <epan/strutil.h>
-#include "../globals.h"
+#include "globals.h"
+
+#include "ui/preference_utils.h"
#include "ui/gtk/prefs_column.h"
#include "ui/gtk/gtkglobals.h"
@@ -333,52 +335,6 @@ column_prefs_show(GtkWidget *prefs_window) {
return(main_vb);
}
-void
-column_prefs_add_custom(gint fmt, const gchar *title, const gchar *custom_field, gint custom_occurrence)
-{
- GList *clp;
- fmt_data *cfmt, *last_cfmt;
-
- cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
- /*
- * Because a single underscore is interpreted as a signal that the next character
- * is going to be marked as accelerator for this header (i.e. is going to be
- * shown underlined), escape it be inserting a second consecutive underscore.
- */
- cfmt->title = g_strdup(title);
- cfmt->fmt = fmt;
- cfmt->custom_field = g_strdup(custom_field);
- cfmt->custom_occurrence = custom_occurrence;
- cfmt->resolved = TRUE;
-
- if (custom_field) {
- cfmt->visible = TRUE;
- clp = g_list_last(prefs.col_list);
- last_cfmt = (fmt_data *) clp->data;
- if (last_cfmt->fmt == COL_INFO) {
- /* Last column is COL_INFO, add custom column before this */
- prefs.col_list = g_list_insert(prefs.col_list, cfmt, g_list_length(prefs.col_list)-1);
- } else {
- prefs.col_list = g_list_append(prefs.col_list, cfmt);
- }
- } else {
- cfmt->visible = FALSE; /* Will be set to TRUE in visible_toggled() when added to list */
- prefs.col_list = g_list_append(prefs.col_list, cfmt);
- }
-}
-
-void
-column_prefs_remove(gint col)
-{
- GList *clp = g_list_nth(prefs.col_list, col);
- fmt_data *cfmt = (fmt_data *) clp->data;
-
- g_free(cfmt->title);
- g_free(cfmt->custom_field);
- g_free(cfmt);
- prefs.col_list = g_list_remove_link(prefs.col_list, clp);
-}
-
/* To do: add input checking to each of these callbacks */
static void
@@ -424,7 +380,6 @@ static void
column_list_delete_cb(GtkWidget *w _U_, gpointer data) {
GtkTreeView *column_l = GTK_TREE_VIEW(data);
GList *clp;
- fmt_data *cfmt;
GtkTreeSelection *sel;
GtkTreeModel *model;
GtkTreeIter iter;
@@ -434,12 +389,7 @@ column_list_delete_cb(GtkWidget *w _U_, gpointer data) {
if (gtk_tree_selection_get_selected(sel, &model, &iter))
{
gtk_tree_model_get(model, &iter, DATA_COLUMN, &clp, -1);
-
- cfmt = (fmt_data *) clp->data;
- g_free(cfmt->title);
- g_free(cfmt->custom_field);
- g_free(cfmt);
- prefs.col_list = g_list_remove_link(prefs.col_list, clp);
+ column_prefs_remove_link(clp);
/* Change the row selection to the next row (if available) or */
/* the previous row (if available). If there's only one row */
diff --git a/ui/gtk/prefs_column.h b/ui/gtk/prefs_column.h
index ac19239cc6..7011463a8e 100644
--- a/ui/gtk/prefs_column.h
+++ b/ui/gtk/prefs_column.h
@@ -55,20 +55,4 @@ void column_prefs_apply(GtkWidget *widget);
*/
void column_prefs_destroy(GtkWidget *widget);
-/** Add a custom column.
- *
- * @param fmt column format
- * @param title column title
- * @param custom_field column custom field
- */
-void column_prefs_add_custom(gint fmt, const gchar *title,
- const gchar *custom_field,
- gint custom_occurrence);
-
-/** Remove a column.
- *
- * @param col column id
- */
-void column_prefs_remove(gint col);
-
#endif
diff --git a/ui/preference_utils.c b/ui/preference_utils.c
index 2896ac3d2c..29e403f5f8 100644
--- a/ui/preference_utils.c
+++ b/ui/preference_utils.c
@@ -28,6 +28,8 @@
#include <glib.h>
+#include <epan/column_info.h>
+#include <epan/column.h>
#include <epan/filesystem.h>
#include <epan/prefs.h>
#include <epan/prefs-int.h>
@@ -271,6 +273,61 @@ prefs_main_write(void)
}
}
+void
+column_prefs_add_custom(gint fmt, const gchar *title, const gchar *custom_field, gint custom_occurrence)
+{
+ GList *clp;
+ fmt_data *cfmt, *last_cfmt;
+
+ cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
+ /*
+ * Because a single underscore is interpreted as a signal that the next character
+ * is going to be marked as accelerator for this header (i.e. is going to be
+ * shown underlined), escape it be inserting a second consecutive underscore.
+ */
+ cfmt->title = g_strdup(title);
+ cfmt->fmt = fmt;
+ cfmt->custom_field = g_strdup(custom_field);
+ cfmt->custom_occurrence = custom_occurrence;
+ cfmt->resolved = TRUE;
+
+ if (custom_field) {
+ cfmt->visible = TRUE;
+ clp = g_list_last(prefs.col_list);
+ last_cfmt = (fmt_data *) clp->data;
+ if (last_cfmt->fmt == COL_INFO) {
+ /* Last column is COL_INFO, add custom column before this */
+ prefs.col_list = g_list_insert(prefs.col_list, cfmt, g_list_length(prefs.col_list)-1);
+ } else {
+ prefs.col_list = g_list_append(prefs.col_list, cfmt);
+ }
+ } else {
+ cfmt->visible = FALSE; /* Will be set to TRUE in visible_toggled() when added to list */
+ prefs.col_list = g_list_append(prefs.col_list, cfmt);
+ }
+}
+
+void
+column_prefs_remove_link(GList *col_link)
+{
+ fmt_data *cfmt;
+
+ if (!col_link || !col_link->data) return;
+
+ cfmt = (fmt_data *) col_link->data;
+
+ g_free(cfmt->title);
+ g_free(cfmt->custom_field);
+ g_free(cfmt);
+ prefs.col_list = g_list_remove_link(prefs.col_list, col_link);
+}
+
+void
+column_prefs_remove_nth(gint col)
+{
+ column_prefs_remove_link(g_list_nth(prefs.col_list, col));
+}
+
/*
* Editor modelines
*
diff --git a/ui/preference_utils.h b/ui/preference_utils.h
index c135b1d305..59639eb9ca 100644
--- a/ui/preference_utils.h
+++ b/ui/preference_utils.h
@@ -80,6 +80,28 @@ extern void prefs_to_capture_opts(void);
*/
extern void prefs_main_write(void);
+/** Add a custom column.
+ *
+ * @param fmt column format
+ * @param title column title
+ * @param custom_field column custom field
+ */
+void column_prefs_add_custom(gint fmt, const gchar *title,
+ const gchar *custom_field,
+ gint custom_occurrence);
+
+/** Remove a column.
+ *
+ * @param col_link Column list entry
+ */
+void column_prefs_remove_link(GList* col_link);
+
+/** Remove a column.
+ *
+ * @param col Column number
+ */
+void column_prefs_remove_nth(gint col);
+
#ifdef __cplusplus
}
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt
index 950669e897..a62402853d 100644
--- a/ui/qt/CMakeLists.txt
+++ b/ui/qt/CMakeLists.txt
@@ -32,6 +32,7 @@ set(QTSHARK_H_SRC
capture_interface_dialog.h
color_dialog.h
color_utils.h
+ column_preferences_frame.h
display_filter_combo.h
display_filter_edit.h
export_dissection_dialog.h
@@ -79,6 +80,7 @@ set(QTSHARK_CPP_SRC
capture_interface_dialog.cpp
color_dialog.cpp
color_utils.cpp
+ column_preferences_frame.cpp
display_filter_combo.cpp
display_filter_edit.cpp
export_dissection_dialog.cpp
@@ -122,6 +124,7 @@ set(QTSHARK_SRC
)
set(QTSHARK_UI
+ column_preferences_frame.ui
export_object_dialog.ui
file_set_dialog.ui
import_text_dialog.ui
diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am
index 69bcef7845..23fbf5881c 100644
--- a/ui/qt/Makefile.am
+++ b/ui/qt/Makefile.am
@@ -83,6 +83,8 @@ ui_%.h: %.ui
#moc_%.cpp: %.h
# moc $< -o $@
+column_preferences_frame.cpp column_preferences_frame.h: ui_column_preferences_frame.h
+
export_object_dialog.cpp export_object_dialog.h: ui_export_object_dialog.h
file_set_dialog.cpp file_set_dialog.h: ui_file_set_dialog.h
diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common
index af327f4849..92cc573e61 100644
--- a/ui/qt/Makefile.common
+++ b/ui/qt/Makefile.common
@@ -31,6 +31,7 @@ GENERATED_HEADER_FILES =
# Generated header files that we don't want in the distribution.
GENERATED_NODIST_HEADER_FILES = \
+ ui_column_preferences_frame.h \
ui_export_object_dialog.h \
ui_file_set_dialog.h \
ui_import_text_dialog.h \
@@ -89,6 +90,7 @@ MOC_HDRS = \
capture_interface_dialog.h \
color_dialog.h \
color_utils.h \
+ column_preferences_frame.h \
display_filter_combo.h \
display_filter_edit.h \
export_dissection_dialog.h \
@@ -127,6 +129,7 @@ MOC_HDRS = \
# .ui files.
#
UI_FILES = \
+ column_preferences_frame.ui \
export_object_dialog.ui \
file_set_dialog.ui \
import_text_dialog.ui \
@@ -196,6 +199,7 @@ WIRESHARK_QT_SRC = \
capture_interface_dialog.cpp \
color_dialog.cpp \
color_utils.cpp \
+ column_preferences_frame.cpp \
display_filter_combo.cpp \
display_filter_edit.cpp \
export_dissection_dialog.cpp \
diff --git a/ui/qt/QtShark.pro b/ui/qt/QtShark.pro
index 03a3ccd68d..73faee8fa2 100644
--- a/ui/qt/QtShark.pro
+++ b/ui/qt/QtShark.pro
@@ -195,7 +195,8 @@ FORMS += main_window.ui \
profile_dialog.ui \
preferences_dialog.ui \
main_window_preferences_frame.ui \
- layout_preferences_frame.ui
+ layout_preferences_frame.ui \
+ column_preferences_frame.ui
win32 { ## These should be in config.pri ??
!isEmpty(PORTAUDIO_DIR) {
@@ -231,7 +232,8 @@ HEADERS += $$HEADERS_WS_C \
profile_dialog.h \
preferences_dialog.h \
main_window_preferences_frame.h \
- layout_preferences_frame.h
+ layout_preferences_frame.h \
+ column_preferences_frame.h
win32 {
OBJECTS_WS_C = $$SOURCES_WS_C
@@ -453,4 +455,5 @@ SOURCES += \
profile_dialog.cpp \
preferences_dialog.cpp \
main_window_preferences_frame.cpp \
- layout_preferences_frame.cpp
+ layout_preferences_frame.cpp \
+ column_preferences_frame.cpp
diff --git a/ui/qt/column_preferences_frame.cpp b/ui/qt/column_preferences_frame.cpp
new file mode 100644
index 0000000000..ebfdbdce30
--- /dev/null
+++ b/ui/qt/column_preferences_frame.cpp
@@ -0,0 +1,440 @@
+/* column_preferences_frame.cpp
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include "color.h"
+#include "packet-range.h"
+
+#include <epan/column_info.h>
+#include <epan/column.h>
+#include <epan/prefs.h>
+#include <epan/proto.h>
+
+#include <ui/preference_utils.h>
+
+#include "column_preferences_frame.h"
+#include "ui_column_preferences_frame.h"
+#include "syntax_line_edit.h"
+#include "wireshark_application.h"
+
+#include <QTreeWidgetItemIterator>
+#include <QLineEdit>
+#include <QKeyEvent>
+
+#include <QDebug>
+
+const int visible_col_ = 0;
+const int title_col_ = 1;
+const int type_col_ = 2;
+const int custom_field_col_ = 3;
+const int custom_occurrence_col_ = 4;
+
+ColumnPreferencesFrame::ColumnPreferencesFrame(QWidget *parent) :
+ QFrame(parent),
+ ui(new Ui::ColumnPreferencesFrame),
+ cur_line_edit_(NULL),
+ cur_combo_box_(NULL)
+{
+ ui->setupUi(this);
+
+ int one_em = ui->columnTreeWidget->fontMetrics().height();
+ ui->columnTreeWidget->setColumnWidth(3, one_em * 10);
+ ui->columnTreeWidget->setColumnWidth(4, one_em * 5);
+
+ ui->columnTreeWidget->setMinimumWidth(one_em * 20);
+ ui->columnTreeWidget->setMinimumHeight(one_em * 12);
+
+ ui->columnTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
+ ui->columnTreeWidget->setDragEnabled(true);
+ ui->columnTreeWidget->viewport()->setAcceptDrops(true);
+ ui->columnTreeWidget->setDropIndicatorShown(true);
+ ui->columnTreeWidget->setDragDropMode(QAbstractItemView::InternalMove);
+
+ updateWidgets();
+}
+
+ColumnPreferencesFrame::~ColumnPreferencesFrame()
+{
+ delete ui;
+}
+
+void ColumnPreferencesFrame::unstash()
+{
+ GList *new_col_list = NULL;
+ bool changed = false;
+
+ QTreeWidgetItemIterator it(ui->columnTreeWidget);
+ while (*it) {
+ fmt_data *cfmt = g_new0(fmt_data, 1);
+ cfmt->visible = (*it)->checkState(visible_col_) == Qt::Checked ? TRUE : FALSE;
+ cfmt->title = g_strdup((*it)->text(title_col_).toUtf8().constData());
+ cfmt->fmt = (*it)->data(type_col_, Qt::UserRole).value<int>();
+ if (cfmt->fmt == COL_CUSTOM) {
+ bool ok;
+ int occurrence = (*it)->text(custom_occurrence_col_).toInt(&ok);
+ cfmt->custom_field = g_strdup((*it)->text(custom_field_col_).toUtf8().constData());
+ cfmt->custom_occurrence = ok ? occurrence : 0;
+ }
+
+ if (prefs.col_list == NULL) {
+ changed = true;
+ } else {
+ fmt_data *old_cfmt = (fmt_data *) prefs.col_list->data;
+ if (!old_cfmt ||
+ g_strcmp0(old_cfmt->title, cfmt->title) != 0 ||
+ old_cfmt->fmt != cfmt->fmt ||
+ old_cfmt->visible != cfmt->visible ||
+ (old_cfmt->fmt == COL_CUSTOM && (
+ g_strcmp0(old_cfmt->custom_field, cfmt->custom_field) != 0 ||
+ old_cfmt->custom_occurrence != cfmt->custom_occurrence))) {
+ changed = true;
+ }
+ column_prefs_remove_link(prefs.col_list);
+ }
+
+ new_col_list = g_list_append(new_col_list, cfmt);
+ ++it;
+ }
+
+ while (prefs.col_list) {
+ changed = true;
+ column_prefs_remove_link(prefs.col_list);
+ }
+ prefs.col_list = new_col_list;
+
+ if (changed) {
+ wsApp->emitAppSignal(WiresharkApplication::ColumnsChanged);
+ }
+}
+
+void ColumnPreferencesFrame::showEvent(QShowEvent *evt)
+{
+ Q_UNUSED(evt);
+}
+
+void ColumnPreferencesFrame::keyPressEvent(QKeyEvent *evt)
+{
+ if (cur_line_edit_ && cur_line_edit_->hasFocus()) {
+ int new_idx = COL_CUSTOM;
+ switch (evt->key()) {
+ case Qt::Key_Escape:
+ cur_line_edit_->setText(saved_col_string_);
+ new_idx = saved_combo_idx_;
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ switch (cur_column_) {
+ case title_col_:
+ columnTitleEditingFinished();
+ break;
+ case custom_field_col_:
+ customFieldEditingFinished();
+ columnTypeCurrentIndexChanged(new_idx);
+ break;
+ case custom_occurrence_col_:
+ customOccurrenceEditingFinished();
+ columnTypeCurrentIndexChanged(new_idx);
+ break;
+ default:
+ break;
+ }
+
+ delete cur_line_edit_;
+ return;
+ default:
+ break;
+ }
+ } else if (cur_combo_box_ && cur_combo_box_->hasFocus()) {
+ switch (evt->key()) {
+ case Qt::Key_Escape:
+ cur_combo_box_->setCurrentIndex(saved_combo_idx_);
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ // XXX The combo box eats enter and return
+ columnTypeCurrentIndexChanged(cur_combo_box_->currentIndex());
+ delete cur_combo_box_;
+ return;
+ default:
+ break;
+ }
+ }
+ QFrame::keyPressEvent(evt);
+}
+
+void ColumnPreferencesFrame::addColumn(bool visible, const char *title, int fmt, const char *custom_field, int custom_occurrence)
+{
+ QTreeWidgetItem *item = new QTreeWidgetItem(ui->columnTreeWidget);
+
+ item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
+ item->setFlags(item->flags() & ~(Qt::ItemIsDropEnabled));
+ item->setCheckState(visible_col_, visible ? Qt::Checked : Qt::Unchecked);
+ item->setText(title_col_, title);
+ item->setText(type_col_, col_format_desc(fmt));
+ item->setData(type_col_, Qt::UserRole, QVariant(fmt));
+ if (fmt == COL_CUSTOM) {
+ item->setText(custom_field_col_, custom_field);
+ item->setText(custom_occurrence_col_, QString::number(custom_occurrence));
+ }
+}
+
+void ColumnPreferencesFrame::updateWidgets()
+{
+ ui->columnTreeWidget->clear();
+
+ for (GList *cur = g_list_first(prefs.col_list); cur != NULL && cur->data != NULL; cur = cur->next) {
+ fmt_data *cfmt = (fmt_data *) cur->data;
+ addColumn(cfmt->visible, cfmt->title, cfmt->fmt, cfmt->custom_field, cfmt->custom_occurrence);
+ }
+
+ ui->columnTreeWidget->resizeColumnToContents(visible_col_);
+ ui->columnTreeWidget->resizeColumnToContents(title_col_);
+ ui->columnTreeWidget->resizeColumnToContents(type_col_);
+}
+
+
+void ColumnPreferencesFrame::on_columnTreeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
+{
+ ui->deleteToolButton->setEnabled(current ? true : false);
+
+ if (previous && ui->columnTreeWidget->itemWidget(previous, title_col_)) {
+ ui->columnTreeWidget->removeItemWidget(previous, title_col_);
+ }
+ if (previous && ui->columnTreeWidget->itemWidget(previous, type_col_)) {
+ ui->columnTreeWidget->removeItemWidget(previous, type_col_);
+ previous->setText(type_col_, col_format_desc(previous->data(type_col_, Qt::UserRole).toInt()));
+ }
+ if (previous && ui->columnTreeWidget->itemWidget(previous, custom_field_col_)) {
+ ui->columnTreeWidget->removeItemWidget(previous, custom_field_col_);
+ }
+ if (previous && ui->columnTreeWidget->itemWidget(previous, custom_occurrence_col_)) {
+ ui->columnTreeWidget->removeItemWidget(previous, custom_occurrence_col_);
+ }
+}
+
+void ColumnPreferencesFrame::on_columnTreeWidget_itemActivated(QTreeWidgetItem *item, int column)
+{
+ if (!item || cur_line_edit_ || cur_combo_box_) return;
+
+ QWidget *editor = NULL;
+ cur_column_ = column;
+ saved_combo_idx_ = item->data(type_col_, Qt::UserRole).toInt();
+
+ switch (column) {
+ case title_col_:
+ {
+ cur_line_edit_ = new QLineEdit();
+ cur_column_ = column;
+ saved_col_string_ = item->text(title_col_);
+ connect(cur_line_edit_, SIGNAL(editingFinished()), this, SLOT(columnTitleEditingFinished()));
+ editor = cur_line_edit_;
+ break;
+ }
+ case type_col_:
+ {
+ cur_combo_box_ = new QComboBox();
+ for (int i = 0; i < NUM_COL_FMTS; i++) {
+ cur_combo_box_->addItem(col_format_desc(i), QVariant(i));
+ if (i == saved_combo_idx_) {
+ cur_combo_box_->setCurrentIndex(i);
+ }
+ }
+ connect(cur_combo_box_, SIGNAL(currentIndexChanged(int)), this, SLOT(columnTypeCurrentIndexChanged(int)));
+ editor = cur_combo_box_;
+ break;
+ }
+ case custom_field_col_:
+ {
+ SyntaxLineEdit *syntax_edit = new SyntaxLineEdit();
+ saved_col_string_ = item->text(custom_field_col_);
+ connect(syntax_edit, SIGNAL(textChanged(QString)),
+ this, SLOT(customFieldTextChanged(QString)));
+ connect(syntax_edit, SIGNAL(editingFinished()), this, SLOT(customFieldEditingFinished()));
+ editor = cur_line_edit_ = syntax_edit;
+
+ saved_combo_idx_ = item->data(type_col_, Qt::UserRole).toInt();
+ item->setText(type_col_, col_format_desc(COL_CUSTOM));
+ item->setData(type_col_, Qt::UserRole, QVariant(COL_CUSTOM));
+ break;
+ }
+ case custom_occurrence_col_:
+ {
+ SyntaxLineEdit *syntax_edit = new SyntaxLineEdit();
+ saved_col_string_ = item->text(custom_occurrence_col_);
+ connect(syntax_edit, SIGNAL(textChanged(QString)),
+ this, SLOT(customOccurrenceTextChanged(QString)));
+ connect(syntax_edit, SIGNAL(editingFinished()), this, SLOT(customOccurrenceEditingFinished()));
+ editor = cur_line_edit_ = syntax_edit;
+
+ saved_combo_idx_ = item->data(type_col_, Qt::UserRole).toInt();
+ item->setText(type_col_, col_format_desc(COL_CUSTOM));
+ item->setData(type_col_, Qt::UserRole, QVariant(COL_CUSTOM));
+ break;
+ }
+ default:
+ return;
+ }
+
+ if (cur_line_edit_) {
+ cur_line_edit_->setText(saved_col_string_);
+ cur_line_edit_->selectAll();
+ connect(cur_line_edit_, SIGNAL(destroyed()), this, SLOT(lineEditDestroyed()));
+ }
+ if (cur_combo_box_) {
+ connect(cur_combo_box_, SIGNAL(destroyed()), this, SLOT(comboDestroyed()));
+ }
+ if (editor) {
+ QFrame *edit_frame = new QFrame();
+ QHBoxLayout *hb = new QHBoxLayout();
+ QSpacerItem *spacer = new QSpacerItem(5, 10);
+
+ hb->addWidget(editor, 0);
+ hb->addSpacerItem(spacer);
+ hb->setStretch(1, 1);
+ hb->setContentsMargins(0, 0, 0, 0);
+
+ edit_frame->setLineWidth(0);
+ edit_frame->setFrameStyle(QFrame::NoFrame);
+ // The documentation suggests setting autoFillbackground. That looks silly
+ // so we clear the item text instead.
+ item->setText(cur_column_, "");
+ edit_frame->setLayout(hb);
+ ui->columnTreeWidget->setItemWidget(item, cur_column_, edit_frame);
+ editor->setFocus();
+ }
+}
+
+void ColumnPreferencesFrame::lineEditDestroyed()
+{
+ cur_line_edit_ = NULL;
+}
+
+void ColumnPreferencesFrame::comboDestroyed()
+{
+ cur_combo_box_ = NULL;
+}
+
+void ColumnPreferencesFrame::columnTitleEditingFinished()
+{
+ QTreeWidgetItem *item = ui->columnTreeWidget->currentItem();
+ if (!cur_line_edit_ || !item) return;
+
+ item->setText(title_col_, cur_line_edit_->text());
+ ui->columnTreeWidget->removeItemWidget(item, title_col_);
+}
+
+void ColumnPreferencesFrame::columnTypeCurrentIndexChanged(int index)
+{
+ QTreeWidgetItem *item = ui->columnTreeWidget->currentItem();
+ if (!item || index < 0) return;
+
+ item->setData(type_col_, Qt::UserRole, QVariant(index));
+ item->setText(type_col_, col_format_desc(index));
+
+ if (index != COL_CUSTOM) {
+ item->setText(custom_field_col_, "");
+ item->setText(custom_occurrence_col_, "");
+ }
+}
+
+void ColumnPreferencesFrame::customFieldTextChanged(QString)
+{
+ SyntaxLineEdit *syntax_edit = qobject_cast<SyntaxLineEdit *>(cur_line_edit_);
+ QTreeWidgetItem *item = ui->columnTreeWidget->currentItem();
+ if (!syntax_edit || !item) return;
+
+ dfilter_t *dfp = NULL;
+ const char *field_text = syntax_edit->text().toUtf8().constData();
+ if (strlen(field_text) < 1) {
+ syntax_edit->setSyntaxState(SyntaxLineEdit::Empty);
+ } else if (proto_check_field_name(field_text) != 0 || !dfilter_compile(field_text, &dfp)) {
+ syntax_edit->setSyntaxState(SyntaxLineEdit::Invalid);
+ } else {
+ syntax_edit->setSyntaxState(SyntaxLineEdit::Valid);
+ }
+ dfilter_free(dfp);
+}
+
+void ColumnPreferencesFrame::customFieldEditingFinished()
+{
+ QTreeWidgetItem *item = ui->columnTreeWidget->currentItem();
+ if (!cur_line_edit_ || !item) return;
+
+ item->setText(custom_field_col_, cur_line_edit_->text());
+ ui->columnTreeWidget->removeItemWidget(item, custom_field_col_);
+}
+
+void ColumnPreferencesFrame::customOccurrenceTextChanged(QString)
+{
+ SyntaxLineEdit *syntax_edit = qobject_cast<SyntaxLineEdit *>(cur_line_edit_);
+ QTreeWidgetItem *item = ui->columnTreeWidget->currentItem();
+ if (!syntax_edit || !item) return;
+
+ if (syntax_edit->text().isEmpty()) {
+ syntax_edit->setSyntaxState(SyntaxLineEdit::Empty);
+ } else {
+ bool ok;
+ syntax_edit->text().toInt(&ok);
+ if (ok) {
+ syntax_edit->setSyntaxState(SyntaxLineEdit::Valid);
+ } else {
+ syntax_edit->setSyntaxState(SyntaxLineEdit::Invalid);
+ }
+ }
+}
+
+void ColumnPreferencesFrame::customOccurrenceEditingFinished()
+{
+ QTreeWidgetItem *item = ui->columnTreeWidget->currentItem();
+ if (!cur_line_edit_ || !item) return;
+
+ item->setText(custom_occurrence_col_, cur_line_edit_->text());
+ ui->columnTreeWidget->removeItemWidget(item, custom_occurrence_col_);
+}
+
+void ColumnPreferencesFrame::on_newToolButton_clicked()
+{
+ addColumn(true, "New Column", COL_NUMBER, NULL, 0);
+}
+
+void ColumnPreferencesFrame::on_deleteToolButton_clicked()
+{
+ QTreeWidgetItem *item = ui->columnTreeWidget->currentItem();
+ if (item) {
+ ui->columnTreeWidget->invisibleRootItem()->removeChild(item);
+ }
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/qt/column_preferences_frame.h b/ui/qt/column_preferences_frame.h
new file mode 100644
index 0000000000..3eabae0cc4
--- /dev/null
+++ b/ui/qt/column_preferences_frame.h
@@ -0,0 +1,76 @@
+/* column_preferences_frame.h
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef COLUMN_PREFERENCES_FRAME_H
+#define COLUMN_PREFERENCES_FRAME_H
+
+#include <QFrame>
+#include <QComboBox>
+#include <QTreeWidgetItem>
+
+namespace Ui {
+class ColumnPreferencesFrame;
+}
+
+class ColumnPreferencesFrame : public QFrame
+{
+ Q_OBJECT
+
+public:
+ explicit ColumnPreferencesFrame(QWidget *parent = 0);
+ ~ColumnPreferencesFrame();
+
+ void unstash();
+
+protected:
+ void showEvent(QShowEvent *evt);
+ void keyPressEvent(QKeyEvent *evt);
+
+private:
+ Ui::ColumnPreferencesFrame *ui;
+
+ int cur_column_;
+ QLineEdit *cur_line_edit_;
+ QString saved_col_string_;
+ QComboBox *cur_combo_box_;
+ int saved_combo_idx_;
+
+ void addColumn(bool visible, const char *title, int fmt, const char *custom_field, int custom_occurrence);
+ void updateWidgets(void);
+
+private slots:
+ void on_columnTreeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
+ void on_columnTreeWidget_itemActivated(QTreeWidgetItem *item, int column);
+ void lineEditDestroyed();
+ void comboDestroyed();
+ void columnTitleEditingFinished();
+ void columnTypeCurrentIndexChanged(int index);
+ void customFieldTextChanged(QString);
+ void customFieldEditingFinished();
+ void customOccurrenceTextChanged(QString);
+ void customOccurrenceEditingFinished();
+ void on_newToolButton_clicked();
+ void on_deleteToolButton_clicked();
+};
+
+#endif // COLUMN_PREFERENCES_FRAME_H
diff --git a/ui/qt/column_preferences_frame.ui b/ui/qt/column_preferences_frame.ui
new file mode 100644
index 0000000000..195ae004ef
--- /dev/null
+++ b/ui/qt/column_preferences_frame.ui
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ColumnPreferencesFrame</class>
+ <widget class="QFrame" name="ColumnPreferencesFrame">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>550</width>
+ <height>350</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Frame</string>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTreeWidget" name="columnTreeWidget">
+ <column>
+ <property name="text">
+ <string>Displayed</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Title</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Type</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Field name</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Field occurence</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QToolButton" name="newToolButton">
+ <property name="icon">
+ <iconset resource="../../image/toolbar.qrc">
+ <normaloff>:/stock/plus-8.png</normaloff>:/stock/plus-8.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="deleteToolButton">
+ <property name="icon">
+ <iconset resource="../../image/toolbar.qrc">
+ <normaloff>:/stock/minus-8.png</normaloff>:/stock/minus-8.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../image/toolbar.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index d0aa9993ba..70d3510f1c 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -191,6 +191,8 @@ MainWindow::MainWindow(QWidget *parent) :
this, SLOT(captureFileClosing(const capture_file*)));
connect(wsApp, SIGNAL(captureFileClosed(const capture_file*)),
this, SLOT(captureFileClosed(const capture_file*)));
+ connect(wsApp, SIGNAL(columnsChanged()),
+ this, SLOT(recreatePacketList()));
connect(wsApp, SIGNAL(packetDissectionChanged()),
this, SLOT(redissectPackets()));
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index 81a4552a97..0ee395204a 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -174,6 +174,7 @@ private slots:
void setMenusForSelectedTreeRow(field_info *fi = NULL);
void interfaceSelectionChanged();
void redissectPackets();
+ void recreatePacketList();
// We should probably move these to main_window_actions.cpp similar to
// gtk/main_menubar.c
diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp
index 1094f37a30..a032901cba 100644
--- a/ui/qt/main_window_slots.cpp
+++ b/ui/qt/main_window_slots.cpp
@@ -52,6 +52,8 @@
#include "wsutil/file_util.h"
+#include "epan/column.h"
+
#include "ui/alert_box.h"
#include "ui/capture_globals.h"
#include "ui/help_url.h"
@@ -357,8 +359,7 @@ void MainWindow::configurationProfileChanged(const gchar *profile_name) {
// welcome_if_panel_reload();
/* Recreate the packet list according to new preferences */
-// packet_list_recreate ();
- if (cap_file_) cap_file_->columns_changed = FALSE; /* Reset value */
+ recreatePacketList();
/* Reload pane geometry, must be done after recreating the list */
// main_pane_load_window_geometry();
@@ -922,6 +923,21 @@ void MainWindow::redissectPackets()
main_ui_->statusBar->expertUpdate();
}
+void MainWindow::recreatePacketList()
+{
+ if (!cap_file_) return;
+
+ prefs.num_cols = g_list_length(prefs.col_list);
+
+ col_cleanup(&cap_file_->cinfo);
+ build_column_format_array(&cap_file_->cinfo, prefs.num_cols, FALSE);
+
+ packet_list_->hide();
+ packet_list_->show();
+
+ cap_file_->columns_changed = FALSE; /* Reset value */
+}
+
// File Menu
void MainWindow::on_actionFileOpen_triggered()
diff --git a/ui/qt/preferences_dialog.cpp b/ui/qt/preferences_dialog.cpp
index 4c12ff52c4..9121aedae2 100644
--- a/ui/qt/preferences_dialog.cpp
+++ b/ui/qt/preferences_dialog.cpp
@@ -160,7 +160,6 @@ module_prefs_clean_stash(module_t *module, gpointer unused)
// Preference tree items
const int appearance_item_ = 0;
-const int layout_item_ = 1;
const int protocols_item_ = 4;
const int statistics_item_ = 5;
const int advanced_item_ = 6;
@@ -198,6 +197,8 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) :
// This assumes that the prefs tree and stacked widget contents exactly
// correspond to each other.
QTreeWidgetItem *item = pd_ui_->prefsTree->itemAt(0,0);
+ item->setSelected(true);
+ pd_ui_->stackedWidget->setCurrentIndex(0);
for (int i = 0; i < pd_ui_->stackedWidget->count() && item; i++) {
item->setData(0, Qt::UserRole, qVariantFromValue(pd_ui_->stackedWidget->widget(i)));
item = pd_ui_->prefsTree->itemBelow(item);
@@ -521,6 +522,7 @@ void PreferencesDialog::on_advancedTree_itemActivated(QTreeWidgetItem *item, int
cur_pref_type_ = pref->type;
if (cur_line_edit_) {
cur_line_edit_->setText(saved_string_pref_);
+ cur_line_edit_->selectAll();
connect(cur_line_edit_, SIGNAL(destroyed()), this, SLOT(lineEditPrefDestroyed()));
}
if (cur_combo_box_) {
@@ -653,6 +655,8 @@ void PreferencesDialog::on_buttonBox_accepted()
// return; /* Errors in some preference setting - already reported */
prefs_modules_foreach_submodules(NULL, module_prefs_unstash, (gpointer) &must_redissect);
+ pd_ui_->columnFrame->unstash();
+
prefs_main_write();
#ifdef HAVE_AIRPCAP
diff --git a/ui/qt/preferences_dialog.ui b/ui/qt/preferences_dialog.ui
index 13da76beb8..2a00617285 100644
--- a/ui/qt/preferences_dialog.ui
+++ b/ui/qt/preferences_dialog.ui
@@ -50,9 +50,6 @@
<property name="text">
<string>Columns</string>
</property>
- <property name="flags">
- <set>ItemIsDragEnabled|ItemIsUserCheckable</set>
- </property>
</item>
<item>
<property name="text">
@@ -121,7 +118,7 @@
</property>
<widget class="MainWindowPreferencesFrame" name="appearanceFrame"/>
<widget class="LayoutPreferencesFrame" name="layoutFrame"/>
- <widget class="QFrame" name="columnFrame"/>
+ <widget class="ColumnPreferencesFrame" name="columnFrame"/>
<widget class="QFrame" name="fontandcolorFrame"/>
<widget class="QFrame" name="captureFrame"/>
<widget class="QFrame" name="filterFrame"/>
@@ -214,6 +211,12 @@
<header>layout_preferences_frame.h</header>
<container>1</container>
</customwidget>
+ <customwidget>
+ <class>ColumnPreferencesFrame</class>
+ <extends>QFrame</extends>
+ <header>column_preferences_frame.h</header>
+ <container>1</container>
+ </customwidget>
</customwidgets>
<resources/>
<connections>
diff --git a/ui/qt/wireshark_application.cpp b/ui/qt/wireshark_application.cpp
index 295efd6aa4..eb321b535a 100644
--- a/ui/qt/wireshark_application.cpp
+++ b/ui/qt/wireshark_application.cpp
@@ -527,6 +527,9 @@ void WiresharkApplication::registerUpdate(register_action_e action, const char *
void WiresharkApplication::emitAppSignal(AppSignal signal)
{
switch (signal) {
+ case ColumnsChanged:
+ emit columnsChanged();
+ break;
case PreferencesChanged:
emit preferencesChanged();
break;
diff --git a/ui/qt/wireshark_application.h b/ui/qt/wireshark_application.h
index 326d7cd248..750ea2a9b6 100644
--- a/ui/qt/wireshark_application.h
+++ b/ui/qt/wireshark_application.h
@@ -61,6 +61,7 @@ public:
explicit WiresharkApplication(int &argc, char **argv);
enum AppSignal {
+ ColumnsChanged,
PacketDissectionChanged,
PreferencesChanged
};
@@ -100,6 +101,7 @@ signals:
void splashUpdate(register_action_e action, const char *message);
void configurationProfileChanged(const gchar *profile_name);
+ void columnsChanged();
void packetDissectionChanged();
void preferencesChanged();