#include "finddialog.h" #include "./ui_finddialog.h" #include #include FindDialog::FindDialog(QWidget* parent) : QDialog(parent, Qt::Tool), ui(new Ui::FindDialog) { ui->setupUi(this); } FindDialog::~FindDialog() { delete last_search; delete ui; } void FindDialog::on_buttonSearchPrev_clicked() { if (--selected_match < 0) { selected_match = total_matches - 1; ui->statusLabel->setText(tr("Reached top, continued from bottom.")); } else update_status(); select_match(); } void FindDialog::on_buttonSearchNext_clicked() { if (++selected_match >= total_matches) { selected_match = 0; ui->statusLabel->setText(tr("Reached bottom, continued from top.")); } else update_status(); select_match(); } // Update the textbox in the main window and search after 400 ms of no typing void FindDialog::on_textInputSearch_textEdited(const QString &text) { emit search_text_changed(text); static QTimer* differed_search = new QTimer(this); if (static bool timer_init_done = false; not timer_init_done) { differed_search->setTimerType(Qt::CoarseTimer); differed_search->setSingleShot(true); differed_search->setInterval(400); connect(differed_search, &QTimer::timeout, this, &FindDialog::run_search); timer_init_done = true; } differed_search->start(); } void FindDialog::set_search_text(const QString &text, bool search_immediately) { ui->textInputSearch->setText(text); if (search_immediately) init_search(); else on_textInputSearch_textEdited(text); } void FindDialog::force_research() { init_search(true); } inline void FindDialog::run_search() { init_search(); } void FindDialog::on_hSlider_valueChanged(int value) { selected_match = value; update_status(); select_match(); } void FindDialog::on_spinBox_valueChanged(int value) { // Avoids repeatedly changing the selected_match as the valueChanged signal is a notifier for the spin box's value if (not value_changed_processed) { selected_match = value - 1; update_status(); select_match(); } value_changed_processed = false; } void FindDialog::set_qlist_widget(QListWidget* widget) { list_widget = widget; } // Start a new search only if the search text input has changed void FindDialog::init_search(bool force) { QString current_search = ui->textInputSearch->text(); if (not force and (*last_search == current_search or not list_widget)) return; matches = list_widget->findItems(current_search, Qt::MatchContains); *last_search = current_search; selected_match = 0; total_matches = matches.size(); if (total_matches > 0) { ui->hSlider->setEnabled(true); ui->spinBox->setEnabled(true); ui->buttonSearchPrev->setEnabled(true); ui->buttonSearchNext->setEnabled(true); } else { ui->spinBox->setEnabled(false); ui->hSlider->setEnabled(false); ui->buttonSearchPrev->setEnabled(false); ui->buttonSearchNext->setEnabled(false); } // Set the minimum as when there are no matches, the widget would return out of range index values to having an out of range minimum. ui->hSlider->setMinimum(0); ui->spinBox->setMinimum(1); ui->hSlider->setMaximum(total_matches - 1); ui->spinBox->setMaximum(total_matches); select_match(); update_status(); } // Activate the match requested by the user void FindDialog::select_match() { if (list_widget and total_matches != 0 and selected_match >= 0) { list_widget->scrollToItem(matches[selected_match], QAbstractItemView::EnsureVisible); list_widget->setCurrentItem(matches[selected_match]); emit item_selected(matches[selected_match]); } // Best place to update these sliders as select_match is always called by each input ui->hSlider->setValue(selected_match); ui->spinBox->setValue(selected_match + 1); value_changed_processed = true; } // Update the status line with current search information void FindDialog::update_status() { if (total_matches > 0) { ui->statusLabel->setText(tr("Search result %1 out of %2.") .arg(selected_match+1) .arg(total_matches)); } else ui->statusLabel->setText(tr("No search results.")); }