diff --git a/epan/libwireshark.def b/epan/libwireshark.def index bd3951273a..bbd7cb0d3f 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -947,6 +947,7 @@ report_open_failure report_read_failure report_write_failure req_resp_hdrs_do_reassembly +reset_pref reset_tap_listeners reset_tcp_reassembly rose_ctx_clean_data diff --git a/epan/prefs.c b/epan/prefs.c index 1a2714889d..99d7422396 100644 --- a/epan/prefs.c +++ b/epan/prefs.c @@ -840,6 +840,11 @@ prefs_register_uint_preference(module_t *module, const char *name, preference->info.base = base; } +/* + * XXX Add a prefs_register_{uint16|port}_preference which sets max_value? + */ + + /* * Register a "custom" preference with a unsigned integral value. * XXX - This should be temporary until we can find a better way @@ -1241,11 +1246,12 @@ static prefs_set_pref_e console_log_level_set_cb(pref_t* pref, const gchar* valu } static const char * console_log_level_type_name_cb(void) { - return "Console log level (for debugging)"; + return "Log level"; } static char * console_log_level_type_description_cb(void) { return g_strdup_printf( + "Console log level (for debugging)\n" "A bitmask of log levels:\n" "ERROR = 4\n" "CRITICAL = 8\n" @@ -1693,12 +1699,12 @@ static prefs_set_pref_e capture_column_set_cb(pref_t* pref, const gchar* value, static const char * capture_column_type_name_cb(void) { - return "Capture options dialog column list"; + return "Column list"; } static char * capture_column_type_description_cb(void) { return g_strdup_printf( - "List of columns to be displayed.\n" + "List of columns to be displayed in the capture options dialog.\n" "Possible values: INTERFACE,LINK,PMODE,SNAPLEN,MONITOR,BUFFER,FILTER\n"); } @@ -2695,10 +2701,10 @@ pre_init_prefs(void) /* * Reset a single dissector preference. */ -static void -reset_pref(gpointer data, gpointer user_data _U_) +void +reset_pref(pref_t *pref) { - pref_t *pref = data; + if (!pref) return; switch (pref->type) { @@ -2756,6 +2762,13 @@ reset_pref(gpointer data, gpointer user_data _U_) } } +static void +reset_pref_cb(gpointer data, gpointer user_data _U_) +{ + pref_t *pref = (pref_t *) data; + reset_pref(pref); +} + typedef struct { module_t *module; } reset_pref_arg_t; @@ -2769,7 +2782,7 @@ reset_module_prefs(void *value, void *data _U_) reset_pref_arg_t arg; arg.module = value; - g_list_foreach(arg.module->prefs, reset_pref, &arg); + g_list_foreach(arg.module->prefs, reset_pref_cb, &arg); return FALSE; } @@ -3926,7 +3939,7 @@ prefs_pref_type_name(pref_t *pref) break; case PREF_ENUM: - type_name = "Enumeration"; + type_name = "Choice"; break; case PREF_STRING: @@ -4057,7 +4070,7 @@ prefs_pref_type_description(pref_t *pref) default: break; } - return g_strdup_printf("%s.", type_desc); + return g_strdup(type_desc); } gboolean diff --git a/epan/prefs.h b/epan/prefs.h index de0909eac1..461a04753a 100644 --- a/epan/prefs.h +++ b/epan/prefs.h @@ -514,6 +514,12 @@ extern e_prefs *read_prefs(int *, int *, char **, int *, int *, char **); into "*pf_path_return", and return the errno. */ extern int write_prefs(char **); +/** Set a preference to its default value + * + * @param pref A preference. + */ +extern void reset_pref(pref_t *pref); + /* * Given a string of the form ":", as might appear * as an argument to a "-o" option, parse it and set the preference in diff --git a/ui/qt/preferences_dialog.cpp b/ui/qt/preferences_dialog.cpp index 1e12a5a560..495f71b4bd 100644 --- a/ui/qt/preferences_dialog.cpp +++ b/ui/qt/preferences_dialog.cpp @@ -21,22 +21,26 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include - -#include "color.h" -#include "packet-range.h" - -#include -#include - #include "preferences_dialog.h" #include "ui_preferences_dialog.h" +#include "wireshark_application.h" +#include + +#include "syntax_line_edit.h" +#include +#include +#include +#include +#include +#include +#include +#include #include #include +Q_DECLARE_METATYPE(pref_t *) + extern "C" { // Callbacks prefs routines @@ -49,15 +53,11 @@ fill_advanced_prefs(module_t *module, gpointer root_ptr) if (module->numprefs < 1 && !prefs_module_has_submodules(module)) return 0; - QString module_title; -// if (module->parent == NULL) - module_title = module->title; -// else -// module_title = QString(module->parent->title) +": "+ module->title; + QString module_title = module->title; QTreeWidgetItem *tl_item = new QTreeWidgetItem(root_item); tl_item->setText(0, module_title); - tl_item->setToolTip(0, module->description); + tl_item->setToolTip(0, QString("%1").arg(module->description)); tl_item->setFirstColumnSpanned(true); QListtl_children; @@ -70,43 +70,19 @@ fill_advanced_prefs(module_t *module, gpointer root_ptr) QTreeWidgetItem *item = new QTreeWidgetItem(); QString full_name = QString(module->name ? module->name : module->parent->name) + "." + pref->name; - QFont font = item->font(0); char *type_desc = prefs_pref_type_description(pref); - char *cur_value = prefs_pref_to_str(pref, false); - char *default_value = prefs_pref_to_str(pref, true); - bool is_default = false; - bool is_editable = true; - - if (pref->type == PREF_UAT) { - is_editable = false; - } else { - if (prefs_pref_is_default(pref)) is_default = true; - } + char * default_value = prefs_pref_to_str(pref, true); + item->setData(0, Qt::UserRole, qVariantFromValue(pref)); item->setText(0, full_name); - item->setToolTip(0, pref->description); - item->setText(1, is_default ? "Default" : "Changed"); - item->setToolTip(1, "Has this value been changed?"); + item->setToolTip(0, QString("%1").arg(pref->description)); item->setText(2, type_name); - item->setToolTip(2, type_desc); - item->setText(3, QString(cur_value).replace(QRegExp("\n\t"), " ")); - item->setToolTip(3, QString("Default: ") + default_value); + item->setToolTip(2, QString("%1").arg(type_desc)); + item->setToolTip(3, QString("%1").arg(strlen(default_value) < 1 ? "Default value is empty" : default_value)); + g_free(type_desc); - g_free(cur_value); g_free(default_value); - font.setBold(!is_default); - - if (!is_editable) { - item->setFlags(item->flags() ^ Qt::ItemIsEnabled); - } - font.setItalic(!is_editable); - item->setFont(0, font); - - item->setFont(0, font); - item->setFont(1, font); - item->setFont(2, font); - item->setFont(3, font); tl_children << item; } tl_item->addChildren(tl_children); @@ -130,25 +106,24 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) : pd_ui_(new Ui::PreferencesDialog) { pd_ui_->setupUi(this); - QTreeWidgetItem tmp_item; + QTreeWidgetItem tmp_item; // Adding pre-populated top-level items is much faster - pd_ui_->advancedTree->setUpdatesEnabled(false); prefs_modules_foreach_submodules(NULL, fill_advanced_prefs, (gpointer) &tmp_item); + pd_ui_->advancedTree->invisibleRootItem()->addChildren(tmp_item.takeChildren()); - pd_ui_->advancedTree->expandAll(); - pd_ui_->advancedTree->setSortingEnabled(true); - pd_ui_->advancedTree->sortByColumn(0, Qt::AscendingOrder); - pd_ui_->advancedTree->setColumnWidth(0, pd_ui_->advancedTree->width() * 2 / 5); - pd_ui_->advancedTree->resizeColumnToContents(1); - pd_ui_->advancedTree->resizeColumnToContents(2); - pd_ui_->advancedTree->setColumnWidth(3, pd_ui_->advancedTree->width() * 3 / 5); - pd_ui_->advancedTree->setUpdatesEnabled(true); + QTreeWidgetItemIterator pref_it(pd_ui_->advancedTree, QTreeWidgetItemIterator::NoChildren); + while (*pref_it) { +// pref_t *pref = (*pref_it)->data(0, Qt::UserRole).value(); + updateItem(*(*pref_it)); +// if (pref) pref_item_hash_[pref] = (*pref_it); + ++pref_it; + } pd_ui_->splitter->setStretchFactor(0, 1); pd_ui_->splitter->setStretchFactor(1, 5); pd_ui_->prefsTree->invisibleRootItem()->child(appearance_item_)->setExpanded(true); - pd_ui_->prefsTree->invisibleRootItem()->child(advanced_item_)->setSelected(true); + pd_ui_->prefsTree->setCurrentItem(pd_ui_->prefsTree->invisibleRootItem()->child(advanced_item_)); } PreferencesDialog::~PreferencesDialog() @@ -169,6 +144,307 @@ void PreferencesDialog::showEvent(QShowEvent *evt) sizes[0] = new_prefs_tree_width; pd_ui_->splitter->setSizes(sizes); pd_ui_->splitter->setStretchFactor(0, 0); + + pd_ui_->advancedTree->expandAll(); + pd_ui_->advancedTree->setSortingEnabled(true); + pd_ui_->advancedTree->sortByColumn(0, Qt::AscendingOrder); + pd_ui_->advancedTree->setColumnWidth(0, pd_ui_->stackedWidget->width() / 2); // Don't let long items widen things too much + pd_ui_->advancedTree->resizeColumnToContents(1); + pd_ui_->advancedTree->resizeColumnToContents(2); + pd_ui_->advancedTree->resizeColumnToContents(3); +} + +void PreferencesDialog::updateItem(QTreeWidgetItem &item) +{ + pref_t *pref = item.data(0, Qt::UserRole).value(); + if (!pref) return; + + char *cur_value = prefs_pref_to_str(pref, false); + bool is_changed = false; + QFont font = item.font(0); + + if (pref->type == PREF_UAT) { + item.setText(1, "Unknown"); + } else if (prefs_pref_is_default(pref)) { + item.setText(1, "Default"); + } else { + item.setText(1, "Changed"); + is_changed = true; + } + font.setBold(is_changed); + item.setFont(0, font); + item.setFont(0, font); + item.setFont(1, font); + item.setFont(2, font); + item.setFont(3, font); + + item.setToolTip(1, "Has this value been changed?"); + item.setText(3, QString(cur_value).remove(QRegExp("\n\t"))); + g_free(cur_value); +} + +void PreferencesDialog::on_prefsTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) +{ + Q_UNUSED(previous) + QString frame_name = current->text(0).remove(" ").toLower().append("Frame"); + QFrame *frame = pd_ui_->stackedWidget->findChild(frame_name); + if (frame) { + pd_ui_->stackedWidget->setCurrentWidget(frame); + } +} + +void PreferencesDialog::on_advancedSearchLineEdit_textEdited(const QString &search_str) +{ + // Hide or show each branch + QTreeWidgetItemIterator branch_it(pd_ui_->advancedTree); + while (*branch_it) { + if ((*branch_it)->data(0, Qt::UserRole).value() == NULL) { + (*branch_it)->setHidden(!search_str.isEmpty()); + } + ++branch_it; + } + + // Hide or show each item, showing its parents if needed + QTreeWidgetItemIterator pref_it(pd_ui_->advancedTree); + while (*pref_it) { + bool hidden = true; + + if ((*pref_it)->data(0, Qt::UserRole).value()) { + QTreeWidgetItem *parent = (*pref_it)->parent(); + + if (search_str.isEmpty() || + (*pref_it)->text(0).contains(search_str, Qt::CaseInsensitive) || + (*pref_it)->toolTip(0).contains(search_str, Qt::CaseInsensitive)) { + hidden = false; + } + + (*pref_it)->setHidden(hidden); + if (!hidden) { + while (parent) { + parent->setHidden(false); + parent = parent->parent(); + } + } + } + ++pref_it; + } +} + +void PreferencesDialog::on_advancedTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) +{ + Q_UNUSED(current); + + if (previous && pd_ui_->advancedTree->itemWidget(previous, 3)) { + pd_ui_->advancedTree->removeItemWidget(previous, 3); + } +} + +void PreferencesDialog::on_advancedTree_itemActivated(QTreeWidgetItem *item, int column) +{ + pref_t *pref = item->data(0, Qt::UserRole).value(); + if (!pref) return; + + if (column < 3) { + reset_pref(pref); + updateItem(*item); + } else { + QWidget *editor = NULL; + + switch (pref->type) { + case PREF_UINT: + { + QLineEdit *line_edit = new QLineEdit(); + line_edit->setInputMask("0000000009;"); + line_edit->setText(*pref->varp.string); + connect(line_edit, SIGNAL(editingFinished()), this, SLOT(uintPrefEditingFinished())); + editor = line_edit; + break; + } + case PREF_BOOL: + *pref->varp.boolp = !*pref->varp.boolp; + updateItem(*item); + break; + case PREF_ENUM: + { + QComboBox *combo = new QComboBox(); + const enum_val_t *ev; + for (ev = pref->info.enum_info.enumvals; ev && ev->description; ev++) { + combo->addItem(ev->description, QVariant(ev->value)); + if (*pref->varp.enump == ev->value) + combo->setCurrentIndex(combo->count() - 1); + } + connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(enumPrefCurrentIndexChanged(int))); + editor = combo; + break; + } + case PREF_STRING: + { + QLineEdit *line_edit = new QLineEdit(); + line_edit->setText(*pref->varp.string); + connect(line_edit, SIGNAL(editingFinished()), this, SLOT(stringPrefEditingFinished())); + editor = line_edit; + break; + } + case PREF_FILENAME: + { + QString filename = QFileDialog::getSaveFileName(this, + QString("Wireshark: ") + pref->description, + *pref->varp.string); + if (!filename.isEmpty()) { + g_free((void *)*pref->varp.string); + *pref->varp.string = g_strdup(filename.toUtf8().constData()); + updateItem(*item); + } + break; + } + case PREF_RANGE: + { + SyntaxLineEdit *syntax_edit = new SyntaxLineEdit(); + char *cur_val = prefs_pref_to_str(pref, FALSE); + connect(syntax_edit, SIGNAL(textChanged(QString)), + this, SLOT(rangePrefTextChanged(QString))); + connect(syntax_edit, SIGNAL(editingFinished()), this, SLOT(rangePrefEditingFinished())); + syntax_edit->setText(cur_val); + g_free(cur_val); + editor = syntax_edit; + break; + } + case PREF_COLOR: + { + QColorDialog color_dlg; + + color_dlg.setCurrentColor(QColor( + pref->varp.color->red >> 8, + pref->varp.color->green >> 8, + pref->varp.color->blue >> 8 + )); + if (color_dlg.exec() == QDialog::Accepted) { + QColor cc = color_dlg.currentColor(); + pref->varp.color->red = cc.red() << 8 | cc.red(); + pref->varp.color->green = cc.green() << 8 | cc.green(); + pref->varp.color->blue = cc.blue() << 8 | cc.blue(); + updateItem(*item); + } + break; + } + case PREF_UAT: + qDebug() << "FIX open uat dialog" << item->text(column); + break; + default: + break; + } + 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(3, ""); + edit_frame->setLayout(hb); + pd_ui_->advancedTree->setItemWidget(item, 3, edit_frame); + editor->setFocus(); + } + } +} + +void PreferencesDialog::uintPrefEditingFinished() +{ + QLineEdit *line_edit = qobject_cast(QObject::sender()); + QTreeWidgetItem *item = pd_ui_->advancedTree->currentItem(); + if (!line_edit || !item) return; + + pref_t *pref = item->data(0, Qt::UserRole).value(); + if (!pref) return; + + *pref->varp.uint = line_edit->text().toUInt(); + pd_ui_->advancedTree->removeItemWidget(item, 3); + updateItem(*item); +} + +void PreferencesDialog::enumPrefCurrentIndexChanged(int index) +{ + QComboBox *combo_box = qobject_cast(QObject::sender()); + QTreeWidgetItem *item = pd_ui_->advancedTree->currentItem(); + if (!combo_box || !item || index < 0) return; + + pref_t *pref = item->data(0, Qt::UserRole).value(); + if (!pref) return; + + *pref->varp.enump = combo_box->itemData(index, Qt::UserRole).toInt(); +// pd_ui_->advancedTree->removeItemWidget(item, 3); // Crashes + updateItem(*item); +} + +void PreferencesDialog::stringPrefEditingFinished() +{ + QLineEdit *line_edit = qobject_cast(QObject::sender()); + QTreeWidgetItem *item = pd_ui_->advancedTree->currentItem(); + if (!line_edit || !item) return; + + pref_t *pref = item->data(0, Qt::UserRole).value(); + if (!pref) return; + + g_free((void *)*pref->varp.string); + *pref->varp.string = g_strdup(line_edit->text().toUtf8().constData()); + pd_ui_->advancedTree->removeItemWidget(item, 3); + updateItem(*item); +} + +void PreferencesDialog::rangePrefTextChanged(const QString &text) +{ + SyntaxLineEdit *syntax_edit = qobject_cast(QObject::sender()); + QTreeWidgetItem *item = pd_ui_->advancedTree->currentItem(); + if (!syntax_edit || !item) return; + + pref_t *pref = item->data(0, Qt::UserRole).value(); + if (!pref) return; + + if (text.isEmpty()) { + syntax_edit->setSyntaxState(SyntaxLineEdit::Empty); + } else { + range_t *newrange; + convert_ret_t ret = range_convert_str(&newrange, text.toUtf8().constData(), pref->info.max_value); + + if (ret == CVT_NO_ERROR) { + syntax_edit->setSyntaxState(SyntaxLineEdit::Valid); + g_free(newrange); + } else { + syntax_edit->setSyntaxState(SyntaxLineEdit::Invalid); + } + } +} + +void PreferencesDialog::rangePrefEditingFinished() +{ + SyntaxLineEdit *syntax_edit = qobject_cast(QObject::sender()); + QTreeWidgetItem *item = pd_ui_->advancedTree->currentItem(); + if (!syntax_edit || !item) return; + + pref_t *pref = item->data(0, Qt::UserRole).value(); + if (!pref) return; + + range_t *newrange; + convert_ret_t ret = range_convert_str(&newrange, syntax_edit->text().toUtf8().constData(), pref->info.max_value); + + if (ret == CVT_NO_ERROR) { + g_free(*pref->varp.range); + *pref->varp.range = newrange; + } + pd_ui_->advancedTree->removeItemWidget(item, 3); + updateItem(*item); +} + +void PreferencesDialog::on_buttonBox_helpRequested() +{ + wsApp->helpTopicAction(HELP_PREFERENCES_DIALOG); } /* diff --git a/ui/qt/preferences_dialog.h b/ui/qt/preferences_dialog.h index 67f9a48aa3..981378ea17 100644 --- a/ui/qt/preferences_dialog.h +++ b/ui/qt/preferences_dialog.h @@ -24,7 +24,17 @@ #ifndef PREFERENCES_DIALOG_H #define PREFERENCES_DIALOG_H +#include "config.h" + +#include + +#include "color.h" +#include "packet-range.h" + +#include + #include +#include namespace Ui { class PreferencesDialog; @@ -42,7 +52,22 @@ protected: void showEvent(QShowEvent *evt); private: + void updateItem(QTreeWidgetItem &item); + Ui::PreferencesDialog *pd_ui_; +// QHash pref_item_hash_; + +private slots: + void on_prefsTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + void on_advancedSearchLineEdit_textEdited(const QString &search_str); + void on_advancedTree_itemActivated(QTreeWidgetItem *item, int column); + void uintPrefEditingFinished(); + void enumPrefCurrentIndexChanged(int index); + void stringPrefEditingFinished(); + void rangePrefTextChanged(const QString & text); + void rangePrefEditingFinished(); + void on_buttonBox_helpRequested(); + void on_advancedTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); }; #endif // PREFERENCES_DIALOG_H diff --git a/ui/qt/preferences_dialog.ui b/ui/qt/preferences_dialog.ui index ffc65f87cc..8fd7b1e982 100644 --- a/ui/qt/preferences_dialog.ui +++ b/ui/qt/preferences_dialog.ui @@ -35,32 +35,29 @@ Appearance - - ItemIsDragEnabled|ItemIsUserCheckable - Layout - - ItemIsDragEnabled|ItemIsUserCheckable - + + ItemIsDragEnabled|ItemIsUserCheckable + Columns - - ItemIsDragEnabled|ItemIsUserCheckable - + + ItemIsDragEnabled|ItemIsUserCheckable + Font and Colors - - ItemIsDragEnabled|ItemIsUserCheckable - + + ItemIsDragEnabled|ItemIsUserCheckable + @@ -116,10 +113,10 @@ - + - + @@ -153,9 +150,6 @@ - - true - true