Improve FIFO analyzer search function

- Only one search result is generated per command/line, even if there are multiple matches in that line.
- Pressing enter on the edit field begins a search, just like clicking the begin button.
- The next and previous buttons are disabled until a search is begun.
- The search results are cleared when changing objects or frames.
- The previous button once again works (a regression from the previous commit), and the register updates and graphics data for the correct object are searched.
- currentRow() never returns -1, so checking that is unnecessary (and misleading).
- The 'Invalid search parameters (no object selected)' previously never showed up before because FRAME_ROLE is present if and only if OBJECT_ROLE is present.
This commit is contained in:
Pokechu22 2021-02-19 14:02:59 -08:00
parent 1dc3ff5879
commit dbacf68b79
2 changed files with 58 additions and 59 deletions

View File

@ -81,6 +81,9 @@ void FIFOAnalyzer::CreateWidgets()
m_search_previous = new QPushButton(tr("Previous Match")); m_search_previous = new QPushButton(tr("Previous Match"));
m_search_label = new QLabel; m_search_label = new QLabel;
m_search_next->setEnabled(false);
m_search_previous->setEnabled(false);
auto* box_layout = new QHBoxLayout; auto* box_layout = new QHBoxLayout;
box_layout->addWidget(m_search_edit); box_layout->addWidget(m_search_edit);
@ -111,6 +114,7 @@ void FIFOAnalyzer::ConnectWidgets()
connect(m_detail_list, &QListWidget::itemSelectionChanged, this, connect(m_detail_list, &QListWidget::itemSelectionChanged, this,
&FIFOAnalyzer::UpdateDescription); &FIFOAnalyzer::UpdateDescription);
connect(m_search_edit, &QLineEdit::returnPressed, this, &FIFOAnalyzer::BeginSearch);
connect(m_search_new, &QPushButton::clicked, this, &FIFOAnalyzer::BeginSearch); connect(m_search_new, &QPushButton::clicked, this, &FIFOAnalyzer::BeginSearch);
connect(m_search_next, &QPushButton::clicked, this, &FIFOAnalyzer::FindNext); connect(m_search_next, &QPushButton::clicked, this, &FIFOAnalyzer::FindNext);
connect(m_search_previous, &QPushButton::clicked, this, &FIFOAnalyzer::FindPrevious); connect(m_search_previous, &QPushButton::clicked, this, &FIFOAnalyzer::FindPrevious);
@ -167,6 +171,10 @@ void FIFOAnalyzer::UpdateDetails()
// Clear m_object_data_offsets first, so that UpdateDescription exits immediately. // Clear m_object_data_offsets first, so that UpdateDescription exits immediately.
m_object_data_offsets.clear(); m_object_data_offsets.clear();
m_detail_list->clear(); m_detail_list->clear();
m_search_results.clear();
m_search_next->setEnabled(false);
m_search_previous->setEnabled(false);
m_search_label->clear();
if (!FifoPlayer::GetInstance().IsPlaying()) if (!FifoPlayer::GetInstance().IsPlaying())
return; return;
@ -335,17 +343,15 @@ void FIFOAnalyzer::UpdateDetails()
void FIFOAnalyzer::BeginSearch() void FIFOAnalyzer::BeginSearch()
{ {
QString search_str = m_search_edit->text(); const QString search_str = m_search_edit->text();
if (!FifoPlayer::GetInstance().IsPlaying()) if (!FifoPlayer::GetInstance().IsPlaying())
return; return;
auto items = m_tree_widget->selectedItems(); const auto items = m_tree_widget->selectedItems();
if (items.isEmpty() || items[0]->data(0, FRAME_ROLE).isNull()) if (items.isEmpty() || items[0]->data(0, FRAME_ROLE).isNull() ||
return; items[0]->data(0, OBJECT_ROLE).isNull())
if (items[0]->data(0, OBJECT_ROLE).isNull())
{ {
m_search_label->setText(tr("Invalid search parameters (no object selected)")); m_search_label->setText(tr("Invalid search parameters (no object selected)"));
return; return;
@ -380,37 +386,36 @@ void FIFOAnalyzer::BeginSearch()
m_search_results.clear(); m_search_results.clear();
int frame_nr = items[0]->data(0, FRAME_ROLE).toInt(); const u32 frame_nr = items[0]->data(0, FRAME_ROLE).toUInt();
int object_nr = items[0]->data(0, OBJECT_ROLE).toInt(); const u32 object_nr = items[0]->data(0, OBJECT_ROLE).toUInt();
const AnalyzedFrameInfo& frame_info = FifoPlayer::GetInstance().GetAnalyzedFrameInfo(frame_nr); const AnalyzedFrameInfo& frame_info = FifoPlayer::GetInstance().GetAnalyzedFrameInfo(frame_nr);
const FifoFrameInfo& fifo_frame = FifoPlayer::GetInstance().GetFile()->GetFrame(frame_nr); const FifoFrameInfo& fifo_frame = FifoPlayer::GetInstance().GetFile()->GetFrame(frame_nr);
// TODO: Support searching through the last object...how do we know where the cmd data ends? const u32 object_start = (object_nr == 0 ? 0 : frame_info.objectEnds[object_nr - 1]);
const u32 object_size = frame_info.objectEnds[object_nr] - object_start;
const u8* const object = &fifo_frame.fifoData[object_start];
// TODO: Support searching for bit patterns // TODO: Support searching for bit patterns
for (u32 cmd_nr = 0; cmd_nr < m_object_data_offsets.size(); cmd_nr++)
{
const u32 cmd_start = m_object_data_offsets[cmd_nr];
const u32 cmd_end = (cmd_nr + 1 == m_object_data_offsets.size()) ?
object_size :
m_object_data_offsets[cmd_nr + 1];
const auto* start_ptr = &fifo_frame.fifoData[frame_info.objectStarts[object_nr]]; const u8* const cmd_start_ptr = &object[cmd_start];
const auto* end_ptr = &fifo_frame.fifoData[frame_info.objectStarts[object_nr + 1]]; const u8* const cmd_end_ptr = &object[cmd_end];
for (const u8* ptr = start_ptr; ptr < end_ptr - length + 1; ++ptr) for (const u8* ptr = cmd_start_ptr; ptr < cmd_end_ptr - length + 1; ptr++)
{ {
if (std::equal(search_val.begin(), search_val.end(), ptr)) if (std::equal(search_val.begin(), search_val.end(), ptr))
{ {
SearchResult result; m_search_results.emplace_back(frame_nr, object_nr, cmd_nr);
result.frame = frame_nr;
result.object = object_nr;
result.cmd = 0;
for (unsigned int cmd_nr = 1; cmd_nr < m_object_data_offsets.size(); ++cmd_nr)
{
if (ptr < start_ptr + m_object_data_offsets[cmd_nr])
{
result.cmd = cmd_nr - 1;
break; break;
} }
} }
m_search_results.push_back(result);
}
} }
ShowSearchResult(0); ShowSearchResult(0);
@ -421,41 +426,29 @@ void FIFOAnalyzer::BeginSearch()
void FIFOAnalyzer::FindNext() void FIFOAnalyzer::FindNext()
{ {
int index = m_detail_list->currentRow(); const int index = m_detail_list->currentRow();
ASSERT(index >= 0);
if (index == -1) auto next_result =
std::find_if(m_search_results.begin(), m_search_results.end(),
[index](auto& result) { return result.m_cmd > static_cast<u32>(index); });
if (next_result != m_search_results.end())
{ {
ShowSearchResult(0); ShowSearchResult(next_result - m_search_results.begin());
return;
}
for (auto it = m_search_results.begin(); it != m_search_results.end(); ++it)
{
if (it->cmd > index)
{
ShowSearchResult(it - m_search_results.begin());
return;
}
} }
} }
void FIFOAnalyzer::FindPrevious() void FIFOAnalyzer::FindPrevious()
{ {
int index = m_detail_list->currentRow(); const int index = m_detail_list->currentRow();
ASSERT(index >= 0);
if (index == -1) auto prev_result =
std::find_if(m_search_results.rbegin(), m_search_results.rend(),
[index](auto& result) { return result.m_cmd < static_cast<u32>(index); });
if (prev_result != m_search_results.rend())
{ {
ShowSearchResult(m_search_results.size() - 1); ShowSearchResult((m_search_results.rend() - prev_result) - 1);
return;
}
for (auto it = m_search_results.rbegin(); it != m_search_results.rend(); ++it)
{
if (it->cmd < index)
{
ShowSearchResult(m_search_results.size() - 1 - (it - m_search_results.rbegin()));
return;
}
} }
} }
@ -464,7 +457,7 @@ void FIFOAnalyzer::ShowSearchResult(size_t index)
if (m_search_results.empty()) if (m_search_results.empty())
return; return;
if (index > m_search_results.size()) if (index >= m_search_results.size())
{ {
ShowSearchResult(m_search_results.size() - 1); ShowSearchResult(m_search_results.size() - 1);
return; return;
@ -473,10 +466,10 @@ void FIFOAnalyzer::ShowSearchResult(size_t index)
const auto& result = m_search_results[index]; const auto& result = m_search_results[index];
QTreeWidgetItem* object_item = QTreeWidgetItem* object_item =
m_tree_widget->topLevelItem(0)->child(result.frame)->child(result.object); m_tree_widget->topLevelItem(0)->child(result.m_frame)->child(result.m_object);
m_tree_widget->setCurrentItem(object_item); m_tree_widget->setCurrentItem(object_item);
m_detail_list->setCurrentRow(result.cmd); m_detail_list->setCurrentRow(result.m_cmd);
m_search_next->setEnabled(index + 1 < m_search_results.size()); m_search_next->setEnabled(index + 1 < m_search_results.size());
m_search_previous->setEnabled(index > 0); m_search_previous->setEnabled(index > 0);

View File

@ -8,6 +8,8 @@
#include <QWidget> #include <QWidget>
#include "Common/CommonTypes.h"
class QGroupBox; class QGroupBox;
class QLabel; class QLabel;
class QLineEdit; class QLineEdit;
@ -57,9 +59,13 @@ private:
struct SearchResult struct SearchResult
{ {
int frame; constexpr SearchResult(u32 frame, u32 object, u32 cmd)
int object; : m_frame(frame), m_object(object), m_cmd(cmd)
int cmd; {
}
const u32 m_frame;
const u32 m_object;
const u32 m_cmd;
}; };
std::vector<int> m_object_data_offsets; std::vector<int> m_object_data_offsets;