/* preferences_dialog.cpp * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "preferences_dialog.h" #include #include "module_preferences_scroll_area.h" #include #include #include #include #include #include #include #include "wireshark_application.h" extern "C" { // Callbacks prefs routines static guint module_prefs_unstash(module_t *module, gpointer data) { gboolean *must_redissect_p = (gboolean *)data; pref_unstash_data_t unstashed_data; unstashed_data.handle_decode_as = TRUE; module->prefs_changed_flags = 0; /* assume none of them changed */ for (GList *pref_l = module->prefs; pref_l && pref_l->data; pref_l = g_list_next(pref_l)) { pref_t *pref = (pref_t *) pref_l->data; if (prefs_get_type(pref) == PREF_OBSOLETE || prefs_get_type(pref) == PREF_STATIC_TEXT) continue; unstashed_data.module = module; pref_unstash(pref, &unstashed_data); } /* If any of them changed, indicate that we must redissect and refilter the current capture (if we have one), as the preference change could cause packets to be dissected differently. */ *must_redissect_p |= module->prefs_changed_flags; if(prefs_module_has_submodules(module)) return prefs_modules_foreach_submodules(module, module_prefs_unstash, data); return 0; /* Keep unstashing. */ } static guint module_prefs_clean_stash(module_t *module, gpointer) { for (GList *pref_l = module->prefs; pref_l && pref_l->data; pref_l = g_list_next(pref_l)) { pref_t *pref = (pref_t *) pref_l->data; if (prefs_get_type(pref) == PREF_OBSOLETE || prefs_get_type(pref) == PREF_STATIC_TEXT) continue; pref_clean_stash(pref, NULL); } if(prefs_module_has_submodules(module)) return prefs_modules_foreach_submodules(module, module_prefs_clean_stash, NULL); return 0; /* Keep cleaning modules */ } } // extern "C" // Preference tree items const int APPEARANCE_ITEM = 0; //placeholder key to keep dynamically loaded preferences static const char* MODULES_NAME = "Modules"; PreferencesDialog::PreferencesDialog(QWidget *parent) : GeometryStateDialog(parent), pd_ui_(new Ui::PreferencesDialog), model_(this), advancedPrefsModel_(this), advancedPrefsDelegate_(this), modulePrefsModel_(this) { advancedPrefsModel_.setSourceModel(&model_); modulePrefsModel_.setSourceModel(&model_); saved_capture_no_extcap_ = prefs.capture_no_extcap; // Some classes depend on pref_ptr_to_pref_ so this MUST be called after // model_.populate(). pd_ui_->setupUi(this); loadGeometry(); setWindowTitle(wsApp->windowTitleString(tr("Preferences"))); pd_ui_->advancedView->setModel(&advancedPrefsModel_); pd_ui_->advancedView->setItemDelegate(&advancedPrefsDelegate_); advancedPrefsModel_.setFirstColumnSpanned(pd_ui_->advancedView); pd_ui_->prefsView->setModel(&modulePrefsModel_); pd_ui_->splitter->setStretchFactor(0, 1); pd_ui_->splitter->setStretchFactor(1, 5); pd_ui_->prefsView->sortByColumn(ModulePrefsModel::colName, Qt::AscendingOrder); //Set the Appearance leaf to expanded pd_ui_->prefsView->setExpanded(modulePrefsModel_.index(APPEARANCE_ITEM, 0), true); // PreferencesPane, prefsView, and stackedWidget must all correspond to each other. prefs_pane_to_item_[PrefsModel::APPEARANCE_PREFERENCE_TREE_NAME] = pd_ui_->appearanceFrame; prefs_pane_to_item_[PrefsModel::LAYOUT_PREFERENCE_TREE_NAME] = pd_ui_->layoutFrame; prefs_pane_to_item_[PrefsModel::COLUMNS_PREFERENCE_TREE_NAME] = pd_ui_->columnFrame; prefs_pane_to_item_[PrefsModel::FONT_AND_COLORS_PREFERENCE_TREE_NAME] = pd_ui_->fontandcolorFrame; prefs_pane_to_item_[PrefsModel::CAPTURE_PREFERENCE_TREE_NAME] = pd_ui_->captureFrame; prefs_pane_to_item_[PrefsModel::EXPERT_PREFERENCE_TREE_NAME] = pd_ui_->expertFrame; prefs_pane_to_item_[PrefsModel::FILTER_BUTTONS_PREFERENCE_TREE_NAME] = pd_ui_->filterExpressonsFrame; prefs_pane_to_item_[PrefsModel::ADVANCED_PREFERENCE_TREE_NAME] = pd_ui_->advancedFrame; prefs_pane_to_item_[MODULES_NAME] = NULL; pd_ui_->filterExpressonsFrame->setUat(uat_get_table_by_name("Display expressions")); pd_ui_->expertFrame->setUat(uat_get_table_by_name("Expert Info Severity Level Configuration")); connect(pd_ui_->prefsView, SIGNAL(goToPane(QString)), this, SLOT(selectPane(QString))); } PreferencesDialog::~PreferencesDialog() { delete pd_ui_; prefs_modules_foreach_submodules(NULL, module_prefs_clean_stash, NULL); } void PreferencesDialog::setPane(const QString pane_name) { pd_ui_->prefsView->setPane(pane_name); } void PreferencesDialog::showEvent(QShowEvent *) { QStyleOption style_opt; int new_prefs_tree_width = pd_ui_->prefsView->style()->subElementRect(QStyle::SE_TreeViewDisclosureItem, &style_opt).left(); QList sizes = pd_ui_->splitter->sizes(); #ifdef Q_OS_WIN new_prefs_tree_width *= 2; #endif pd_ui_->prefsView->resizeColumnToContents(ModulePrefsModel::colName); new_prefs_tree_width += pd_ui_->prefsView->columnWidth(ModulePrefsModel::colName); pd_ui_->prefsView->setMinimumWidth(new_prefs_tree_width); sizes[1] += sizes[0] - new_prefs_tree_width; sizes[0] = new_prefs_tree_width; pd_ui_->splitter->setSizes(sizes); pd_ui_->splitter->setStretchFactor(0, 1); pd_ui_->advancedView->expandAll(); pd_ui_->advancedView->setSortingEnabled(true); pd_ui_->advancedView->sortByColumn(AdvancedPrefsModel::colName, Qt::AscendingOrder); int one_em = fontMetrics().height(); pd_ui_->advancedView->setColumnWidth(AdvancedPrefsModel::colName, one_em * 12); // Don't let long items widen things too much pd_ui_->advancedView->resizeColumnToContents(AdvancedPrefsModel::colStatus); pd_ui_->advancedView->resizeColumnToContents(AdvancedPrefsModel::colType); pd_ui_->advancedView->setColumnWidth(AdvancedPrefsModel::colValue, one_em * 30); } void PreferencesDialog::selectPane(QString pane) { if (prefs_pane_to_item_.contains(pane)) { pd_ui_->stackedWidget->setCurrentWidget(prefs_pane_to_item_[pane]); } else { //If not found in prefs_pane_to_item_, it must be an individual module module_t* module = prefs_find_module(pane.toStdString().c_str()); if (module != NULL) { QWidget* moduleWindow = prefs_pane_to_item_[MODULES_NAME]; if (moduleWindow != NULL) { pd_ui_->stackedWidget->removeWidget(moduleWindow); delete moduleWindow; } moduleWindow = new ModulePreferencesScrollArea(module); prefs_pane_to_item_[MODULES_NAME] = moduleWindow; pd_ui_->stackedWidget->addWidget(moduleWindow); pd_ui_->stackedWidget->setCurrentWidget(moduleWindow); } } } void PreferencesDialog::on_advancedSearchLineEdit_textEdited(const QString &search_re) { advancedPrefsModel_.setFilter(search_re); /* If items are filtered out, then filtered back in, the tree remains colapsed Force an expansion */ pd_ui_->advancedView->expandAll(); } void PreferencesDialog::on_buttonBox_accepted() { gchar* err = NULL; unsigned int redissect_flags = 0; // XXX - We should validate preferences as the user changes them, not here. // XXX - We're also too enthusiastic about setting must_redissect. prefs_modules_foreach_submodules(NULL, module_prefs_unstash, (gpointer)&redissect_flags); if (redissect_flags & PREF_EFFECT_GUI_LAYOUT) { // Layout type changed, reset sizes recent.gui_geometry_main_upper_pane = 0; recent.gui_geometry_main_lower_pane = 0; } pd_ui_->columnFrame->unstash(); pd_ui_->filterExpressonsFrame->acceptChanges(); pd_ui_->expertFrame->acceptChanges(); //Filter expressions don't affect dissection, so there is no need to //send any events to that effect. However, the app needs to know //about any button changes. wsApp->emitAppSignal(WiresharkApplication::FilterExpressionsChanged); prefs_main_write(); if (save_decode_as_entries(&err) < 0) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err); g_free(err); } write_language_prefs(); wsApp->loadLanguage(QString(language)); #ifdef HAVE_AIRPCAP /* * Load the Wireshark decryption keys (just set) and save * the changes to the adapters' registry */ //airpcap_load_decryption_keys(airpcap_if_list); #endif // gtk/prefs_dlg.c:prefs_main_apply_all /* * Apply the protocol preferences first - "gui_prefs_apply()" could * cause redissection, and we have to make sure the protocol * preference changes have been fully applied. */ prefs_apply_all(); /* Fill in capture options with values from the preferences */ prefs_to_capture_opts(); #ifdef HAVE_AIRPCAP // prefs_airpcap_update(); #endif wsApp->setMonospaceFont(prefs.gui_qt_font_name); if (redissect_flags & PREF_EFFECT_DISSECTION) { /* Redissect all the packets, and re-evaluate the display filter. */ wsApp->queueAppSignal(WiresharkApplication::PacketDissectionChanged); } wsApp->queueAppSignal(WiresharkApplication::PreferencesChanged); if (redissect_flags & PREF_EFFECT_GUI_LAYOUT) { wsApp->queueAppSignal(WiresharkApplication::RecentPreferencesRead); } if (prefs.capture_no_extcap != saved_capture_no_extcap_) wsApp->refreshLocalInterfaces(); } void PreferencesDialog::on_buttonBox_rejected() { //handle frames that don't have their own OK/Cancel "buttons" pd_ui_->filterExpressonsFrame->rejectChanges(); pd_ui_->expertFrame->rejectChanges(); } void PreferencesDialog::on_buttonBox_helpRequested() { wsApp->helpTopicAction(HELP_PREFERENCES_DIALOG); } /* * 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: */