From 43e85c45ab971e01716675a50d5a65717b830c4e Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Thu, 25 Sep 2025 11:46:09 -0700 Subject: [PATCH] Sort table views in the shared cache / kernel cache triage views by address by default The table views previously visually suggested they were being sorted by address, but in practice they were not sorted until the user set an explicit sort order by clicking on a column header. --- view/kernelcache/ui/kctriage.cpp | 5 +++ view/kernelcache/ui/symboltable.cpp | 4 +++ view/sharedcache/ui/dsctriage.cpp | 50 +++++++++++++++++++---------- view/sharedcache/ui/dsctriage.h | 2 ++ view/sharedcache/ui/symboltable.cpp | 5 +++ 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/view/kernelcache/ui/kctriage.cpp b/view/kernelcache/ui/kctriage.cpp index 57392e190c..baae517c46 100644 --- a/view/kernelcache/ui/kctriage.cpp +++ b/view/kernelcache/ui/kctriage.cpp @@ -298,6 +298,7 @@ QWidget* KCTriageView::initImageTable() m_imageTable->setSelectionBehavior(QAbstractItemView::SelectRows); m_imageTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_imageTable->sortByColumn(0, Qt::AscendingOrder); m_imageTable->setSortingEnabled(true); m_imageTable->verticalHeader()->setVisible(false); @@ -454,4 +455,8 @@ void KCTriageView::RefreshData() setImageLoaded(loadedImg.headerVirtualAddress); m_symbolTable->populateSymbols(*m_data); + + // Reapply the current sort after repopulating the model + // TODO: This should use `QSortFilterProxyModel`, but that's a bigger change. + m_imageTable->setSortingEnabled(true); } diff --git a/view/kernelcache/ui/symboltable.cpp b/view/kernelcache/ui/symboltable.cpp index 5c86b3b450..90d0d18b1b 100644 --- a/view/kernelcache/ui/symboltable.cpp +++ b/view/kernelcache/ui/symboltable.cpp @@ -196,6 +196,10 @@ void SymbolTableView::populateSymbols(BinaryView &view) { auto symbols = watcher->result(); m_model->updateSymbols(std::move(symbols)); + + // Reapply the current sort after repopulating the model + // TODO: The model should use `QSortFilterProxyModel`, but that's a bigger change. + setSortingEnabled(true); } }); QFuture future = QtConcurrent::run([controller]() { diff --git a/view/sharedcache/ui/dsctriage.cpp b/view/sharedcache/ui/dsctriage.cpp index 081ef25e5a..48ad613067 100644 --- a/view/sharedcache/ui/dsctriage.cpp +++ b/view/sharedcache/ui/dsctriage.cpp @@ -300,6 +300,7 @@ QWidget* DSCTriageView::initImageTable() m_imageTable->setSelectionBehavior(QAbstractItemView::SelectRows); m_imageTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_imageTable->sortByColumn(0, Qt::AscendingOrder); m_imageTable->setSortingEnabled(true); m_imageTable->verticalHeader()->setVisible(false); @@ -421,32 +422,34 @@ void DSCTriageView::initCacheInfoTables() m_mappingTable->setSelectionBehavior(QAbstractItemView::SelectRows); m_mappingTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_mappingTable->sortByColumn(0, Qt::AscendingOrder); m_mappingTable->setSortingEnabled(true); m_mappingTable->verticalHeader()->setVisible(false); - auto regionTable = new FilterableTableView(cacheInfoSubwidget); - m_regionModel = new QStandardItemModel(0, 4, regionTable); + m_regionTable = new FilterableTableView(cacheInfoSubwidget); + m_regionModel = new QStandardItemModel(0, 4, m_regionTable); m_regionModel->setHorizontalHeaderLabels({"Address", "Size", "Type", "Name"}); // Apply custom column styling - regionTable->setItemDelegateForColumn(0, new AddressColorDelegate(regionTable)); + m_regionTable->setItemDelegateForColumn(0, new AddressColorDelegate(m_regionTable)); - regionTable->setModel(m_regionModel); + m_regionTable->setModel(m_regionModel); - regionTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents); - regionTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents); - regionTable->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents); - regionTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch); + m_regionTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents); + m_regionTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents); + m_regionTable->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents); + m_regionTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch); - regionTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_regionTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - regionTable->setSelectionBehavior(QAbstractItemView::SelectRows); - regionTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_regionTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_regionTable->setSelectionMode(QAbstractItemView::ExtendedSelection); - regionTable->setSortingEnabled(true); + m_regionTable->sortByColumn(0, Qt::AscendingOrder); + m_regionTable->setSortingEnabled(true); - regionTable->verticalHeader()->setVisible(false); + m_regionTable->verticalHeader()->setVisible(false); auto mappingLabel = new QLabel("Mappings"); auto mappingFilterEdit = new FilterEdit(m_mappingTable); @@ -462,10 +465,10 @@ void DSCTriageView::initCacheInfoTables() mappingHeaderLayout->setSpacing(30); auto regionLabel = new QLabel("Regions"); - auto regionFilterEdit = new FilterEdit(regionTable); + auto regionFilterEdit = new FilterEdit(m_regionTable); regionFilterEdit->setPlaceholderText("Filter regions"); - connect(regionFilterEdit, &FilterEdit::textChanged, [regionTable](const QString& filter) { - regionTable->setFilter(filter.toStdString()); + connect(regionFilterEdit, &FilterEdit::textChanged, [this](const QString& filter) { + m_regionTable->setFilter(filter.toStdString()); }); auto regionHeaderLayout = new QHBoxLayout; @@ -480,7 +483,7 @@ void DSCTriageView::initCacheInfoTables() auto regionLayout = new QVBoxLayout; regionLayout->addLayout(regionHeaderLayout); - regionLayout->addWidget(regionTable); + regionLayout->addWidget(m_regionTable); cacheInfoLayout->addLayout(mappingLayout); cacheInfoLayout->addLayout(regionLayout); @@ -552,6 +555,10 @@ void DSCTriageView::RefreshData() for (const auto& loadedImg : controller->GetLoadedImages()) setImageLoaded(loadedImg.headerAddress); + // Reapply the current sort after repopulating the model + // TODO: This should use `QSortFilterProxyModel`, but that's a bigger change. + m_imageTable->setSortingEnabled(true); + m_regionModel->setRowCount(0); for (const auto& region : controller->GetRegions()) { @@ -563,6 +570,10 @@ void DSCTriageView::RefreshData() }); } + // Reapply the current sort after repopulating the model + // TODO: This should use `QSortFilterProxyModel`, but that's a bigger change. + m_regionTable->setSortingEnabled(true); + m_mappingModel->setRowCount(0); for (const auto& entry : controller->GetEntries()) { @@ -578,5 +589,10 @@ void DSCTriageView::RefreshData() } } + // Reapply the current sort after repopulating the model + // TODO: This should use `QSortFilterProxyModel`, but that's a bigger change. + m_mappingTable->setSortingEnabled(true); + + m_symbolTable->populateSymbols(*m_data); } diff --git a/view/sharedcache/ui/dsctriage.h b/view/sharedcache/ui/dsctriage.h index 164e7ffbc7..33f45bcf36 100644 --- a/view/sharedcache/ui/dsctriage.h +++ b/view/sharedcache/ui/dsctriage.h @@ -188,6 +188,8 @@ class DSCTriageView : public QWidget, public View, public UIContextNotification SymbolTableView* m_symbolTable; + FilterableTableView* m_regionTable; + FilterableTableView* m_mappingTable; QStandardItemModel* m_mappingModel; diff --git a/view/sharedcache/ui/symboltable.cpp b/view/sharedcache/ui/symboltable.cpp index e4c5dcd8b7..a876bf61bb 100644 --- a/view/sharedcache/ui/symboltable.cpp +++ b/view/sharedcache/ui/symboltable.cpp @@ -187,6 +187,7 @@ SymbolTableView::SymbolTableView(QWidget* parent) : setSelectionMode(QAbstractItemView::SingleSelection); verticalHeader()->setVisible(false); + sortByColumn(0, Qt::AscendingOrder); setSortingEnabled(true); } @@ -203,6 +204,10 @@ void SymbolTableView::populateSymbols(BinaryView &view) { auto symbols = watcher->result(); m_model->updateSymbols(std::move(symbols)); + + // Reapply the current sort after repopulating the model + // TODO: The model should use `QSortFilterProxyModel`, but that's a bigger change. + setSortingEnabled(true); } }); QFuture future = QtConcurrent::run([controller]() {