diff options
author | Michael Mann <mmann78@netscape.net> | 2017-12-29 11:23:07 -0500 |
---|---|---|
committer | Roland Knall <rknall@gmail.com> | 2018-01-04 21:20:59 +0000 |
commit | d239da264c5d0ca2ecfd609ae3eccced939a4c46 (patch) | |
tree | aa5b490fa2d9c1b4b6899a411bbcca03ccc0659d /ui/qt | |
parent | a79b7986cddf40a8ade57638916951323fff581e (diff) |
Convert preference dialog to use more models.
Convert Advanced view and Modules view to use a single base model,
loading the preferences once and then filter and display what they
need with QSortFilterProxyModel derived classes.
Convert the PreferencePane "types" to just strings. This allows
a more straightforward relationship between the "special" modules
that need custom widgets for preference manipulation and it also
removes dependency on preferences_dialog.h for many files.
Change-Id: I091deb3061564aa4d1564e9ca1c792715961b083
Reviewed-on: https://code.wireshark.org/review/25134
Reviewed-by: Michael Mann <mmann78@netscape.net>
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot
Reviewed-by: Roland Knall <rknall@gmail.com>
Diffstat (limited to 'ui/qt')
29 files changed, 1576 insertions, 1033 deletions
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index 609971922b..1b3ee4a829 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -44,6 +44,7 @@ set(WIRESHARK_WIDGET_HEADERS widgets/interface_toolbar_lineedit.h widgets/label_stack.h widgets/overlay_scroll_bar.h + widgets/pref_module_view.h widgets/qcustomplot.h widgets/stock_icon_tool_button.h widgets/syntax_line_edit.h @@ -84,6 +85,8 @@ set(WIRESHARK_MODEL_HEADERS models/packet_list_record.h models/path_chooser_delegate.h models/percent_bar_delegate.h + models/pref_delegate.h + models/pref_models.h models/proto_tree_model.h models/related_packet_delegate.h models/sparkline_delegate.h @@ -267,6 +270,7 @@ set(WIRESHARK_WIDGET_SRCS widgets/interface_toolbar_lineedit.cpp widgets/label_stack.cpp widgets/overlay_scroll_bar.cpp + widgets/pref_module_view.cpp widgets/qcustomplot.cpp widgets/stock_icon_tool_button.cpp widgets/syntax_line_edit.cpp @@ -304,6 +308,8 @@ set(WIRESHARK_MODEL_SRCS models/packet_list_record.cpp models/path_chooser_delegate.cpp models/percent_bar_delegate.cpp + models/pref_delegate.cpp + models/pref_models.cpp models/proto_tree_model.cpp models/related_packet_delegate.cpp models/sparkline_delegate.cpp diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am index 6c467895c4..bed07d6a61 100644 --- a/ui/qt/Makefile.am +++ b/ui/qt/Makefile.am @@ -174,6 +174,7 @@ MOC_WIDGET_HDRS = \ widgets/interface_toolbar_lineedit.h \ widgets/label_stack.h \ widgets/overlay_scroll_bar.h \ + widgets/pref_module_view.h \ widgets/syntax_line_edit.h \ widgets/stock_icon_tool_button.h \ widgets/tabnav_tree_view.h \ @@ -213,6 +214,8 @@ MOC_MODELS_HDRS = \ models/packet_list_record.h \ models/path_chooser_delegate.h \ models/percent_bar_delegate.h \ + models/pref_delegate.h \ + models/pref_models.h \ models/proto_tree_model.h \ models/related_packet_delegate.h \ models/sparkline_delegate.h \ @@ -511,6 +514,7 @@ WIRESHARK_QT_WIDGET_SRC = \ widgets/interface_toolbar_lineedit.cpp \ widgets/label_stack.cpp \ widgets/overlay_scroll_bar.cpp \ + widgets/pref_module_view.cpp \ widgets/stock_icon_tool_button.cpp \ widgets/syntax_line_edit.cpp \ widgets/tabnav_tree_view.cpp \ @@ -546,6 +550,8 @@ WIRESHARK_QT_MODELS_SRCS = \ models/packet_list_record.cpp \ models/path_chooser_delegate.cpp \ models/percent_bar_delegate.cpp \ + models/pref_delegate.cpp \ + models/pref_models.cpp \ models/proto_tree_model.cpp \ models/related_packet_delegate.cpp \ models/sparkline_delegate.cpp \ diff --git a/ui/qt/capture_interfaces_dialog.h b/ui/qt/capture_interfaces_dialog.h index 22843b6443..70ff71947d 100644 --- a/ui/qt/capture_interfaces_dialog.h +++ b/ui/qt/capture_interfaces_dialog.h @@ -35,8 +35,6 @@ typedef struct if_stat_cache_s if_stat_cache_t; -#include "preferences_dialog.h" - namespace Ui { class CaptureInterfacesDialog; } diff --git a/ui/qt/capture_preferences_frame.cpp b/ui/qt/capture_preferences_frame.cpp index 3791edb7a7..2a7baf9c5d 100644 --- a/ui/qt/capture_preferences_frame.cpp +++ b/ui/qt/capture_preferences_frame.cpp @@ -28,6 +28,7 @@ #endif #include "capture_preferences_frame.h" +#include <ui/qt/models/pref_models.h> #include <ui_capture_preferences_frame.h> #include "wireshark_application.h" diff --git a/ui/qt/capture_preferences_frame.h b/ui/qt/capture_preferences_frame.h index 8410291207..1932396a9a 100644 --- a/ui/qt/capture_preferences_frame.h +++ b/ui/qt/capture_preferences_frame.h @@ -22,10 +22,10 @@ #ifndef CAPTURE_PREFERENCES_FRAME_H #define CAPTURE_PREFERENCES_FRAME_H -#include "preferences_dialog.h" - #include <QFrame> +#include <epan/prefs.h> + namespace Ui { class CapturePreferencesFrame; } diff --git a/ui/qt/filter_expression_frame.cpp b/ui/qt/filter_expression_frame.cpp index 322c750f0f..c82d4ec943 100644 --- a/ui/qt/filter_expression_frame.cpp +++ b/ui/qt/filter_expression_frame.cpp @@ -4,19 +4,7 @@ * 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. + * SPDX-License-Identifier: GPL-2.0+ */ #include "filter_expression_frame.h" @@ -27,6 +15,7 @@ #include <ui/preference_utils.h> #include <ui/qt/models/uat_model.h> +#include <ui/qt/models/pref_models.h> #include <QPushButton> #include <QKeyEvent> @@ -115,7 +104,7 @@ void FilterExpressionFrame::updateWidgets() void FilterExpressionFrame::on_filterExpressionPreferencesPushButton_clicked() { on_buttonBox_rejected(); - emit showPreferencesDialog(PreferencesDialog::ppFilterExpressions); + emit showPreferencesDialog(PrefsModel::FILTER_BUTTONS_PREFERENCE_TREE_NAME); } void FilterExpressionFrame::on_labelLineEdit_textChanged(const QString) diff --git a/ui/qt/filter_expression_frame.h b/ui/qt/filter_expression_frame.h index 8394537a59..dc2013301c 100644 --- a/ui/qt/filter_expression_frame.h +++ b/ui/qt/filter_expression_frame.h @@ -4,26 +4,13 @@ * 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. + * SPDX-License-Identifier: GPL-2.0+ */ #ifndef FILTER_EXPRESSION_FRAME_H #define FILTER_EXPRESSION_FRAME_H #include "accordion_frame.h" -#include "preferences_dialog.h" namespace Ui { class FilterExpressionFrame; @@ -41,7 +28,7 @@ public: void editExpression(int exprIdx); signals: - void showPreferencesDialog(PreferencesDialog::PreferencesPane start_pane); + void showPreferencesDialog(QString pane_name); void filterExpressionsChanged(); void pushFilterSyntaxStatus(const QString&); diff --git a/ui/qt/font_color_preferences_frame.cpp b/ui/qt/font_color_preferences_frame.cpp index e3b7ea866c..908d3b25fc 100644 --- a/ui/qt/font_color_preferences_frame.cpp +++ b/ui/qt/font_color_preferences_frame.cpp @@ -4,24 +4,14 @@ * 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. + * SPDX-License-Identifier: GPL-2.0+ */ +#include <config.h> #include <ui/qt/utils/qt_ui_utils.h> #include "font_color_preferences_frame.h" +#include <ui/qt/models/pref_models.h> #include <ui_font_color_preferences_frame.h> #include <ui/qt/utils/color_utils.h> #include "wireshark_application.h" diff --git a/ui/qt/font_color_preferences_frame.h b/ui/qt/font_color_preferences_frame.h index 9255472c95..10d44f9611 100644 --- a/ui/qt/font_color_preferences_frame.h +++ b/ui/qt/font_color_preferences_frame.h @@ -22,11 +22,11 @@ #ifndef FONT_COLOR_PREFERENCES_FRAME_H #define FONT_COLOR_PREFERENCES_FRAME_H -#include "preferences_dialog.h" - #include <QFrame> #include <QFont> +#include <epan/prefs.h> + namespace Ui { class FontColorPreferencesFrame; } diff --git a/ui/qt/layout_preferences_frame.cpp b/ui/qt/layout_preferences_frame.cpp index 0ac1571ca4..f003eccb1e 100644 --- a/ui/qt/layout_preferences_frame.cpp +++ b/ui/qt/layout_preferences_frame.cpp @@ -4,21 +4,11 @@ * 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. + * SPDX-License-Identifier: GPL-2.0+ */ +#include <config.h> + #include "layout_preferences_frame.h" #include <ui_layout_preferences_frame.h> @@ -28,6 +18,7 @@ #include <QDebug> #include <epan/prefs-int.h> +#include <ui/qt/models/pref_models.h> LayoutPreferencesFrame::LayoutPreferencesFrame(QWidget *parent) : QFrame(parent), diff --git a/ui/qt/layout_preferences_frame.h b/ui/qt/layout_preferences_frame.h index c0dacbe76c..85bb8c0c14 100644 --- a/ui/qt/layout_preferences_frame.h +++ b/ui/qt/layout_preferences_frame.h @@ -22,7 +22,7 @@ #ifndef LAYOUT_PREFERENCES_FRAME_H #define LAYOUT_PREFERENCES_FRAME_H -#include "preferences_dialog.h" +#include <epan/prefs.h> #include <QFrame> #include <QAbstractButton> diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index ce51e4863a..6bd39de22a 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -372,8 +372,8 @@ MainWindow::MainWindow(QWidget *parent) : connect(df_edit, SIGNAL(pushFilterSyntaxWarning(const QString&)), main_ui_->statusBar, SLOT(pushTemporaryStatus(const QString&))); connect(df_edit, SIGNAL(filterPackets(QString,bool)), this, SLOT(filterPackets(QString,bool))); - connect(df_edit, SIGNAL(showPreferencesDialog(PreferencesDialog::PreferencesPane)), - this, SLOT(showPreferencesDialog(PreferencesDialog::PreferencesPane))); + connect(df_edit, SIGNAL(showPreferencesDialog(QString)), + this, SLOT(showPreferencesDialog(QString))); connect(wsApp, SIGNAL(preferencesChanged()), df_edit, SLOT(checkFilter())); funnel_statistics_ = new FunnelStatistics(this, capture_file_); @@ -572,8 +572,8 @@ MainWindow::MainWindow(QWidget *parent) : this, SLOT(showPreferencesDialog(QString))); connect(main_ui_->preferenceEditorFrame, SIGNAL(showProtocolPreferences(QString)), this, SLOT(showPreferencesDialog(QString))); - connect(main_ui_->filterExpressionFrame, SIGNAL(showPreferencesDialog(PreferencesDialog::PreferencesPane)), - this, SLOT(showPreferencesDialog(PreferencesDialog::PreferencesPane))); + connect(main_ui_->filterExpressionFrame, SIGNAL(showPreferencesDialog(QString)), + this, SLOT(showPreferencesDialog(QString))); connect(main_ui_->filterExpressionFrame, SIGNAL(filterExpressionsChanged()), this, SLOT(filterExpressionsChanged())); @@ -622,8 +622,8 @@ MainWindow::MainWindow(QWidget *parent) : this, SIGNAL(frameSelected(int))); connect(packet_list_, SIGNAL(packetDissectionChanged()), this, SLOT(redissectPackets())); - connect(packet_list_, SIGNAL(showColumnPreferences(PreferencesDialog::PreferencesPane)), - this, SLOT(showPreferencesDialog(PreferencesDialog::PreferencesPane))); + connect(packet_list_, SIGNAL(showColumnPreferences(QString)), + this, SLOT(showPreferencesDialog(QString))); connect(packet_list_, SIGNAL(showProtocolPreferences(QString)), this, SLOT(showPreferencesDialog(QString))); connect(packet_list_, SIGNAL(editProtocolPreference(preference*,pref_module*)), diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index d3a01e0bd7..7bb2255545 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -46,7 +46,7 @@ #include <ui/qt/widgets/display_filter_combo.h> #include "filter_action.h" #include "follow_stream_dialog.h" -#include "preferences_dialog.h" +#include <ui/qt/models/pref_models.h> class AccordionFrame; class ByteViewTab; @@ -452,8 +452,7 @@ private slots: void on_actionEditPacketComment_triggered(); void on_actionDeleteAllPacketComments_triggered(); void on_actionEditConfigurationProfiles_triggered(); - void showPreferencesDialog(PreferencesDialog::PreferencesPane start_pane = PreferencesDialog::ppAppearance); - void showPreferencesDialog(QString module_name); + void showPreferencesDialog(QString pane_name); void on_actionEditPreferences_triggered(); void showHideMainWidgets(QAction *action); diff --git a/ui/qt/main_window_preferences_frame.cpp b/ui/qt/main_window_preferences_frame.cpp index 3bd0eac6ef..182c13d151 100644 --- a/ui/qt/main_window_preferences_frame.cpp +++ b/ui/qt/main_window_preferences_frame.cpp @@ -4,19 +4,7 @@ * 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. + * SPDX-License-Identifier: GPL-2.0+ */ #include "wireshark_application.h" @@ -27,6 +15,7 @@ #include "ui/language.h" #include <epan/prefs-int.h> +#include <ui/qt/models/pref_models.h> #include <wsutil/filesystem.h> #include <QFileDialog> diff --git a/ui/qt/main_window_preferences_frame.h b/ui/qt/main_window_preferences_frame.h index 4ee39023d7..230bc5c6c0 100644 --- a/ui/qt/main_window_preferences_frame.h +++ b/ui/qt/main_window_preferences_frame.h @@ -4,25 +4,13 @@ * 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. + * SPDX-License-Identifier: GPL-2.0+ */ #ifndef MAIN_WINDOW_PREFERENCES_FRAME_H #define MAIN_WINDOW_PREFERENCES_FRAME_H -#include "preferences_dialog.h" +#include <epan/prefs.h> #include <QFrame> diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 9fd932af26..c3e4775474 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -2332,27 +2332,13 @@ void MainWindow::on_actionEditConfigurationProfiles_triggered() cp_dialog.exec(); } -void MainWindow::showPreferencesDialog(PreferencesDialog::PreferencesPane start_pane) +void MainWindow::showPreferencesDialog(QString pane_name) { PreferencesDialog pref_dialog(this); saveWindowGeometry(); // Save in case the layout panes are rearranged - pref_dialog.setPane(start_pane); - pref_dialog.exec(); - - // Emitting PacketDissectionChanged directly from a QDialog can cause - // problems on macOS. - wsApp->flushAppSignals(); -} - -void MainWindow::showPreferencesDialog(QString module_name) -{ - PreferencesDialog pref_dialog(this); - - saveWindowGeometry(); // Save in case the layout panes are rearranged - - pref_dialog.setPane(module_name); + pref_dialog.setPane(pane_name); pref_dialog.exec(); // Emitting PacketDissectionChanged directly from a QDialog can cause @@ -2362,7 +2348,7 @@ void MainWindow::showPreferencesDialog(QString module_name) void MainWindow::on_actionEditPreferences_triggered() { - showPreferencesDialog(); + showPreferencesDialog(PrefsModel::APPEARANCE_PREFERENCE_TREE_NAME); } // View Menu @@ -4059,7 +4045,7 @@ void MainWindow::filterToolbarCustomMenuHandler(const QPoint& pos) void MainWindow::filterToolbarShowPreferences() { - emit showPreferencesDialog(PreferencesDialog::ppFilterExpressions); + emit showPreferencesDialog(PrefsModel::FILTER_BUTTONS_PREFERENCE_TREE_NAME); } int MainWindow::uatRowIndexForFilterExpression(QString label, QString expression) diff --git a/ui/qt/models/pref_delegate.cpp b/ui/qt/models/pref_delegate.cpp new file mode 100644 index 0000000000..8a4b83a68f --- /dev/null +++ b/ui/qt/models/pref_delegate.cpp @@ -0,0 +1,270 @@ +/* pref_delegate.cpp + * Delegates for editing prefereneces. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <ui/qt/models/pref_delegate.h> +#include <epan/prefs-int.h> + +#include <QComboBox> +#include <QFileDialog> +#include <QLineEdit> +#include <QColorDialog> + +#include "uat_dialog.h" +#include "wireshark_application.h" + +#include <ui/qt/widgets/editor_file_dialog.h> + +RangeSyntaxLineEdit::RangeSyntaxLineEdit(QWidget *parent) + : SyntaxLineEdit(parent), + maxRange_(0xFFFFFFFF) +{ + connect(this, SIGNAL(textChanged(QString)), this, SLOT(checkRange(QString))); +} + +void RangeSyntaxLineEdit::checkRange(QString range) +{ + if (range.isEmpty()) { + setSyntaxState(SyntaxLineEdit::Empty); + return; + } + + range_t *newrange; + convert_ret_t ret = range_convert_str(NULL, &newrange, range.toUtf8().constData(), maxRange_); + + if (ret == CVT_NO_ERROR) { + setSyntaxState(SyntaxLineEdit::Valid); + wmem_free(NULL, newrange); + } else { + setSyntaxState(SyntaxLineEdit::Invalid); + } +} + + + + +AdvancedPrefDelegate::AdvancedPrefDelegate(QObject *parent) : QStyledItemDelegate(parent) +{ +} + +PrefsItem* AdvancedPrefDelegate::indexToPref(const QModelIndex &index) const +{ + const QVariant v = index.model()->data(index, Qt::UserRole); + return VariantPointer<PrefsItem>::asPtr(v); +} + +QWidget *AdvancedPrefDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + PrefsItem* pref; + QString filename; + + switch(index.column()) + { + case AdvancedPrefsModel::colName: + case AdvancedPrefsModel::colStatus: + case AdvancedPrefsModel::colType: + //If user clicks on any of these columns, reset preference back to default + //There is no need to launch an editor + ((QAbstractItemModel*)index.model())->setData(index, QVariant(), Qt::EditRole); + break; + case AdvancedPrefsModel::colValue: + pref = indexToPref(index); + switch(pref->getPrefType()) + { + case PREF_DECODE_AS_UINT: + case PREF_UINT: + { + QLineEdit* editor = new QLineEdit(parent); +#if 0 + //XXX - Do we want some help handling formatting the number? + editor->setInputMask("0000000009;"); +#endif + return editor; + } + case PREF_BOOL: + //Setting any non-NULL value will invert boolean value + ((QAbstractItemModel*)index.model())->setData(index, QString("BOOL"), Qt::EditRole); + break; + case PREF_ENUM: + { + QComboBox* editor = new QComboBox(parent); + return editor; + } + case PREF_STRING: + { + //Separated from UINT in case formatting needs to be applied to UINT + QLineEdit* editor = new QLineEdit(parent); + return editor; + } + case PREF_DECODE_AS_RANGE: + case PREF_RANGE: + { + RangeSyntaxLineEdit *editor = new RangeSyntaxLineEdit(parent); + return editor; + } + case PREF_UAT: + { + if (pref->getPrefGUIType() == GUI_ALL || pref->getPrefGUIType() == GUI_QT) { + UatDialog uat_dlg(parent, prefs_get_uat_value(pref->getPref())); + uat_dlg.exec(); + } + } + break; + case PREF_SAVE_FILENAME: + filename = QFileDialog::getSaveFileName(parent, wsApp->windowTitleString(prefs_get_title(pref->getPref())), + index.model()->data(index, Qt::DisplayRole).toString()); + if (!filename.isEmpty()) { + ((QAbstractItemModel*)index.model())->setData(index, QDir::toNativeSeparators(filename), Qt::EditRole); + } + break; + case PREF_OPEN_FILENAME: + filename = QFileDialog::getOpenFileName(parent, wsApp->windowTitleString(prefs_get_title(pref->getPref())), + index.model()->data(index, Qt::DisplayRole).toString()); + if (!filename.isEmpty()) { + ((QAbstractItemModel*)index.model())->setData(index, QDir::toNativeSeparators(filename), Qt::EditRole); + } + break; + case PREF_DIRNAME: + filename = QFileDialog::getExistingDirectory(parent, wsApp->windowTitleString(prefs_get_title(pref->getPref())), + index.model()->data(index, Qt::DisplayRole).toString()); + if (!filename.isEmpty()) { + ((QAbstractItemModel*)index.model())->setData(index, QDir::toNativeSeparators(filename), Qt::EditRole); + } + break; + case PREF_COLOR: + { + QColorDialog color_dlg; + color_t color = *prefs_get_color_value(pref->getPref(), pref_stashed); + + color_dlg.setCurrentColor(QColor( + color.red >> 8, + color.green >> 8, + color.blue >> 8 + )); + if (color_dlg.exec() == QDialog::Accepted) { + ((QAbstractItemModel*)index.model())->setData(index, color_dlg.currentColor().name(), Qt::EditRole); + } + break; + } + + } + break; + } + + return 0; +} + +void AdvancedPrefDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + PrefsItem* pref = indexToPref(index); + + switch(pref->getPrefType()) + { + case PREF_DECODE_AS_UINT: + case PREF_UINT: + { + QLineEdit* line = static_cast<QLineEdit*>(editor); + line->setText(index.model()->data(index, Qt::DisplayRole).toString()); + } + break; + case PREF_ENUM: + { + QComboBox* combo = static_cast<QComboBox*>(editor); + const enum_val_t *ev; + PrefsItem* pref = VariantPointer<PrefsItem>::asPtr(index.model()->data(index, Qt::UserRole)); + for (ev = prefs_get_enumvals(pref->getPref()); ev && ev->description; ev++) { + combo->addItem(ev->description, QVariant(ev->value)); + if (prefs_get_enum_value(pref->getPref(), pref_stashed) == ev->value) + combo->setCurrentIndex(combo->count() - 1); + } + } + break; + case PREF_STRING: + { + QLineEdit* line = static_cast<QLineEdit*>(editor); + line->setText(index.model()->data(index, Qt::DisplayRole).toString()); + } + break; + case PREF_DECODE_AS_RANGE: + case PREF_RANGE: + { + RangeSyntaxLineEdit* syntax = static_cast<RangeSyntaxLineEdit*>(editor); + syntax->setText(index.model()->data(index, Qt::DisplayRole).toString()); + } + break; + case PREF_UAT: + case PREF_SAVE_FILENAME: + case PREF_OPEN_FILENAME: + case PREF_DIRNAME: + case PREF_COLOR: + //Handled by the dialogs created + break; + default: + //Ensure any new preference types are handled + Q_ASSERT(FALSE); + break; + } +} + +void AdvancedPrefDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + PrefsItem* pref = indexToPref(index); + switch(pref->getPrefType()) + { + case PREF_DECODE_AS_UINT: + case PREF_UINT: + case PREF_STRING: + { + QLineEdit* line = static_cast<QLineEdit*>(editor); + model->setData(index, line->text(), Qt::EditRole); + break; + } + case PREF_ENUM: + { + QComboBox* combo = static_cast<QComboBox*>(editor); + model->setData(index, combo->itemData(combo->currentIndex()), Qt::EditRole); + } + break; + case PREF_DECODE_AS_RANGE: + case PREF_RANGE: + { + RangeSyntaxLineEdit* syntax = static_cast<RangeSyntaxLineEdit*>(editor); + model->setData(index, syntax->text(), Qt::EditRole); + break; + } + case PREF_UAT: + //do nothing because UAT values aren't shown in table + break; + case PREF_SAVE_FILENAME: + case PREF_OPEN_FILENAME: + case PREF_DIRNAME: + case PREF_COLOR: + //do nothing, dialog signals will update table + pref = NULL; + break; + default: + //Ensure any new preference types are handled + Q_ASSERT(FALSE); + break; + } +} + +/* * 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/models/pref_delegate.h b/ui/qt/models/pref_delegate.h new file mode 100644 index 0000000000..1f693e6ade --- /dev/null +++ b/ui/qt/models/pref_delegate.h @@ -0,0 +1,54 @@ +/* pref_delegate.h + * Delegates for editing prefereneces. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef PREF_DELEGATE_H +#define PREF_DELEGATE_H + +#include <config.h> + +#include <ui/qt/models/pref_models.h> +#include <ui/qt/widgets/syntax_line_edit.h> + +#include <QStyledItemDelegate> +#include <QModelIndex> + +class AdvancedPrefDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + AdvancedPrefDelegate(QObject *parent = 0); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const; + +private: + PrefsItem* indexToPref(const QModelIndex &index) const; +}; + +//Utility class for range preferences +class RangeSyntaxLineEdit : public SyntaxLineEdit +{ + Q_OBJECT +public: + explicit RangeSyntaxLineEdit(QWidget *parent = 0); + void setMaxRange(unsigned int max) {maxRange_ = max;} + +public slots: + void checkRange(QString range); + +private: + unsigned int maxRange_; +}; + +#endif // PREF_DELEGATE_H diff --git a/ui/qt/models/pref_models.cpp b/ui/qt/models/pref_models.cpp new file mode 100644 index 0000000000..5c37035ab4 --- /dev/null +++ b/ui/qt/models/pref_models.cpp @@ -0,0 +1,768 @@ +/* pref_models.cpp + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <ui/qt/models/pref_models.h> +#include <ui/qt/utils/qt_ui_utils.h> +#include <epan/prefs-int.h> + +#ifdef HAVE_LIBPCAP +#ifdef _WIN32 +#include "caputils/capture-wpcap.h" +#endif /* _WIN32 */ +#endif /* HAVE_LIBPCAP */ + +#include <QFont> +#include <QColor> + +// XXX Should we move this to ui/preference_utils? +static GHashTable * pref_ptr_to_pref_ = NULL; +pref_t *prefFromPrefPtr(void *pref_ptr) +{ + return (pref_t *)g_hash_table_lookup(pref_ptr_to_pref_, (gpointer) pref_ptr); +} + +static void prefInsertPrefPtr(void * pref_ptr, pref_t * pref) +{ + if ( ! pref_ptr_to_pref_ ) + pref_ptr_to_pref_ = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); + + gpointer key = (gpointer) pref_ptr; + gpointer val = (gpointer) pref; + + /* Already existing entries will be ignored */ + if ( (pref = (pref_t *)g_hash_table_lookup(pref_ptr_to_pref_, key) ) == NULL ) + g_hash_table_insert(pref_ptr_to_pref_, key, val); +} + +PrefsItem::PrefsItem(module_t *module, pref_t *pref, PrefsItem* parent) + : ModelHelperTreeItem<PrefsItem>(parent), + pref_(pref), + module_(module), + changed_(false) +{ + name_ = QString(module->name ? module->name : module->parent->name); + if (pref_ != NULL) { + name_ += QString(".%1").arg(prefs_get_name(pref_)); + } +} + +PrefsItem::PrefsItem(QString name, PrefsItem* parent) + : ModelHelperTreeItem<PrefsItem>(parent), + pref_(NULL), + module_(NULL), + name_(name), + changed_(false) +{ + +} + +PrefsItem::~PrefsItem() +{ +} + +int PrefsItem::getPrefType() const +{ + if (pref_ == NULL) + return 0; + + return prefs_get_type(pref_); +} + +int PrefsItem::getPrefGUIType() const +{ + if (pref_ == NULL) + return GUI_ALL; + + return prefs_get_gui_type(pref_); +} + +bool PrefsItem::isPrefDefault() const +{ + if (pref_ == NULL) + return true; + + if (changed_ == false) + return prefs_pref_is_default(pref_) ? true : false; + + return false; +} + +QString PrefsItem::getPrefTypeName() const +{ + if (pref_ == NULL) + return ""; + + return QString(prefs_pref_type_name(pref_)); +} + +QString PrefsItem::getModuleName() const +{ + if (module_ == NULL) + return name_; + + return QString(module_->name); +} + + +void PrefsItem::setChanged(bool changed) +{ + changed_ = changed; +} + + +const char* PrefsModel::ADVANCED_PREFERENCE_TREE_NAME = "Advanced"; +const char* PrefsModel::APPEARANCE_PREFERENCE_TREE_NAME = "Appearance"; +const char* PrefsModel::LAYOUT_PREFERENCE_TREE_NAME = "Layout"; +const char* PrefsModel::COLUMNS_PREFERENCE_TREE_NAME = "Columns"; +const char* PrefsModel::FONT_AND_COLORS_PREFERENCE_TREE_NAME = "Font and Colors"; +const char* PrefsModel::CAPTURE_PREFERENCE_TREE_NAME = "Capture"; +const char* PrefsModel::EXPERT_PREFERENCE_TREE_NAME = "Expert"; +const char* PrefsModel::FILTER_BUTTONS_PREFERENCE_TREE_NAME = "Filter Buttons"; + + +PrefsModel::PrefsModel(QObject *parent) : + QAbstractItemModel(parent), + root_(new PrefsItem(QString("ROOT"), NULL)) +{ + populate(); +} + +PrefsModel::~PrefsModel() +{ + delete root_; +} + +int PrefsModel::rowCount(const QModelIndex &parent) const +{ + PrefsItem *parent_item; + if (parent.column() > 0) + return 0; + + if (!parent.isValid()) + parent_item = root_; + else + parent_item = static_cast<PrefsItem*>(parent.internalPointer()); + + if (parent_item == NULL) + return 0; + + return parent_item->childCount(); +} + +int PrefsModel::columnCount(const QModelIndex&) const +{ + return colLast; +} + + +QModelIndex PrefsModel::parent(const QModelIndex& index) const +{ + if (!index.isValid()) + return QModelIndex(); + + PrefsItem* item = static_cast<PrefsItem*>(index.internalPointer()); + if (item != NULL) { + PrefsItem* parent_item = item->parentItem(); + if (parent_item != NULL) { + if (parent_item == root_) + return QModelIndex(); + + return createIndex(parent_item->row(), 0, parent_item); + } + } + + return QModelIndex(); +} + +QModelIndex PrefsModel::index(int row, int column, const QModelIndex& parent) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + PrefsItem *parent_item, *child_item; + + if (!parent.isValid()) + parent_item = root_; + else + parent_item = static_cast<PrefsItem*>(parent.internalPointer()); + + Q_ASSERT(parent_item); + + child_item = parent_item->child(row); + if (child_item) { + return createIndex(row, column, child_item); + } + + return QModelIndex(); +} + +QVariant PrefsModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::UserRole)) + return QVariant(); + + PrefsItem* item = static_cast<PrefsItem*>(index.internalPointer()); + if (item == NULL) + return QVariant(); + + if (role == Qt::UserRole) + return VariantPointer<PrefsItem>::asQVariant(item); + + switch ((enum PrefsModelColumn)index.column()) { + case colName: + return item->getName(); + + case colStatus: + if ((item->getPrefType() == PREF_UAT && (item->getPrefGUIType() == GUI_ALL || item->getPrefGUIType() == GUI_QT)) || item->getPrefType() == PREF_CUSTOM) + return QObject::tr("Unknown"); + + if (item->isPrefDefault()) + return QObject::tr("Default"); + + return QObject::tr("Changed"); + case colType: + return item->getPrefTypeName(); + case colValue: + if (item->getPref() == NULL) + return QVariant(); + + return QString(gchar_free_to_qstring(prefs_pref_to_str(item->getPref(), pref_stashed)).remove(QRegExp("\n\t"))); + default: + break; + } + + return QVariant(); +} + +static guint +fill_prefs(module_t *module, gpointer root_ptr) +{ + PrefsItem* root_item = static_cast<PrefsItem*>(root_ptr); + + if ((module == NULL) || (root_item == NULL)) + return 1; + + if (module->numprefs < 1 && !prefs_module_has_submodules(module)) + return 0; + + PrefsItem* module_item = new PrefsItem(module, NULL, root_item); + root_item->appendChild(module_item); + + 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; + + const char *type_name = prefs_pref_type_name(pref); + if (!type_name) + continue; + + pref_stash(pref, NULL); + + PrefsItem* item = new PrefsItem(module, pref, module_item); + module_item->appendChild(item); + + // .uat is a void * so it wins the "useful key value" prize. + if (prefs_get_uat_value(pref)) { + prefInsertPrefPtr( prefs_get_uat_value(pref), pref); + } + } + + if(prefs_module_has_submodules(module)) + return prefs_modules_foreach_submodules(module, fill_prefs, module_item); + + return 0; +} + +void PrefsModel::populate() +{ + // Printing prefs don't apply here. + module_t *print_module = prefs_find_module("print"); + if (print_module) + print_module->use_gui = FALSE; + + //Since "expert" is really a pseudo protocol, it shouldn't be + //categorized with other "real" protocols when it comes to + //preferences. Since it's just a UAT, don't bury it in + //with the other protocols + module_t *expert_module = prefs_find_module("_ws.expert"); + if (expert_module) + expert_module->use_gui = FALSE; + + prefs_modules_foreach_submodules(NULL, fill_prefs, (gpointer)root_); + + //Add the "specially handled" preferences + PrefsItem *appearance_item, *appearance_subitem, *special_item; + + appearance_item = new PrefsItem(APPEARANCE_PREFERENCE_TREE_NAME, root_); + root_->appendChild(appearance_item); + + appearance_subitem = new PrefsItem(LAYOUT_PREFERENCE_TREE_NAME, appearance_item); + appearance_item->appendChild(appearance_subitem); + appearance_subitem = new PrefsItem(COLUMNS_PREFERENCE_TREE_NAME, appearance_item); + appearance_item->appendChild(appearance_subitem); + appearance_subitem = new PrefsItem(FONT_AND_COLORS_PREFERENCE_TREE_NAME, appearance_item); + appearance_item->appendChild(appearance_subitem); + + special_item = new PrefsItem(CAPTURE_PREFERENCE_TREE_NAME, root_); + root_->appendChild(special_item); + special_item = new PrefsItem(EXPERT_PREFERENCE_TREE_NAME, root_); + root_->appendChild(special_item); + special_item = new PrefsItem(FILTER_BUTTONS_PREFERENCE_TREE_NAME, root_); + root_->appendChild(special_item); + special_item = new PrefsItem(ADVANCED_PREFERENCE_TREE_NAME, root_); + root_->appendChild(special_item); +} + + + + + +AdvancedPrefsModel::AdvancedPrefsModel(QObject * parent) +: QSortFilterProxyModel(parent), +filter_() +{ +} + +QVariant AdvancedPrefsModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + + switch (section) { + case colName: + return tr("Name"); + case colStatus: + return tr("Status"); + case colType: + return tr("Type"); + case colValue: + return tr("Value"); + default: + break; + } + } + return QVariant(); +} + +QVariant AdvancedPrefsModel::data(const QModelIndex &dataindex, int role) const +{ + if (!dataindex.isValid()) + return QVariant(); + + QModelIndex modelIndex = mapToSource(dataindex); + + PrefsItem* item = static_cast<PrefsItem*>(modelIndex.internalPointer()); + if (item == NULL) + return QVariant(); + + switch (role) + { + case Qt::DisplayRole: + switch ((AdvancedPrefsModelColumn)dataindex.column()) + { + case colName: + if (item->getPref() == NULL) + return item->getModule()->title; + + return sourceModel()->data(sourceModel()->index(modelIndex.row(), PrefsModel::colName, modelIndex.parent()), role); + case colStatus: + if (item->getPref() == NULL) + return QVariant(); + + return sourceModel()->data(sourceModel()->index(modelIndex.row(), PrefsModel::colStatus, modelIndex.parent()), role); + case colType: + if (item->getPref() == NULL) + return QVariant(); + + return sourceModel()->data(sourceModel()->index(modelIndex.row(), PrefsModel::colType, modelIndex.parent()), role); + case colValue: + if (item->getPref() == NULL) + return QVariant(); + + return sourceModel()->data(sourceModel()->index(modelIndex.row(), PrefsModel::colValue, modelIndex.parent()), role); + default: + break; + } + break; + case Qt::ToolTipRole: + switch ((AdvancedPrefsModelColumn)dataindex.column()) + { + case colName: + if (item->getPref() == NULL) + return QString("<span>%1</span>").arg(item->getModule()->description); + + return QString("<span>%1</span>").arg(prefs_get_description(item->getPref())); + case colStatus: + if (item->getPref() == NULL) + return QVariant(); + + return QObject::tr("Has this preference been changed?"); + case colType: + if (item->getPref() == NULL) { + return QVariant(); + } else { + QString type_desc = gchar_free_to_qstring(prefs_pref_type_description(item->getPref())); + return QString("<span>%1</span>").arg(type_desc); + } + break; + case colValue: + if (item->getPref() == NULL) { + return QVariant(); + } else { + QString default_value = gchar_free_to_qstring(prefs_pref_to_str(item->getPref(), pref_stashed)); + return QString("<span>%1</span>").arg( + default_value.isEmpty() ? default_value : QObject::tr("Default value is empty")); + } + default: + break; + } + break; + case Qt::FontRole: + if (item->getPref() == NULL) + return QVariant(); + + if (!item->isPrefDefault() && + /* UATs and custom preferences are "unknown", that shouldn't mean that they are always bolded */ + item->getPrefType() != PREF_UAT && item->getPrefType() != PREF_CUSTOM) { + QFont font; + font.setBold(true); + return font; + } + break; + case Qt::UserRole: + return sourceModel()->data(modelIndex, role); + default: + break; + } + + return QVariant(); +} + +bool AdvancedPrefsModel::setData(const QModelIndex &dataindex, const QVariant &value, int role) +{ + if ((!dataindex.isValid()) || (role != Qt::EditRole)) + return false; + + QModelIndex modelIndex = mapToSource(dataindex); + + PrefsItem* item = static_cast<PrefsItem*>(modelIndex.internalPointer()); + if (item == NULL) + return false; + + if (value.isNull()) { + //reset preference to default + reset_stashed_pref(item->getPref()); + item->setChanged(false); + } else { + item->setChanged(true); + switch (item->getPrefType()) + { + case PREF_DECODE_AS_UINT: + case PREF_UINT: + { + bool ok; + guint new_val = value.toString().toUInt(&ok, prefs_get_uint_base(item->getPref())); + + if (ok) + prefs_set_uint_value(item->getPref(), new_val, pref_stashed); + } + break; + case PREF_BOOL: + prefs_invert_bool_value(item->getPref(), pref_stashed); + break; + case PREF_ENUM: + prefs_set_enum_value(item->getPref(), value.toInt(), pref_stashed); + break; + case PREF_STRING: + prefs_set_string_value(item->getPref(), value.toString().toStdString().c_str(), pref_stashed); + break; + case PREF_DECODE_AS_RANGE: + case PREF_RANGE: + prefs_set_stashed_range_value(item->getPref(), value.toString().toUtf8().constData()); + break; + case PREF_SAVE_FILENAME: + case PREF_OPEN_FILENAME: + case PREF_DIRNAME: + prefs_set_string_value(item->getPref(), value.toString().toStdString().c_str(), pref_stashed); + break; + case PREF_COLOR: + { + QColor qc(value.toString()); + color_t color; + + color.red = qc.red() << 8 | qc.red(); + color.green = qc.green() << 8 | qc.green(); + color.blue = qc.blue() << 8 | qc.blue(); + + prefs_set_color_value(item->getPref(), color, pref_stashed); + break; + } + } + } + +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + QVector<int> roles; + roles << role; +#endif + + // The status field may change as well as the value, so mark them for update + emit dataChanged(index(dataindex.row(), AdvancedPrefsModel::colStatus), + index(dataindex.row(), AdvancedPrefsModel::colValue) +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + , roles +#endif + ); + + return true; +} + +Qt::ItemFlags AdvancedPrefsModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + + QModelIndex modelIndex = mapToSource(index); + + PrefsItem* item = static_cast<PrefsItem*>(modelIndex.internalPointer()); + if (item == NULL) + return 0; + + Qt::ItemFlags flags = QAbstractItemModel::flags(index); + if (item->getPref() == NULL) { + /* Base modules aren't changable */ + flags &= ~(Qt::ItemIsEnabled | Qt::ItemIsSelectable); + } else { + flags |= Qt::ItemIsEditable; + } + + return flags; +} + + +int AdvancedPrefsModel::columnCount(const QModelIndex&) const +{ + return colLast; +} + +void AdvancedPrefsModel::setFirstColumnSpanned(QTreeView* tree, const QModelIndex& mIndex) +{ + int childCount, row; + PrefsItem* item; + if (mIndex.isValid()) { + item = VariantPointer<PrefsItem>::asPtr(data(mIndex, Qt::UserRole)); + if (item != NULL) { + childCount = item->childCount(); + if (childCount > 0) { + tree->setFirstColumnSpanned(mIndex.row(), mIndex.parent(), true); + for (row = 0; row < childCount; row++) { + setFirstColumnSpanned(tree, mIndex.child(row, 0)); + } + } + } + } else { + for (row = 0; row < rowCount(); row++) { + setFirstColumnSpanned(tree, index(row, 0)); + } + } +} + +bool AdvancedPrefsModel::filterAcceptItem(PrefsItem& item) const +{ + if (filter_.isEmpty()) + return true; + + QString name, tooltip; + if (item.getPref() == NULL) { + name = item.getModule()->title; + tooltip = item.getModule()->description; + } else { + name = QString(item.getModule()->name ? item.getModule()->name : item.getModule()->parent->name); + name += QString(".%1").arg(prefs_get_name(item.getPref())); + tooltip = prefs_get_description(item.getPref()); + } + + if (name.contains(filter_, Qt::CaseInsensitive) || tooltip.contains(filter_, Qt::CaseInsensitive)) + return true; + + PrefsItem *child_item; + for (int child_row = 0; child_row < item.childCount(); child_row++) + { + child_item = item.child(child_row); + if ((child_item != NULL) && (filterAcceptItem(*child_item))) + return true; + } + + return false; +} + +bool AdvancedPrefsModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + QModelIndex nameIdx = sourceModel()->index(sourceRow, PrefsModel::colName, sourceParent); + PrefsItem* item = static_cast<PrefsItem*>(nameIdx.internalPointer()); + if (item == NULL) + return true; + + //filter out the "special" preferences + if ((item->getModule() == NULL) && (item->getPref() == NULL)) + return false; + + if (filterAcceptItem(*item)) + return true; + + return false; +} + +void AdvancedPrefsModel::setFilter(const QString& filter) +{ + filter_ = filter; + invalidateFilter(); +} + + + + + +ModulePrefsModel::ModulePrefsModel(QObject* parent) + : QSortFilterProxyModel(parent) + , advancedPrefName_(PrefsModel::ADVANCED_PREFERENCE_TREE_NAME) +{ +} + +QVariant ModulePrefsModel::data(const QModelIndex &dataindex, int role) const +{ + if (!dataindex.isValid()) + return QVariant(); + + QModelIndex modelIndex = mapToSource(dataindex); + + PrefsItem* item = static_cast<PrefsItem*>(modelIndex.internalPointer()); + if (item == NULL) + return QVariant(); + + switch (role) + { + case Qt::DisplayRole: + switch ((ModulePrefsModelColumn)dataindex.column()) + { + case colName: + if (item->getPref() == NULL) { + if (item->getModule() == NULL) { + return item->getName(); + } + + return item->getModule()->title; + } + + return sourceModel()->data(sourceModel()->index(modelIndex.row(), PrefsModel::colName, modelIndex.parent()), role); + default: + break; + } + break; + case Qt::UserRole: + return sourceModel()->data(modelIndex, role); + case ModuleName: + return item->getModuleName(); + default: + break; + } + + return QVariant(); +} +Qt::ItemFlags ModulePrefsModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + + bool disable_capture = true; +#ifdef HAVE_LIBPCAP +#ifdef _WIN32 + /* Is WPcap loaded? */ + if (has_wpcap) { +#endif /* _WIN32 */ + disable_capture = false; +#ifdef _WIN32 + } +#endif /* _WIN32 */ +#endif /* HAVE_LIBPCAP */ + + Qt::ItemFlags flags = QAbstractItemModel::flags(index); + if (disable_capture) { + QModelIndex modelIndex = mapToSource(index); + + PrefsItem* item = static_cast<PrefsItem*>(modelIndex.internalPointer()); + if (item == NULL) + return flags; + + if (item->getName().compare(PrefsModel::CAPTURE_PREFERENCE_TREE_NAME) == 0) { + flags &= (~Qt::ItemIsEnabled); + } + } + + return flags; +} + +int ModulePrefsModel::columnCount(const QModelIndex&) const +{ + return colLast; +} + +bool ModulePrefsModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const +{ + //Force "Advanced" preferences to be at bottom of model + if (source_left.isValid() && !source_left.parent().isValid() && + source_right.isValid() && !source_right.parent().isValid()) { + PrefsItem* left_item = static_cast<PrefsItem*>(source_left.internalPointer()); + PrefsItem* right_item = static_cast<PrefsItem*>(source_right.internalPointer()); + if ((left_item != NULL) && (left_item->getName().compare(advancedPrefName_) == 0)) { + return false; + } + if ((right_item != NULL) && (right_item->getName().compare(advancedPrefName_) == 0)) { + return true; + } + } + + + return QSortFilterProxyModel::lessThan(source_left, source_right); +} + +bool ModulePrefsModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + QModelIndex nameIdx = sourceModel()->index(sourceRow, PrefsModel::colName, sourceParent); + PrefsItem* item = static_cast<PrefsItem*>(nameIdx.internalPointer()); + if (item == NULL) + return true; + + if (item->getPref() != NULL) + return false; + + if (item->getModule() != NULL) { + if (!item->getModule()->use_gui) { + return false; + } + } + + return true; +} + + + + +/* + * 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/models/pref_models.h b/ui/qt/models/pref_models.h new file mode 100644 index 0000000000..4914e61133 --- /dev/null +++ b/ui/qt/models/pref_models.h @@ -0,0 +1,173 @@ +/* pref_models.h + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef PREF_MODELS_H +#define PREF_MODELS_H + +#include <config.h> + +#include <ui/qt/models/tree_model_helpers.h> + +#include <epan/prefs.h> + +#include <QSortFilterProxyModel> +#include <QTreeView> + +class PrefsItem : public ModelHelperTreeItem<PrefsItem> +{ +public: + PrefsItem(module_t *module, pref_t *pref, PrefsItem* parent); + PrefsItem(QString name, PrefsItem* parent); + virtual ~PrefsItem(); + + QString getName() const {return name_;} + pref_t* getPref() const {return pref_;} + int getPrefType() const; + int getPrefGUIType() const; + bool isPrefDefault() const; + QString getPrefTypeName() const; + module_t* getModule() const {return module_;} + QString getModuleName() const; + void setChanged(bool changed = true); + +private: + pref_t *pref_; + module_t *module_; + QString name_; + //set to true if changed during module manipulation + //Used to determine proper "default" for comparison + bool changed_; +}; + + +class PrefsModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit PrefsModel(QObject * parent = Q_NULLPTR); + virtual ~PrefsModel(); + + //Names of special preferences handled by the GUI + //Names used as keys to determine correct pan displayed + static const char* ADVANCED_PREFERENCE_TREE_NAME; + static const char* APPEARANCE_PREFERENCE_TREE_NAME; + static const char* LAYOUT_PREFERENCE_TREE_NAME; + static const char* COLUMNS_PREFERENCE_TREE_NAME; + static const char* FONT_AND_COLORS_PREFERENCE_TREE_NAME; + static const char* CAPTURE_PREFERENCE_TREE_NAME; + static const char* EXPERT_PREFERENCE_TREE_NAME; + static const char* FILTER_BUTTONS_PREFERENCE_TREE_NAME; + + enum PrefsModelColumn { + colName = 0, + colStatus, + colType, + colValue, + colLast + }; + + QModelIndex index(int row, int column, + const QModelIndex & = QModelIndex()) const; + QModelIndex parent(const QModelIndex &) const; + QVariant data(const QModelIndex &index, int role) const; + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + +private: + void populate(); + + PrefsItem* root_; +}; + +class AdvancedPrefsModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + + explicit AdvancedPrefsModel(QObject * parent = Q_NULLPTR); + + enum AdvancedPrefsModelColumn { + colName = 0, + colStatus, + colType, + colValue, + colLast + }; + + virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + + void setFilter(const QString& filter); + + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + QVariant data(const QModelIndex &index, int role) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + //Keep the internals of model hidden from tree + void setFirstColumnSpanned(QTreeView* tree, const QModelIndex &index = QModelIndex()); + +protected: + bool filterAcceptItem(PrefsItem& item) const; + +private: + + QString filter_; +}; + +class ModulePrefsModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + + explicit ModulePrefsModel(QObject * parent = Q_NULLPTR); + + enum ModulePrefsModelColumn { + colName = 0, + colLast + }; + + enum ModulePrefsRoles { + ModuleName = Qt::UserRole + 1 + }; + + QVariant data(const QModelIndex &index, int role) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + +protected: + bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; + +private: + //cache of the translated "Advanced" preference name + QString advancedPrefName_; +}; + +extern pref_t *prefFromPrefPtr(void *pref_ptr); + +#endif // PREF_MODELS_H + +/* + * 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/packet_list.cpp b/ui/qt/packet_list.cpp index 16e545e96d..891ff4585a 100644 --- a/ui/qt/packet_list.cpp +++ b/ui/qt/packet_list.cpp @@ -47,6 +47,7 @@ #include <ui/qt/utils/data_printer.h> #include <ui/qt/utils/frame_information.h> #include <ui/qt/utils/variant_pointer.h> +#include <ui/qt/models/pref_models.h> #include <QAction> #include <QActionGroup> @@ -1362,7 +1363,7 @@ void PacketList::headerMenuTriggered() recent_set_column_xalign(header_ctx_column_, checked ? COLUMN_XALIGN_RIGHT : COLUMN_XALIGN_DEFAULT); break; case caColumnPreferences: - emit showColumnPreferences(PreferencesDialog::ppColumn); + emit showColumnPreferences(PrefsModel::COLUMNS_PREFERENCE_TREE_NAME); break; case caEditColumn: emit editColumn(header_ctx_column_); diff --git a/ui/qt/packet_list.h b/ui/qt/packet_list.h index 2ee97fe338..6d2eed23cc 100644 --- a/ui/qt/packet_list.h +++ b/ui/qt/packet_list.h @@ -4,19 +4,7 @@ * 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. + * SPDX-License-Identifier: GPL-2.0+ */ #ifndef PACKET_LIST_H @@ -24,7 +12,6 @@ #include "byte_view_tab.h" #include <ui/qt/models/packet_list_model.h> -#include "preferences_dialog.h" #include "proto_tree.h" #include "protocol_preferences_menu.h" #include <ui/qt/models/related_packet_delegate.h> @@ -150,7 +137,7 @@ private: signals: void packetDissectionChanged(); - void showColumnPreferences(PreferencesDialog::PreferencesPane start_pane); + void showColumnPreferences(QString pane_name); void editColumn(int column); void packetListScrolled(bool at_end); void showProtocolPreferences(const QString module_name); diff --git a/ui/qt/preferences_dialog.cpp b/ui/qt/preferences_dialog.cpp index 3592ca2e68..c2ef0a799a 100644 --- a/ui/qt/preferences_dialog.cpp +++ b/ui/qt/preferences_dialog.cpp @@ -4,19 +4,7 @@ * 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. + * SPDX-License-Identifier: GPL-2.0+ */ #include "preferences_dialog.h" @@ -24,12 +12,6 @@ #include "module_preferences_scroll_area.h" -#ifdef HAVE_LIBPCAP -#ifdef _WIN32 -#include "caputils/capture-wpcap.h" -#endif /* _WIN32 */ -#endif /* HAVE_LIBPCAP */ - #include <epan/prefs-int.h> #include <epan/decode_as.h> #include <ui/language.h> @@ -38,300 +20,12 @@ #include <ui/recent.h> #include <main_window.h> -#include <ui/qt/widgets/syntax_line_edit.h> -#include <ui/qt/utils/qt_ui_utils.h> -#include "uat_dialog.h" #include "wireshark_application.h" -#include <ui/qt/utils/variant_pointer.h> - -#include <QColorDialog> -#include <QComboBox> -#include <QFileDialog> -#include <QFrame> -#include <QHBoxLayout> -#include <QKeyEvent> -#include <QLineEdit> -#include <QMessageBox> -#include <QSpacerItem> -#include <QTreeWidgetItemIterator> - -// XXX Should we move this to ui/preference_utils? -static GHashTable * pref_ptr_to_pref_ = NULL; -pref_t *prefFromPrefPtr(void *pref_ptr) -{ - return (pref_t *)g_hash_table_lookup(pref_ptr_to_pref_, (gpointer) pref_ptr); -} - -static void prefInsertPrefPtr(void * pref_ptr, pref_t * pref) -{ - if ( ! pref_ptr_to_pref_ ) - pref_ptr_to_pref_ = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); - - gpointer key = (gpointer) pref_ptr; - gpointer val = (gpointer) pref; - - /* Already existing entries will be ignored */ - if ( (pref = (pref_t *)g_hash_table_lookup(pref_ptr_to_pref_, key) ) == NULL ) - g_hash_table_insert(pref_ptr_to_pref_, key, val); -} - -enum { - module_type_ = 1000, - advanced_type_ -}; - -enum { - adv_name_col_, - adv_status_col_, - adv_type_col_, - adv_value_col_ -}; - -enum { - stacked_role_ = Qt::UserRole + 1, // pd_ui_->stackedWidget - module_name_role_, // QString - mpsa_role_ // QWidget * -}; - -class AdvancedPrefTreeWidgetItem : public QTreeWidgetItem -{ -public: - AdvancedPrefTreeWidgetItem(pref_t *pref, module_t *module) : - QTreeWidgetItem (advanced_type_), - pref_(pref), - module_(module) - {} - pref_t *pref() { return pref_; } - void updatePref() { emitDataChanged(); } - - virtual QVariant data(int column, int role) const { - bool is_default = prefs_pref_is_default(pref_); - switch (role) { - case Qt::DisplayRole: - switch (column) { - case adv_name_col_: - { - QString full_name = QString(module_->name ? module_->name : module_->parent->name); - full_name += QString(".%1").arg(prefs_get_name(pref_)); - return full_name; - } - case adv_status_col_: - if ((prefs_get_type(pref_) == PREF_UAT && (prefs_get_gui_type(pref_) == GUI_ALL || prefs_get_gui_type(pref_) == GUI_QT))|| prefs_get_type(pref_) == PREF_CUSTOM) { - return QObject::tr("Unknown"); - } else if (is_default) { - return QObject::tr("Default"); - } else { - return QObject::tr("Changed"); - } - case adv_type_col_: - return QString(prefs_pref_type_name(pref_)); - case adv_value_col_: - { - QString cur_value = gchar_free_to_qstring(prefs_pref_to_str(pref_, pref_stashed)).remove(QRegExp("\n\t")); - return cur_value; - } - default: - break; - } - break; - case Qt::ToolTipRole: - switch (column) { - case adv_name_col_: - return QString("<span>%1</span>").arg(prefs_get_description(pref_)); - case adv_status_col_: - return QObject::tr("Has this preference been changed?"); - case adv_type_col_: - { - QString type_desc = gchar_free_to_qstring(prefs_pref_type_description(pref_)); - return QString("<span>%1</span>").arg(type_desc); - } - case adv_value_col_: - { - QString default_value = gchar_free_to_qstring(prefs_pref_to_str(pref_, pref_stashed)); - return QString("<span>%1</span>").arg( - default_value.isEmpty() ? default_value : QObject::tr("Default value is empty")); - } - default: - break; - } - break; - case Qt::FontRole: - if (!is_default && treeWidget()) { - QFont font = treeWidget()->font(); - font.setBold(true); - return font; - } - break; - default: - break; - } - return QTreeWidgetItem::data(column, role); - } - -private: - pref_t *pref_; - module_t *module_; -}; - -class ModulePrefTreeWidgetItem : public QTreeWidgetItem -{ -public: - ModulePrefTreeWidgetItem(QTreeWidgetItem *parent, module_t *module) : - QTreeWidgetItem (parent, module_type_), - module_(module), - mpsa_(0) - {} - void ensureModulePreferencesScrollArea(QStackedWidget *sw) { - /* - * We create pages for interior nodes even if they don't have - * preferences, so that we at least have something to show - * if the user clicks on them, even if it's empty. - */ - - /* Scrolled window */ - if (!mpsa_) { - mpsa_ = new ModulePreferencesScrollArea(module_); - if (sw->indexOf(mpsa_) < 0) sw->addWidget(mpsa_); - } - } - - virtual QVariant data(int column, int role) const { - if (column == 0) { - switch (role) { - case Qt::DisplayRole: - return QString(module_->title); - case module_name_role_: - return QString (module_->name); - case mpsa_role_: - return qVariantFromValue(mpsa_); - default: - break; - } - } - return QTreeWidgetItem::data(column, role); - } - -private: - module_t *module_; - QWidget *mpsa_; -}; - extern "C" { // Callbacks prefs routines static guint -fill_advanced_prefs(module_t *module, gpointer root_ptr) -{ - QTreeWidgetItem *root_item = static_cast<QTreeWidgetItem *>(root_ptr); - - if (!module || !root_item) return 1; - - if (module->numprefs < 1 && !prefs_module_has_submodules(module)) return 0; - - QString module_title = module->title; - - QTreeWidgetItem *tl_item = new QTreeWidgetItem(root_item); - tl_item->setText(0, module_title); - tl_item->setToolTip(0, QString("<span>%1</span>").arg(module->description)); - tl_item->setFirstColumnSpanned(true); - Qt::ItemFlags item_flags = tl_item->flags(); - item_flags &= ~(Qt::ItemIsEnabled | Qt::ItemIsSelectable); - tl_item->setFlags(item_flags); - - - QList<QTreeWidgetItem *>tl_children; - 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; - - const char *type_name = prefs_pref_type_name(pref); - if (!type_name) continue; - - pref_stash(pref, NULL); - - AdvancedPrefTreeWidgetItem *item = new AdvancedPrefTreeWidgetItem(pref, module); - tl_children << item; - - // .uat is a void * so it wins the "useful key value" prize. - if (prefs_get_uat_value(pref)) { - prefInsertPrefPtr( prefs_get_uat_value(pref), pref); - } - } - tl_item->addChildren(tl_children); - - if(prefs_module_has_submodules(module)) - return prefs_modules_foreach_submodules(module, fill_advanced_prefs, tl_item); - - return 0; -} - -static guint -pref_exists(pref_t *, gpointer) -{ - return 1; -} - -static guint -fill_module_prefs(module_t *module, gpointer ti_ptr) -{ - QTreeWidgetItem *item = static_cast<QTreeWidgetItem *>(ti_ptr); - - if (!item) return 0; - - QStackedWidget *stacked_widget = VariantPointer<QStackedWidget>::asPtr(item->data(0, stacked_role_)); - - if (!stacked_widget) return 0; - - if (!module->use_gui) { - /* This module uses its own GUI interface to modify its - * preferences, so ignore it - */ - return 0; - } - - /* - * Is this module an interior node, with modules underneath it? - */ - if (!prefs_module_has_submodules(module)) { - /* - * No. - * Does it have any preferences (other than possibly obsolete ones)? - */ - if (prefs_pref_foreach(module, pref_exists, NULL) == 0) { - /* - * No. Don't put the module into the preferences window, - * as there's nothing to show. - * - * XXX - we should do the same for interior ndes; if the module - * has no non-obsolete preferences *and* nothing under it has - * non-obsolete preferences, don't put it into the window. - */ - return 0; - } - } - - /* - * Add this module to the tree. - */ - ModulePrefTreeWidgetItem *new_mpti = new ModulePrefTreeWidgetItem(item, module); - new_mpti->setData(0, stacked_role_, item->data(0, stacked_role_)); - - /* - * Is this an interior node? - */ - if (prefs_module_has_submodules(module)) { - /* - * Yes. Walk the subtree and attach stuff to it. - */ - prefs_modules_foreach_submodules(module, fill_module_prefs, (gpointer) new_mpti); - } - - return 0; -} - -static guint module_prefs_unstash(module_t *module, gpointer data) { gboolean *must_redissect_p = (gboolean *)data; @@ -381,89 +75,58 @@ module_prefs_clean_stash(module_t *module, gpointer) } // extern "C" // Preference tree items -const int appearance_item_ = 0; -const int capture_item_ = 1; +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), - cur_pref_type_(0), - cur_line_edit_(NULL), - cur_combo_box_(NULL), - saved_combo_idx_(0) + model_(this), + advancedPrefsModel_(this), + advancedPrefsDelegate_(this), + modulePrefsModel_(this) { - QTreeWidgetItem tmp_item; // Adding pre-populated top-level items is much faster - prefs_modules_foreach_submodules(NULL, fill_advanced_prefs, (gpointer) &tmp_item); + advancedPrefsModel_.setSourceModel(&model_); + modulePrefsModel_.setSourceModel(&model_); // Some classes depend on pref_ptr_to_pref_ so this MUST be called after - // fill_advanced_prefs. + // model_.populate(). pd_ui_->setupUi(this); loadGeometry(); setWindowTitle(wsApp->windowTitleString(tr("Preferences"))); - pd_ui_->advancedTree->invisibleRootItem()->addChildren(tmp_item.takeChildren()); + + 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); - pd_ui_->prefsTree->invisibleRootItem()->child(appearance_item_)->setExpanded(true); + //Set the Appearance leaf to expanded + pd_ui_->prefsView->setExpanded(modulePrefsModel_.index(APPEARANCE_ITEM, 0), true); - bool disable_capture = true; -#ifdef HAVE_LIBPCAP -#ifdef _WIN32 - /* Is WPcap loaded? */ - if (has_wpcap) { -#endif /* _WIN32 */ - disable_capture = false; -#ifdef _WIN32 - } -#endif /* _WIN32 */ -#endif /* HAVE_LIBPCAP */ - pd_ui_->prefsTree->invisibleRootItem()->child(capture_item_)->setDisabled(disable_capture); - - // PreferencesPane, prefsTree, and stackedWidget must all correspond to each other. - // This may not be the best way to go about enforcing that. - QTreeWidgetItem *item = pd_ui_->prefsTree->topLevelItem(0); - item->setSelected(true); - pd_ui_->stackedWidget->setCurrentIndex(0); - for (int i = 0; i < pd_ui_->stackedWidget->count() && item; i++) { - item->setData(0, mpsa_role_, qVariantFromValue(pd_ui_->stackedWidget->widget(i))); - item = pd_ui_->prefsTree->itemBelow(item); - } - item = pd_ui_->prefsTree->topLevelItem(0); - prefs_pane_to_item_[ppAppearance] = item; - prefs_pane_to_item_[ppLayout] = item->child(0); - prefs_pane_to_item_[ppColumn] = item->child(1); - prefs_pane_to_item_[ppFontAndColor] = item->child(2); - prefs_pane_to_item_[ppCapture] = pd_ui_->prefsTree->topLevelItem(1); - prefs_pane_to_item_[ppExpert] = pd_ui_->prefsTree->topLevelItem(2); - prefs_pane_to_item_[ppFilterExpressions] = pd_ui_->prefsTree->topLevelItem(3); - pd_ui_->filterExpressonsFrame->setUat(uat_get_table_by_name("Display expressions")); - - // Printing prefs don't apply here. - module_t *print_module = prefs_find_module("print"); - if (print_module) - print_module->use_gui = FALSE; + // 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; - //Since "expert" is really a pseudo protocol, it shouldn't be - //categorized with other "real" protocols when it comes to - //preferences. Since it's just a UAT, don't bury it in - //with the other protocols + 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")); - module_t *expert_module = prefs_find_module("_ws.expert"); - if (expert_module) - expert_module->use_gui = FALSE; - - // We called takeChildren above so this shouldn't be necessary. - while (tmp_item.childCount() > 0) { - tmp_item.removeChild(tmp_item.child(0)); - } - tmp_item.setData(0, stacked_role_, VariantPointer<QStackedWidget>::asQVariant(pd_ui_->stackedWidget)); - prefs_modules_foreach_submodules(NULL, fill_module_prefs, (gpointer) &tmp_item); - pd_ui_->prefsTree->invisibleRootItem()->insertChildren( - pd_ui_->prefsTree->invisibleRootItem()->childCount() - 1, tmp_item.takeChildren()); + connect(pd_ui_->prefsView, SIGNAL(goToPane(QString)), this, SLOT(selectPane(QString))); } PreferencesDialog::~PreferencesDialog() @@ -472,418 +135,68 @@ PreferencesDialog::~PreferencesDialog() prefs_modules_foreach_submodules(NULL, module_prefs_clean_stash, NULL); } -void PreferencesDialog::setPane(PreferencesDialog::PreferencesPane start_pane) +void PreferencesDialog::setPane(const QString pane_name) { - if (prefs_pane_to_item_.contains(start_pane)) { - pd_ui_->prefsTree->setCurrentItem(prefs_pane_to_item_[start_pane]); - } -} - -// Only valid for ModulePrefTreeWidgetItems. -void PreferencesDialog::setPane(const QString module_name) -{ - QTreeWidgetItemIterator pref_it(pd_ui_->prefsTree); - while (*pref_it) { - if ((*pref_it)->type() == module_type_) { - ModulePrefTreeWidgetItem *mp_ti = dynamic_cast<ModulePrefTreeWidgetItem *>(*pref_it); - // Ensure that the module's scroll area exists and that it's in the - // widget stack. - if (mp_ti) { - QString mpsa_name = (*pref_it)->data(0, module_name_role_).toString(); - if (mpsa_name == module_name) { - mp_ti->ensureModulePreferencesScrollArea(pd_ui_->stackedWidget); - QWidget *mpsa = (*pref_it)->data(0, mpsa_role_).value<QWidget *>(); - if (mpsa) { - pd_ui_->prefsTree->setCurrentItem((*pref_it)); - break; - } - } - } - } - ++pref_it; - } + pd_ui_->prefsView->setPane(pane_name); } void PreferencesDialog::showEvent(QShowEvent *) { QStyleOption style_opt; - int new_prefs_tree_width = pd_ui_->prefsTree->style()->subElementRect(QStyle::SE_TreeViewDisclosureItem, &style_opt).left(); + int new_prefs_tree_width = pd_ui_->prefsView->style()->subElementRect(QStyle::SE_TreeViewDisclosureItem, &style_opt).left(); QList<int> sizes = pd_ui_->splitter->sizes(); #ifdef Q_OS_WIN new_prefs_tree_width *= 2; #endif - pd_ui_->prefsTree->resizeColumnToContents(0); - new_prefs_tree_width += pd_ui_->prefsTree->columnWidth(0); - pd_ui_->prefsTree->setMinimumWidth(new_prefs_tree_width); + 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_->advancedTree->expandAll(); - pd_ui_->advancedTree->setSortingEnabled(true); - pd_ui_->advancedTree->sortByColumn(0, Qt::AscendingOrder); + pd_ui_->advancedView->expandAll(); + pd_ui_->advancedView->setSortingEnabled(true); + pd_ui_->advancedView->sortByColumn(AdvancedPrefsModel::colName, Qt::AscendingOrder); int one_em = fontMetrics().height(); - pd_ui_->advancedTree->setColumnWidth(adv_name_col_, one_em * 12); // Don't let long items widen things too much - pd_ui_->advancedTree->resizeColumnToContents(adv_status_col_); - pd_ui_->advancedTree->resizeColumnToContents(adv_type_col_); - pd_ui_->advancedTree->setColumnWidth(adv_value_col_, one_em * 30); -} - -void PreferencesDialog::keyPressEvent(QKeyEvent *evt) -{ - if (cur_line_edit_ && cur_line_edit_->hasFocus()) { - switch (evt->key()) { - case Qt::Key_Escape: - cur_line_edit_->setText(saved_string_pref_); - /* Fall Through */ - case Qt::Key_Enter: - case Qt::Key_Return: - switch (cur_pref_type_) { - case PREF_UINT: - uintPrefEditingFinished(); - break; - case PREF_STRING: - stringPrefEditingFinished(); - break; - case PREF_RANGE: - rangePrefEditingFinished(); - 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_); - /* Fall Through */ - case Qt::Key_Enter: - case Qt::Key_Return: - // XXX The combo box eats enter and return - enumPrefCurrentIndexChanged(cur_combo_box_->currentIndex()); - delete cur_combo_box_; - return; - default: - break; - } - } - QDialog::keyPressEvent(evt); -} - -void PreferencesDialog::on_prefsTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *) -{ - if (!current) return; - QWidget *new_item = NULL; - - // "current" might be a QTreeWidgetItem from our .ui file, e.g. "Columns" - // or a ModulePrefTreeWidgetItem created by fill_module_prefs, e.g. a - // protocol preference. If it's the latter, ensure that the module's - // scroll area exists and that it's in the widget stack. - if (current->type() == module_type_) { - ModulePrefTreeWidgetItem *mp_ti = dynamic_cast<ModulePrefTreeWidgetItem *>(current); - if (mp_ti) mp_ti->ensureModulePreferencesScrollArea(pd_ui_->stackedWidget); - } - - new_item = current->data(0, mpsa_role_).value<QWidget *>(); - g_assert(new_item != NULL); - pd_ui_->stackedWidget->setCurrentWidget(new_item); -} - -void PreferencesDialog::on_advancedSearchLineEdit_textEdited(const QString &search_re) -{ - QTreeWidgetItemIterator branch_it(pd_ui_->advancedTree); - QRegExp regex(search_re, Qt::CaseInsensitive); - - // Hide or show everything - while (*branch_it) { - (*branch_it)->setHidden(!search_re.isEmpty()); - ++branch_it; - } - if (search_re.isEmpty()) return; - - // 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)->type() == advanced_type_) { - - if ((*pref_it)->text(0).contains(regex) || - (*pref_it)->toolTip(0).contains(regex)) { - hidden = false; - } - - (*pref_it)->setHidden(hidden); - if (!hidden) { - QTreeWidgetItem *parent = (*pref_it)->parent(); - while (parent) { - parent->setHidden(false); - parent = parent->parent(); - } - } - } - ++pref_it; - } + 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::on_advancedTree_currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *previous) +void PreferencesDialog::selectPane(QString pane) { - if (previous && pd_ui_->advancedTree->itemWidget(previous, 3)) { - pd_ui_->advancedTree->removeItemWidget(previous, 3); - } -} - -void PreferencesDialog::on_advancedTree_itemActivated(QTreeWidgetItem *item, int column) -{ - AdvancedPrefTreeWidgetItem *adv_ti; - pref_t *pref = NULL; - - if (item->type() == advanced_type_) { - adv_ti = dynamic_cast<AdvancedPrefTreeWidgetItem *>(item); - if (adv_ti) pref = adv_ti->pref(); - } - - if (!pref || cur_line_edit_ || cur_combo_box_) return; - - if (column < 3) { // Reset to default - reset_stashed_pref(pref); - adv_ti->updatePref(); + if (prefs_pane_to_item_.contains(pane)) { + pd_ui_->stackedWidget->setCurrentWidget(prefs_pane_to_item_[pane]); } else { - QWidget *editor = NULL; - - switch (prefs_get_type(pref)) { - case PREF_DECODE_AS_UINT: - case PREF_UINT: - { - char* tmpstr = prefs_pref_to_str(pref, pref_stashed); - cur_line_edit_ = new QLineEdit(); -// cur_line_edit_->setInputMask("0000000009;"); - saved_string_pref_ = tmpstr; - g_free(tmpstr); - connect(cur_line_edit_, SIGNAL(editingFinished()), this, SLOT(uintPrefEditingFinished())); - editor = cur_line_edit_; - break; - } - case PREF_BOOL: - prefs_invert_bool_value(pref, pref_stashed); - adv_ti->updatePref(); - break; - case PREF_ENUM: - { - cur_combo_box_ = new QComboBox(); - const enum_val_t *ev; - for (ev = prefs_get_enumvals(pref); ev && ev->description; ev++) { - cur_combo_box_->addItem(ev->description, QVariant(ev->value)); - if (prefs_get_enum_value(pref, pref_stashed) == ev->value) - cur_combo_box_->setCurrentIndex(cur_combo_box_->count() - 1); - } - saved_combo_idx_ = cur_combo_box_->currentIndex(); - connect(cur_combo_box_, SIGNAL(currentIndexChanged(int)), this, SLOT(enumPrefCurrentIndexChanged(int))); - editor = cur_combo_box_; - break; - } - case PREF_STRING: - { - cur_line_edit_ = new QLineEdit(); - saved_string_pref_ = prefs_get_string_value(pref, pref_stashed); - connect(cur_line_edit_, SIGNAL(editingFinished()), this, SLOT(stringPrefEditingFinished())); - editor = cur_line_edit_; - break; - } - case PREF_SAVE_FILENAME: - case PREF_OPEN_FILENAME: - case PREF_DIRNAME: - { - QString filename; - - if (prefs_get_type(pref) == PREF_SAVE_FILENAME) { - filename = QFileDialog::getSaveFileName(this, wsApp->windowTitleString(prefs_get_title(pref)), - prefs_get_string_value(pref, pref_stashed)); - - } else if (prefs_get_type(pref) == PREF_OPEN_FILENAME) { - filename = QFileDialog::getOpenFileName(this, wsApp->windowTitleString(prefs_get_title(pref)), - prefs_get_string_value(pref, pref_stashed)); - - } else { - filename = QFileDialog::getExistingDirectory(this, wsApp->windowTitleString(prefs_get_title(pref)), - prefs_get_string_value(pref, pref_stashed)); + //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; } - if (!filename.isEmpty()) { - prefs_set_string_value(pref, QDir::toNativeSeparators(filename).toStdString().c_str(), pref_stashed); - adv_ti->updatePref(); - } - break; - } - case PREF_DECODE_AS_RANGE: - case PREF_RANGE: - { - SyntaxLineEdit *syntax_edit = new SyntaxLineEdit(); - char *cur_val = prefs_pref_to_str(pref, pref_stashed); - saved_string_pref_ = gchar_free_to_qstring(cur_val); - connect(syntax_edit, SIGNAL(textChanged(QString)), - this, SLOT(rangePrefTextChanged(QString))); - connect(syntax_edit, SIGNAL(editingFinished()), this, SLOT(rangePrefEditingFinished())); - editor = cur_line_edit_ = syntax_edit; - break; - } - case PREF_COLOR: - { - QColorDialog color_dlg; - color_t color = *prefs_get_color_value(pref, pref_stashed); - - color_dlg.setCurrentColor(QColor( - color.red >> 8, - color.green >> 8, - color.blue >> 8 - )); - if (color_dlg.exec() == QDialog::Accepted) { - QColor cc = color_dlg.currentColor(); - color.red = cc.red() << 8 | cc.red(); - color.green = cc.green() << 8 | cc.green(); - color.blue = cc.blue() << 8 | cc.blue(); - prefs_set_color_value(pref, color, pref_stashed); - adv_ti->updatePref(); - } - break; - } - case PREF_UAT: - { - if (prefs_get_gui_type(pref) == GUI_ALL || prefs_get_gui_type(pref) == GUI_QT) { - UatDialog uat_dlg(this, prefs_get_uat_value(pref)); - uat_dlg.exec(); - } - break; - } - default: - break; - } - cur_pref_type_ = prefs_get_type(pref); - 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_) { - connect(cur_combo_box_, SIGNAL(destroyed()), this, SLOT(enumPrefDestroyed())); - } - 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(); + moduleWindow = new ModulePreferencesScrollArea(module); + prefs_pane_to_item_[MODULES_NAME] = moduleWindow; + pd_ui_->stackedWidget->addWidget(moduleWindow); + pd_ui_->stackedWidget->setCurrentWidget(moduleWindow); } } } -void PreferencesDialog::lineEditPrefDestroyed() -{ - cur_line_edit_ = NULL; -} - -void PreferencesDialog::enumPrefDestroyed() -{ - cur_combo_box_ = NULL; -} - -void PreferencesDialog::uintPrefEditingFinished() -{ - AdvancedPrefTreeWidgetItem *adv_ti = dynamic_cast<AdvancedPrefTreeWidgetItem *>(pd_ui_->advancedTree->currentItem()); - if (!cur_line_edit_ || !adv_ti) return; - - pref_t *pref = adv_ti->pref(); - if (!pref) return; - - bool ok; - guint new_val = cur_line_edit_->text().toUInt(&ok, prefs_get_uint_base(pref)); - - if (ok) prefs_set_uint_value(pref, new_val, pref_stashed); - pd_ui_->advancedTree->removeItemWidget(adv_ti, 3); - adv_ti->updatePref(); -} - -void PreferencesDialog::enumPrefCurrentIndexChanged(int index) -{ - AdvancedPrefTreeWidgetItem *adv_ti = dynamic_cast<AdvancedPrefTreeWidgetItem *>(pd_ui_->advancedTree->currentItem()); - if (!cur_combo_box_ || !adv_ti || index < 0) return; - - pref_t *pref = adv_ti->pref(); - if (!pref) return; - - prefs_set_uint_value(pref, cur_combo_box_->itemData(index).toInt(), pref_stashed); - adv_ti->updatePref(); -} - -void PreferencesDialog::stringPrefEditingFinished() -{ - AdvancedPrefTreeWidgetItem *adv_ti = dynamic_cast<AdvancedPrefTreeWidgetItem *>(pd_ui_->advancedTree->currentItem()); - if (!cur_line_edit_ || !adv_ti) return; - - pref_t *pref = adv_ti->pref(); - if (!pref) return; - - prefs_set_string_value(pref, cur_line_edit_->text().toStdString().c_str(), pref_stashed); - pd_ui_->advancedTree->removeItemWidget(adv_ti, 3); - adv_ti->updatePref(); -} - -void PreferencesDialog::rangePrefTextChanged(const QString &text) -{ - SyntaxLineEdit *syntax_edit = qobject_cast<SyntaxLineEdit *>(cur_line_edit_); - AdvancedPrefTreeWidgetItem *adv_ti = dynamic_cast<AdvancedPrefTreeWidgetItem *>(pd_ui_->advancedTree->currentItem()); - if (!syntax_edit || !adv_ti) return; - - pref_t *pref = adv_ti->pref(); - if (!pref) return; - - if (text.isEmpty()) { - syntax_edit->setSyntaxState(SyntaxLineEdit::Empty); - } else { - range_t *newrange; - convert_ret_t ret = range_convert_str(NULL, &newrange, text.toUtf8().constData(), prefs_get_max_value(pref)); - - if (ret == CVT_NO_ERROR) { - syntax_edit->setSyntaxState(SyntaxLineEdit::Valid); - } else { - syntax_edit->setSyntaxState(SyntaxLineEdit::Invalid); - } - wmem_free(NULL, newrange); - } -} - -void PreferencesDialog::rangePrefEditingFinished() +void PreferencesDialog::on_advancedSearchLineEdit_textEdited(const QString &search_re) { - SyntaxLineEdit *syntax_edit = qobject_cast<SyntaxLineEdit *>(QObject::sender()); - AdvancedPrefTreeWidgetItem *adv_ti = dynamic_cast<AdvancedPrefTreeWidgetItem *>(pd_ui_->advancedTree->currentItem()); - if (!syntax_edit || !adv_ti) return; - - pref_t *pref = adv_ti->pref(); - if (!pref) return; - - prefs_set_stashed_range_value(pref, syntax_edit->text().toUtf8().constData()); - pd_ui_->advancedTree->removeItemWidget(adv_ti, 3); - adv_ti->updatePref(); + 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() diff --git a/ui/qt/preferences_dialog.h b/ui/qt/preferences_dialog.h index b841f783fd..e78116f27e 100644 --- a/ui/qt/preferences_dialog.h +++ b/ui/qt/preferences_dialog.h @@ -4,19 +4,7 @@ * 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. + * SPDX-License-Identifier: GPL-2.0+ */ #ifndef PREFERENCES_DIALOG_H @@ -24,19 +12,15 @@ #include <config.h> -#include <glib.h> - #include <epan/prefs.h> -#include "wireshark_application.h" +#include <ui/qt/models/pref_models.h> +#include <ui/qt/models/pref_delegate.h> #include "geometry_state_dialog.h" -#include <QTreeWidgetItem> class QComboBox; -extern pref_t *prefFromPrefPtr(void *pref_ptr); - namespace Ui { class PreferencesDialog; } @@ -46,50 +30,27 @@ class PreferencesDialog : public GeometryStateDialog Q_OBJECT public: - // This, prefsTree, and stackedWidget must all correspond to each other. - enum PreferencesPane { - ppAppearance, - ppLayout, - ppColumn, - ppFontAndColor, - ppCapture, - ppExpert, - ppFilterExpressions - }; - explicit PreferencesDialog(QWidget *parent = 0); ~PreferencesDialog(); - void setPane(PreferencesPane start_pane); - void setPane(const QString module_name); + + void setPane(const QString pane_name); protected: void showEvent(QShowEvent *evt); - void keyPressEvent(QKeyEvent *evt); private: - void updateItem(QTreeWidgetItem &item); - Ui::PreferencesDialog *pd_ui_; - QHash<PreferencesDialog::PreferencesPane, QTreeWidgetItem *>prefs_pane_to_item_; - int cur_pref_type_; - QLineEdit *cur_line_edit_; - QString saved_string_pref_; - QComboBox *cur_combo_box_; - int saved_combo_idx_; + + QHash<QString, QWidget*> prefs_pane_to_item_; + + PrefsModel model_; + AdvancedPrefsModel advancedPrefsModel_; + AdvancedPrefDelegate advancedPrefsDelegate_; + ModulePrefsModel modulePrefsModel_; private slots: - void on_prefsTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + void selectPane(QString pane); void on_advancedSearchLineEdit_textEdited(const QString &search_re); - void lineEditPrefDestroyed(); - void enumPrefDestroyed(); - void uintPrefEditingFinished(); - void enumPrefCurrentIndexChanged(int index); - void stringPrefEditingFinished(); - void rangePrefTextChanged(const QString & text); - void rangePrefEditingFinished(); - - void on_advancedTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); - void on_advancedTree_itemActivated(QTreeWidgetItem *item, int column); void on_buttonBox_accepted(); void on_buttonBox_rejected(); diff --git a/ui/qt/preferences_dialog.ui b/ui/qt/preferences_dialog.ui index 621076fe53..662590e2d6 100644 --- a/ui/qt/preferences_dialog.ui +++ b/ui/qt/preferences_dialog.ui @@ -16,7 +16,7 @@ <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <widget class="QTreeWidget" name="prefsTree"> + <widget class="PrefModuleTreeView" name="prefsView"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding"> <horstretch>0</horstretch> @@ -29,51 +29,9 @@ <property name="headerHidden"> <bool>true</bool> </property> - <column> - <property name="text"> - <string notr="true">1</string> - </property> - </column> - <item> - <property name="text"> - <string>Appearance</string> - </property> - <item> - <property name="text"> - <string>Layout</string> - </property> - </item> - <item> - <property name="text"> - <string>Columns</string> - </property> - </item> - <item> - <property name="text"> - <string>Font and Colors</string> - </property> - </item> - </item> - <item> - <property name="text"> - <string>Capture</string> - </property> - </item> - <item> - <property name="text"> - <string>Expert</string> - </property> - </item> - <item> - <property name="text"> - <string>Filter Buttons</string> - </property> - </item> - <item> - <property name="text"> - <string>Advanced</string> - </property> - </item> + <property name="sortingEnabled"> + <bool>true</bool> + </property> </widget> <widget class="QStackedWidget" name="stackedWidget"> <property name="sizePolicy"> @@ -122,33 +80,13 @@ </layout> </item> <item> - <widget class="QTreeWidget" name="advancedTree"> + <widget class="QTreeView" name="advancedView"> <property name="indentation"> <number>0</number> </property> <property name="uniformRowHeights"> <bool>true</bool> </property> - <column> - <property name="text"> - <string>Name</string> - </property> - </column> - <column> - <property name="text"> - <string>Status</string> - </property> - </column> - <column> - <property name="text"> - <string>Type</string> - </property> - </column> - <column> - <property name="text"> - <string>Value</string> - </property> - </column> </widget> </item> </layout> @@ -205,6 +143,12 @@ <header>uat_frame.h</header> <container>1</container> </customwidget> + <customwidget> + <class>PrefModuleTreeView</class> + <extends>QTreeView</extends> + <header>widgets/pref_module_view.h</header> + <container>1</container> + </customwidget> </customwidgets> <resources/> <connections> diff --git a/ui/qt/widgets/display_filter_edit.cpp b/ui/qt/widgets/display_filter_edit.cpp index 97cdbe96e6..46f832d8dc 100644 --- a/ui/qt/widgets/display_filter_edit.cpp +++ b/ui/qt/widgets/display_filter_edit.cpp @@ -4,19 +4,7 @@ * 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. + * SPDX-License-Identifier: GPL-2.0+ */ #include "config.h" @@ -34,6 +22,8 @@ #include <ui/qt/widgets/stock_icon_tool_button.h> #include <ui/qt/widgets/syntax_line_edit.h> #include <ui/qt/utils/wireshark_mime_data.h> +#include <ui/qt/models/pref_models.h> +#include "wireshark_application.h" #include <QAction> #include <QAbstractItemView> @@ -519,7 +509,7 @@ void DisplayFilterEdit::showFilters() void DisplayFilterEdit::showExpressionPrefs() { - emit showPreferencesDialog(PreferencesDialog::ppFilterExpressions); + emit showPreferencesDialog(PrefsModel::FILTER_BUTTONS_PREFERENCE_TREE_NAME); } void DisplayFilterEdit::applyOrPrepareFilter() diff --git a/ui/qt/widgets/display_filter_edit.h b/ui/qt/widgets/display_filter_edit.h index 84c6307fd4..447d969671 100644 --- a/ui/qt/widgets/display_filter_edit.h +++ b/ui/qt/widgets/display_filter_edit.h @@ -4,19 +4,7 @@ * 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. + * SPDX-License-Identifier: GPL-2.0+ */ #ifndef DISPLAYFILTEREDIT_H @@ -24,7 +12,6 @@ #include <QDrag> -#include <ui/qt/preferences_dialog.h> #include <ui/qt/widgets/syntax_line_edit.h> class QEvent; @@ -87,7 +74,7 @@ signals: void popFilterSyntaxStatus(); void pushFilterSyntaxWarning(const QString&); void filterPackets(QString new_filter, bool force); - void showPreferencesDialog(PreferencesDialog::PreferencesPane start_pane); + void showPreferencesDialog(QString pane_name); }; #endif // DISPLAYFILTEREDIT_H diff --git a/ui/qt/widgets/pref_module_view.cpp b/ui/qt/widgets/pref_module_view.cpp new file mode 100644 index 0000000000..388839260d --- /dev/null +++ b/ui/qt/widgets/pref_module_view.cpp @@ -0,0 +1,117 @@ +/* pref_module_view.cpp + * Tree view of preference module data. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "pref_module_view.h" +#include <ui/qt/models/pref_models.h> + +#include <QHeaderView> + +PrefModuleTreeView::PrefModuleTreeView(QWidget *parent) : QTreeView(parent), + appearanceName_(PrefsModel::APPEARANCE_PREFERENCE_TREE_NAME) +{ +} + +void PrefModuleTreeView::setPane(const QString pane_name) +{ + QModelIndex newIndex, modelIndex, appearanceIndex, protocolIndex, statIndex; + QString modelTreeName; + int row; + + //look for the pane name in the main tree before trying children + for (row = 0; row < model()->rowCount(); row++) + { + modelIndex = model()->index(row, ModulePrefsModel::colName); + modelTreeName = model()->data(modelIndex, Qt::DisplayRole).toString(); + + if (modelTreeName.compare(appearanceName_) == 0) { + appearanceIndex = modelIndex; + } else if (modelTreeName.compare("Protocols") == 0) { + protocolIndex = modelIndex; + } else if (modelTreeName.compare("Statistics") == 0) { + statIndex = modelIndex; + } + + if (modelTreeName.compare(pane_name) == 0) { + newIndex = modelIndex; + break; + } + } + + //Look through appearance children + if (!newIndex.isValid()) { + for (row = 0; row < model()->rowCount(appearanceIndex); row++) + { + modelIndex = model()->index(row, ModulePrefsModel::colName, appearanceIndex); + modelTreeName = model()->data(modelIndex, Qt::DisplayRole).toString(); + + if (modelTreeName.compare(pane_name) == 0) { + newIndex = modelIndex; + break; + } + } + } + + //Look through protocol children + if (!newIndex.isValid()) { + for (row = 0; row < model()->rowCount(protocolIndex); row++) + { + modelIndex = model()->index(row, ModulePrefsModel::colName, protocolIndex); + PrefsItem* proto_pref = VariantPointer<PrefsItem>::asPtr(model()->data(modelIndex, Qt::UserRole)); + if (proto_pref != NULL) { + if (pane_name.compare(proto_pref->getModuleName()) == 0) { + newIndex = modelIndex; + break; + } + } + } + } + + //Look through stat children + if (!newIndex.isValid()) { + for (row = 0; row < model()->rowCount(protocolIndex); row++) + { + modelIndex = model()->index(row, ModulePrefsModel::colName, protocolIndex); + PrefsItem* stat_pref = VariantPointer<PrefsItem>::asPtr(model()->data(modelIndex, Qt::UserRole)); + if (stat_pref != NULL) { + if (pane_name.compare(stat_pref->getModuleName()) == 0) { + newIndex = modelIndex; + break; + } + } + } + } + + setCurrentIndex(newIndex); +} + + +void PrefModuleTreeView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + if (current.isValid()) + { + QString pane_name = model()->data(current, ModulePrefsModel::ModuleName).toString(); + + emit goToPane(pane_name); + } + + QTreeView::currentChanged(current, previous); +} + +/* * 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/widgets/pref_module_view.h b/ui/qt/widgets/pref_module_view.h new file mode 100644 index 0000000000..8a1b871bfc --- /dev/null +++ b/ui/qt/widgets/pref_module_view.h @@ -0,0 +1,48 @@ +/* pref_module_view.h + * Tree view of preference module data. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef PREFERENCE_MODULE_VIEW_H +#define PREFERENCE_MODULE_VIEW_H + +#include <config.h> +#include <QTreeView> + +class PrefModuleTreeView : public QTreeView +{ + Q_OBJECT +public: + PrefModuleTreeView(QWidget *parent = 0); + + void setPane(const QString pane_name); + +signals: + void goToPane(QString pane); + +protected slots: + void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); + +private: + //cache the translation of the module names we check frequently + QString appearanceName_; +}; +#endif // PREFERENCE_MODULE_VIEW_H + +/* + * 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: + */ |