diff options
author | Gerald Combs <gerald@wireshark.org> | 2013-01-23 19:04:36 +0000 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2013-01-23 19:04:36 +0000 |
commit | 21e66f0c6f38d20dc4ac3968324fff0959113b14 (patch) | |
tree | e801135c51e407d67516e1969c1ef788af48292e | |
parent | d59e9cf574976b1e9849f5c35be1fd2abdf8ed6d (diff) |
Add column preferences.
svn path=/trunk/; revision=47231
-rw-r--r-- | ui/gtk/packet_list.c | 2 | ||||
-rw-r--r-- | ui/gtk/prefs_column.c | 58 | ||||
-rw-r--r-- | ui/gtk/prefs_column.h | 16 | ||||
-rw-r--r-- | ui/preference_utils.c | 57 | ||||
-rw-r--r-- | ui/preference_utils.h | 22 | ||||
-rw-r--r-- | ui/qt/CMakeLists.txt | 3 | ||||
-rw-r--r-- | ui/qt/Makefile.am | 2 | ||||
-rw-r--r-- | ui/qt/Makefile.common | 4 | ||||
-rw-r--r-- | ui/qt/QtShark.pro | 9 | ||||
-rw-r--r-- | ui/qt/column_preferences_frame.cpp | 440 | ||||
-rw-r--r-- | ui/qt/column_preferences_frame.h | 76 | ||||
-rw-r--r-- | ui/qt/column_preferences_frame.ui | 94 | ||||
-rw-r--r-- | ui/qt/main_window.cpp | 2 | ||||
-rw-r--r-- | ui/qt/main_window.h | 1 | ||||
-rw-r--r-- | ui/qt/main_window_slots.cpp | 20 | ||||
-rw-r--r-- | ui/qt/preferences_dialog.cpp | 6 | ||||
-rw-r--r-- | ui/qt/preferences_dialog.ui | 11 | ||||
-rw-r--r-- | ui/qt/wireshark_application.cpp | 3 | ||||
-rw-r--r-- | ui/qt/wireshark_application.h | 2 |
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(); |