From 07f5b0aa5b8f0fc4e85522d5eb047e9c747a8b74 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 23 Mar 2026 15:53:03 +0100 Subject: [PATCH] Qt: Improve find dialog Add index of current line and word. Add case sensitivity checkbox. --- rpcs3/rpcs3qt/find_dialog.cpp | 176 ++++++++++++++++++++++------------ rpcs3/rpcs3qt/find_dialog.h | 29 +++--- 2 files changed, 131 insertions(+), 74 deletions(-) diff --git a/rpcs3/rpcs3qt/find_dialog.cpp b/rpcs3/rpcs3qt/find_dialog.cpp index 9c5e805050..25d9442f2b 100644 --- a/rpcs3/rpcs3qt/find_dialog.cpp +++ b/rpcs3/rpcs3qt/find_dialog.cpp @@ -1,6 +1,10 @@ +#include "stdafx.h" #include "find_dialog.h" +#include #include +#include +#include find_dialog::find_dialog(QPlainTextEdit* edit, QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f), m_text_edit(edit) { @@ -9,109 +13,159 @@ find_dialog::find_dialog(QPlainTextEdit* edit, QWidget *parent, Qt::WindowFlags m_find_bar = new QLineEdit(); m_find_bar->setPlaceholderText(tr("Search...")); - m_label_count_lines = new QLabel(tr("Counted in lines: -")); - m_label_count_total = new QLabel(tr("Counted in total: -")); + QCheckBox* cb_case_sensitive = new QCheckBox(tr("Case sensitive")); + cb_case_sensitive->setChecked(m_case_sensitive); + connect(cb_case_sensitive, &QCheckBox::toggled, this, [=](bool checked) + { + m_case_sensitive = checked; + }); - m_find_first = new QPushButton(tr("First")); - m_find_last = new QPushButton(tr("Last")); - m_find_next = new QPushButton(tr("Next")); - m_find_previous = new QPushButton(tr("Previous")); + m_label_count_lines = new QLabel(tr("Line 0/0")); + m_label_count_total = new QLabel(tr("Word 0/0")); + + QPushButton* find_first = new QPushButton(tr("First")); + QPushButton* find_last = new QPushButton(tr("Last")); + QPushButton* find_next = new QPushButton(tr("Next")); + QPushButton* find_previous = new QPushButton(tr("Previous")); + + QHBoxLayout* find_layout = new QHBoxLayout(); + find_layout->addWidget(m_find_bar); + find_layout->addWidget(cb_case_sensitive); QHBoxLayout* count_layout = new QHBoxLayout(); count_layout->addWidget(m_label_count_lines); count_layout->addWidget(m_label_count_total); QHBoxLayout* button_layout = new QHBoxLayout(); - button_layout->addWidget(m_find_first); - button_layout->addWidget(m_find_last); - button_layout->addWidget(m_find_previous); - button_layout->addWidget(m_find_next); + button_layout->addWidget(find_first); + button_layout->addWidget(find_last); + button_layout->addWidget(find_previous); + button_layout->addWidget(find_next); QVBoxLayout* layout = new QVBoxLayout(); - layout->addWidget(m_find_bar); + layout->addLayout(find_layout); layout->addLayout(count_layout); layout->addLayout(button_layout); setLayout(layout); - connect(m_find_first, &QPushButton::clicked, this, &find_dialog::find_first); - connect(m_find_last, &QPushButton::clicked, this, &find_dialog::find_last); - connect(m_find_next, &QPushButton::clicked, this, &find_dialog::find_next); - connect(m_find_previous, &QPushButton::clicked, this, &find_dialog::find_previous); + connect(find_first, &QPushButton::clicked, this, [this](){ find(find_type::first); }); + connect(find_last, &QPushButton::clicked, this, [this](){ find(find_type::last); }); + connect(find_next, &QPushButton::clicked, this, [this](){ find(find_type::next); }); + connect(find_previous, &QPushButton::clicked, this, [this](){ find(find_type::prev); }); - m_find_next->setDefault(true); + find_next->setDefault(true); show(); } -int find_dialog::count_all() +void find_dialog::find(find_type type) { m_count_lines = 0; m_count_total = 0; + m_current_line = 0; + m_current_index = 0; if (!m_text_edit || m_find_bar->text().isEmpty()) { show_count(); - return 0; + return; } + const QTextDocument::FindFlags flags = m_case_sensitive ? QTextDocument::FindCaseSensitively : QTextDocument::FindFlag{}; + + std::map /*pos*/>> block_indices; + const QTextCursor old_cursor = m_text_edit->textCursor(); m_text_edit->moveCursor(QTextCursor::Start); - int old_line_index = -1; + const QString text = m_find_bar->text(); - while (m_text_edit->find(m_find_bar->text())) + while (m_text_edit->find(text, flags)) { m_count_total++; - const int new_line_index = m_text_edit->textCursor().blockNumber(); - if (new_line_index != old_line_index) + const QTextCursor cursor = m_text_edit->textCursor(); + const QTextBlock block = cursor.block(); + const QTextLayout* layout = block.layout(); + + const int relative_pos = cursor.position() - block.position(); + const QTextLine line = layout->lineForTextPosition(relative_pos); + const int pos_in_line = relative_pos - line.textStart(); + + block_indices[cursor.blockNumber()][line.lineNumber()].push_back(pos_in_line); + } + + switch (type) + { + case find_type::first: + { + m_text_edit->moveCursor(QTextCursor::Start); + m_text_edit->find(text, flags); + break; + } + case find_type::last: + { + m_text_edit->moveCursor(QTextCursor::End); + m_text_edit->find(text, flags | QTextDocument::FindBackward); + break; + } + case find_type::next: + { + m_text_edit->setTextCursor(old_cursor); + m_text_edit->find(text, flags); + break; + } + case find_type::prev: + { + m_text_edit->setTextCursor(old_cursor); + m_text_edit->find(text, flags | QTextDocument::FindBackward); + break; + } + } + + const QTextCursor cursor = m_text_edit->textCursor(); + const QTextBlock block = cursor.block(); + const QTextLayout* layout = block.layout(); + + const int relative_pos = cursor.position() - block.position(); + const QTextLine line = layout->lineForTextPosition(relative_pos); + const int pos_in_line = relative_pos - line.textStart(); + + const int current_line = line.lineNumber(); + const int current_pos = pos_in_line; + + int word_count = 0; + for (const auto& [block, lines] : block_indices) + { + const bool is_current_block = block == cursor.blockNumber(); + + for (const auto& [line, positions] : lines) { + const bool is_current_line = line == current_line; + m_count_lines++; - old_line_index = new_line_index; + + int pos_count = 0; + + for (int pos : positions) + { + pos_count++; + word_count++; + + if (is_current_block && is_current_line && pos == current_pos) + { + m_current_line = m_count_lines; + m_current_index = word_count; + } + } } } - m_text_edit->setTextCursor(old_cursor); show_count(); - return m_count_total; -} - -void find_dialog::find_first() -{ - if (count_all() <= 0) - return; - - m_text_edit->moveCursor(QTextCursor::Start); - m_text_edit->find(m_find_bar->text()); -} - -void find_dialog::find_last() -{ - if (count_all() <= 0) - return; - - m_text_edit->moveCursor(QTextCursor::End); - m_text_edit->find(m_find_bar->text(), QTextDocument::FindBackward); -} - -void find_dialog::find_next() -{ - if (count_all() <= 0) - return; - - m_text_edit->find(m_find_bar->text()); -} - -void find_dialog::find_previous() -{ - if (count_all() <= 0) - return; - - m_text_edit->find(m_find_bar->text(), QTextDocument::FindBackward); } void find_dialog::show_count() const { - m_label_count_lines->setText(tr("Counted in lines: %0").arg(m_count_lines)); - m_label_count_total->setText(tr("Counted in total: %0").arg(m_count_total)); + m_label_count_lines->setText(tr("Line %0/%1").arg(m_current_line).arg(m_count_lines)); + m_label_count_total->setText(tr("Word %0/%1").arg(m_current_index).arg(m_count_total)); } diff --git a/rpcs3/rpcs3qt/find_dialog.h b/rpcs3/rpcs3qt/find_dialog.h index 27baf03c75..a4e9293fc6 100644 --- a/rpcs3/rpcs3qt/find_dialog.h +++ b/rpcs3/rpcs3qt/find_dialog.h @@ -3,7 +3,6 @@ #include #include #include -#include #include class find_dialog : public QDialog @@ -14,22 +13,26 @@ public: find_dialog(QPlainTextEdit* edit, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); private: + enum class find_type + { + first, + last, + next, + prev + }; + + void find(find_type type); + void show_count() const; + int m_count_lines = 0; int m_count_total = 0; + int m_current_line = 0; + int m_current_index = 0; + + bool m_case_sensitive = false; + QLabel* m_label_count_lines; QLabel* m_label_count_total; QPlainTextEdit* m_text_edit; QLineEdit* m_find_bar; - QPushButton* m_find_first; - QPushButton* m_find_last; - QPushButton* m_find_next; - QPushButton* m_find_previous; - -private Q_SLOTS: - int count_all(); - void find_first(); - void find_last(); - void find_next(); - void find_previous(); - void show_count() const; };