aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Thacker <johnthacker@gmail.com>2022-12-26 14:27:02 -0500
committerJohn Thacker <johnthacker@gmail.com>2023-01-07 13:20:24 +0000
commitda3a48f820773ba3764fe010bb07070eb26633e7 (patch)
treec69265c69839ae191a5e53c0388e088b25508f74
parent751d8361236c361739065c007a84ec8e2028c946 (diff)
Qt: Add a pref for column text caching, and have it affect sorting
Introduce a preference for the number of rows whose column text can be cached, and allow sorting of the packet list only when the number of displayed rows can fit in the cache. This preference only has an effect for sorting based on columns that require dissection and caching the column text. This reduces the number of dissections from O(N log N) to N. Subsequent sorts are even faster. Columns based on frame data are unaffected, as they sort much faster as dissection is not required. Set the size of the QCache introduced in 8c6854fb653cf58df39 based on this preference. Send a temporary status message to the status bar if we try to sort but there are too many rows, explaining why sorting did not happen and that the layout preferences can be changed. Ping #18741
-rw-r--r--epan/prefs.c6
-rw-r--r--epan/prefs.h1
-rw-r--r--ui/qt/layout_preferences_frame.cpp16
-rw-r--r--ui/qt/layout_preferences_frame.h2
-rw-r--r--ui/qt/layout_preferences_frame.ui28
-rw-r--r--ui/qt/models/packet_list_model.cpp21
-rw-r--r--ui/qt/models/packet_list_record.h4
-rw-r--r--ui/qt/packet_list.cpp6
8 files changed, 83 insertions, 1 deletions
diff --git a/epan/prefs.c b/epan/prefs.c
index d096f28a38..a54cafac3a 100644
--- a/epan/prefs.c
+++ b/epan/prefs.c
@@ -3485,6 +3485,11 @@ prefs_register_modules(void)
"To prevent sorting by mistake (which can take some time to calculate), it can be disabled",
&prefs.gui_packet_list_sortable);
+ prefs_register_uint_preference(gui_module, "packet_list_cached_rows_max",
+ "Maximum cached rows",
+ "Maximum number of rows that can be sorted by columns that require dissection. Increasing this increases memory consumption by caching column text",
+ 10,
+ &prefs.gui_packet_list_cached_rows_max);
prefs_register_bool_preference(gui_module, "interfaces_show_hidden",
"Show hidden interfaces",
@@ -4190,6 +4195,7 @@ pre_init_prefs(void)
prefs.gui_packet_list_show_related = TRUE;
prefs.gui_packet_list_show_minimap = TRUE;
prefs.gui_packet_list_sortable = TRUE;
+ prefs.gui_packet_list_cached_rows_max = 10000;
g_free (prefs.gui_interfaces_hide_types);
prefs.gui_interfaces_hide_types = g_strdup("");
prefs.gui_interfaces_show_hidden = FALSE;
diff --git a/epan/prefs.h b/epan/prefs.h
index 9e6fcff56c..6bfd0ae1ea 100644
--- a/epan/prefs.h
+++ b/epan/prefs.h
@@ -220,6 +220,7 @@ typedef struct _e_prefs {
gboolean gui_packet_list_show_related;
gboolean gui_packet_list_show_minimap;
gboolean gui_packet_list_sortable;
+ guint gui_packet_list_cached_rows_max;
gint gui_decimal_places1; /* Used for type 1 calculations */
gint gui_decimal_places2; /* Used for type 2 calculations */
gint gui_decimal_places3; /* Used for type 3 calculations */
diff --git a/ui/qt/layout_preferences_frame.cpp b/ui/qt/layout_preferences_frame.cpp
index 34d6d2d866..e1a5d99015 100644
--- a/ui/qt/layout_preferences_frame.cpp
+++ b/ui/qt/layout_preferences_frame.cpp
@@ -41,7 +41,7 @@ LayoutPreferencesFrame::LayoutPreferencesFrame(QWidget *parent) :
QStyleOption style_opt;
QString indent_ss = QString(
- "QCheckBox {"
+ "QCheckBox, QLabel {"
" margin-left: %1px;"
"}"
).arg(ui->packetListSeparatorCheckBox->style()->subElementRect(QStyle::SE_CheckBoxContents, &style_opt).left());
@@ -49,6 +49,7 @@ LayoutPreferencesFrame::LayoutPreferencesFrame(QWidget *parent) :
ui->packetListHeaderShowColumnDefinition->setStyleSheet(indent_ss);
ui->packetListHoverStyleCheckbox->setStyleSheet(indent_ss);
ui->packetListAllowSorting->setStyleSheet(indent_ss);
+ ui->packetListCachedRowsLabel->setStyleSheet(indent_ss);
ui->statusBarShowSelectedPacketCheckBox->setStyleSheet(indent_ss);
ui->statusBarShowFileLoadTimeCheckBox->setStyleSheet(indent_ss);
@@ -64,6 +65,8 @@ LayoutPreferencesFrame::LayoutPreferencesFrame(QWidget *parent) :
pref_packet_list_sorting_ = prefFromPrefPtr(&prefs.gui_packet_list_sortable);
ui->packetListAllowSorting->setChecked(prefs_get_bool_value(pref_packet_list_sorting_, pref_stashed));
+ pref_packet_list_cached_rows_max_ = prefFromPrefPtr(&prefs.gui_packet_list_cached_rows_max);
+
pref_show_selected_packet_ = prefFromPrefPtr(&prefs.gui_qt_show_selected_packet);
ui->statusBarShowSelectedPacketCheckBox->setChecked(prefs_get_bool_value(pref_show_selected_packet_, pref_stashed));
@@ -157,6 +160,8 @@ void LayoutPreferencesFrame::updateWidgets()
ui->pane3NoneRadioButton->setChecked(true);
break;
}
+
+ ui->packetListCachedRowsLineEdit->setText(QString::number(prefs_get_uint_value_real(pref_packet_list_cached_rows_max_, pref_stashed)));
}
void LayoutPreferencesFrame::on_layout5ToolButton_toggled(bool checked)
@@ -371,6 +376,15 @@ void LayoutPreferencesFrame::on_packetListAllowSorting_toggled(bool checked)
prefs_set_bool_value(pref_packet_list_sorting_, (gboolean) checked, pref_stashed);
}
+void LayoutPreferencesFrame::on_packetListCachedRowsLineEdit_textEdited(const QString &new_str)
+{
+ bool ok;
+ uint new_uint = new_str.toUInt(&ok, 0);
+ if (ok) {
+ prefs_set_uint_value(pref_packet_list_cached_rows_max_, new_uint, pref_stashed);
+ }
+}
+
void LayoutPreferencesFrame::on_statusBarShowSelectedPacketCheckBox_toggled(bool checked)
{
prefs_set_bool_value(pref_show_selected_packet_, (gboolean) checked, pref_stashed);
diff --git a/ui/qt/layout_preferences_frame.h b/ui/qt/layout_preferences_frame.h
index 372caeae17..6773c5eeb9 100644
--- a/ui/qt/layout_preferences_frame.h
+++ b/ui/qt/layout_preferences_frame.h
@@ -41,6 +41,7 @@ private:
pref_t *pref_packet_header_column_definition_;
pref_t *pref_packet_list_hover_style_;
pref_t *pref_packet_list_sorting_;
+ pref_t *pref_packet_list_cached_rows_max_;
pref_t *pref_show_selected_packet_;
pref_t *pref_show_file_load_time_;
@@ -73,6 +74,7 @@ private slots:
void on_packetListHeaderShowColumnDefinition_toggled(bool checked);
void on_packetListHoverStyleCheckbox_toggled(bool checked);
void on_packetListAllowSorting_toggled(bool checked);
+ void on_packetListCachedRowsLineEdit_textEdited(const QString &new_str);
void on_statusBarShowSelectedPacketCheckBox_toggled(bool checked);
void on_statusBarShowFileLoadTimeCheckBox_toggled(bool checked);
};
diff --git a/ui/qt/layout_preferences_frame.ui b/ui/qt/layout_preferences_frame.ui
index 77a7edf62f..70600706a4 100644
--- a/ui/qt/layout_preferences_frame.ui
+++ b/ui/qt/layout_preferences_frame.ui
@@ -403,6 +403,34 @@
</widget>
</item>
<item>
+ <layout class="QHBoxLayout" name="packetListCachedRows">
+ <item>
+ <widget class="QLabel" name="packetListCachedRowsLabel">
+ <property name="text">
+ <string>Maximum number of cached rows (affects sorting)</string>
+ </property>
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If more than this many rows are displayed, then sorting by columns that require packet dissection will be disabled. Increasing this number increases memory consumption by caching column values.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="packetListCachedRowsLineEdit">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If more than this many rows are displayed, then sorting by columns that require packet dissection will be disabled. Increasing this number increases memory consumption by caching column values.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="packetListCachedRowsHorizontalSpacer">
+ <property name="orientation">
+ <enum>Qt:Horizontal</enum>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
<widget class="QCheckBox" name="packetListHoverStyleCheckbox">
<property name="text">
<string>Enable mouse-over colorization</string>
diff --git a/ui/qt/models/packet_list_model.cpp b/ui/qt/models/packet_list_model.cpp
index a9726a8aa1..7c71e824c6 100644
--- a/ui/qt/models/packet_list_model.cpp
+++ b/ui/qt/models/packet_list_model.cpp
@@ -358,6 +358,27 @@ void PacketListModel::sort(int column, Qt::SortOrder order)
QString col_title = get_column_title(column);
+ if (text_sort_column_ >= 0 && (guint)visible_rows_.count() > prefs.gui_packet_list_cached_rows_max) {
+ /* Column not based on frame data but by column text that requires
+ * dissection, so to sort in a reasonable amount of time the column
+ * text needs to be cached.
+ */
+ /* If the sort is being triggered because the columns were already
+ * sorted and the filter is being cleared (or changed to something
+ * else with more rows than fit in the cache), then the temporary
+ * message will be immediately overwritten with the standard capture
+ * statistics by the packets_bar_update() call after thawing the rows.
+ * It will still blink yellow, and the user will get the message if
+ * they then click on the header file (wondering why it didn't sort.)
+ */
+ if (col_title.isEmpty()) {
+ col_title = tr("Column");
+ }
+ QString temp_msg = tr("%1 can only be sorted with %2 or fewer visible rows; increase cache size in Layout preferences").arg(col_title).arg(prefs.gui_packet_list_cached_rows_max);
+ mainApp->pushStatus(MainApplication::TemporaryStatus, temp_msg);
+ return;
+ }
+
// XXX Use updateProgress instead. We'd have to switch from std::sort to
// something we can interrupt.
if (!col_title.isEmpty()) {
diff --git a/ui/qt/models/packet_list_record.h b/ui/qt/models/packet_list_record.h
index 5afe37b7ba..2a6db75cba 100644
--- a/ui/qt/models/packet_list_record.h
+++ b/ui/qt/models/packet_list_record.h
@@ -45,6 +45,10 @@ public:
int columnTextSize(const char *str);
static void invalidateAllRecords() { col_text_cache_.clear(); }
+ /* In Qt 6, QCache maxCost is a qsizetype, but the QAbstractItemModel
+ * number of rows is still an int, so we're limited to INT_MAX anyway.
+ */
+ static void setMaxCache(int cost) { col_text_cache_.setMaxCost(cost); }
static void resetColumns(column_info *cinfo);
static void resetColorization() { rows_color_ver_++; }
diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp
index 2f35683609..227fc139c3 100644
--- a/ui/qt/packet_list.cpp
+++ b/ui/qt/packet_list.cpp
@@ -252,6 +252,12 @@ PacketList::PacketList(QWidget *parent) :
connect(mainApp, SIGNAL(addressResolutionChanged()), this, SLOT(redrawVisiblePacketsDontSelectCurrent()));
connect(mainApp, SIGNAL(columnDataChanged()), this, SLOT(redrawVisiblePacketsDontSelectCurrent()));
connect(mainApp, &MainApplication::preferencesChanged, this, [=]() {
+ /* The pref is a uint but QCache maxCost is a signed int (/
+ * qsizetype in Qt 6). Note that QAbstractItemModel row numbers
+ * are ints, not unsigned ints, so we're limited to INT_MAX
+ * rows anyway.
+ */
+ PacketListRecord::setMaxCache(prefs.gui_packet_list_cached_rows_max > INT_MAX ? INT_MAX : prefs.gui_packet_list_cached_rows_max);
if ((bool) (prefs.gui_packet_list_sortable) != isSortingEnabled()) {
setSortingEnabled(prefs.gui_packet_list_sortable);
}