aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorConfuSomu2023-08-02 01:56:58 +0200
committerConfuSomu2023-08-02 01:56:58 +0200
commit42434314d65cdc29402c7adcb08c2fa5113f7ca2 (patch)
tree703e792905b16d02c7137dd8cf7b60ed8d911890 /src
parentcdd08523b9af7afda906766d22197a066c9264f3 (diff)
downloadActorViewer-42434314d65cdc29402c7adcb08c2fa5113f7ca2.tar
ActorViewer-42434314d65cdc29402c7adcb08c2fa5113f7ca2.tar.gz
ActorViewer-42434314d65cdc29402c7adcb08c2fa5113f7ca2.zip
Implement find dialog
This dialog consolidates options for searching through textual elements in lists which simplifies the logic present in the MainWindow class.
Diffstat (limited to 'src')
-rw-r--r--src/finddialog.cpp134
-rw-r--r--src/finddialog.h49
-rw-r--r--src/finddialog.ui176
-rw-r--r--src/mainwindow.cpp39
-rw-r--r--src/mainwindow.h11
5 files changed, 390 insertions, 19 deletions
diff --git a/src/finddialog.cpp b/src/finddialog.cpp
new file mode 100644
index 0000000..4de17d0
--- /dev/null
+++ b/src/finddialog.cpp
@@ -0,0 +1,134 @@
+#include "finddialog.h"
+#include "./ui_finddialog.h"
+
+#include <QListWidgetItem>
+#include <QTimer>
+#include <QDebug>
+#include <qnamespace.h>
+#include <qtimer.h>
+
+FindDialog::FindDialog(QWidget* parent)
+ : QDialog(parent, Qt::Tool), ui(new Ui::FindDialog)
+{
+ ui->setupUi(this);
+}
+
+FindDialog::~FindDialog() {
+ 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) {
+ ui->textInputSearch->setText(text);
+}
+
+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() {
+ QString current_search = ui->textInputSearch->text();
+ if (*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."));
+}
+
+
diff --git a/src/finddialog.h b/src/finddialog.h
new file mode 100644
index 0000000..c6907f8
--- /dev/null
+++ b/src/finddialog.h
@@ -0,0 +1,49 @@
+#pragma once
+#include <QDialog>
+#include <QListWidget>
+#include "./ui_finddialog.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class FindDialog; }
+QT_END_NAMESPACE
+
+class FindDialog : public QDialog {
+ Q_OBJECT
+
+public:
+ FindDialog(QWidget *parent = nullptr);
+ ~FindDialog();
+
+public slots:
+ void set_search_text(const QString &text);
+ void set_qlist_widget(QListWidget* widget);
+ inline void run_search();
+
+signals:
+ void item_selected(QListWidgetItem* item);
+ void search_text_changed(const QString &text);
+
+private slots:
+ void on_textInputSearch_textEdited(const QString &text);
+ void on_buttonSearchPrev_clicked();
+ void on_buttonSearchNext_clicked();
+ void on_hSlider_valueChanged(int value);
+ void on_spinBox_valueChanged(int value);
+
+private:
+ Ui::FindDialog* ui;
+
+ QListWidget* list_widget = nullptr;
+ QString* last_search = new QString;
+ QList<QListWidgetItem*> matches;
+ int selected_match = 0;
+ int total_matches = 0;
+
+ // This is used with the spin box to avoid having repeated value changes due to the on_spinBox_valueChanged slot
+ bool value_changed_processed = false;
+
+ void init_search();
+ void update_status();
+ void select_match();
+ bool has_search_changed();
+};
diff --git a/src/finddialog.ui b/src/finddialog.ui
new file mode 100644
index 0000000..0ee159c
--- /dev/null
+++ b/src/finddialog.ui
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>FindDialog</class>
+ <widget class="QDialog" name="FindDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>336</width>
+ <height>135</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>135</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>135</height>
+ </size>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::WheelFocus</enum>
+ </property>
+ <property name="windowTitle">
+ <string>Find</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_root">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_find" stretch="1,0,0">
+ <item>
+ <widget class="QLineEdit" name="textInputSearch">
+ <property name="placeholderText">
+ <string>Search in list</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonSearchPrev">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>48</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Previous</string>
+ </property>
+ <property name="text">
+ <string>↑</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonSearchNext">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>48</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Next</string>
+ </property>
+ <property name="text">
+ <string>↓</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_slider">
+ <item>
+ <widget class="QSlider" name="hSlider">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="spinBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_status">
+ <item>
+ <widget class="QLabel" name="statusLabel">
+ <property name="text">
+ <string>Ready.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Close</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>FindDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>FindDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 363f2b1..2b8a0df 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1,6 +1,7 @@
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include "src/archive_parser.h"
+#include "src/finddialog.h"
#include "src/list_item.h"
#include "src/command_line.h"
@@ -100,29 +101,29 @@ void MainWindow::on_actionCopy_status_triggered(bool checked) {
}
void MainWindow::on_buttonSearch_clicked() {
- static QString* last_search = new QString;
- static int selected_match = 0;
-
- QString current_search = ui->textInputSearch->text();
+ if (!find_dialog) {
+ find_dialog = new FindDialog(this);
+ find_dialog->set_qlist_widget(ui->listWidget);
+ connect(find_dialog, &FindDialog::item_selected, this, &MainWindow::select_list_item);
+ connect(this, &MainWindow::search_text_changed, find_dialog, &FindDialog::set_search_text);
+ connect(find_dialog, &FindDialog::search_text_changed, this, &MainWindow::set_search_text);
+ }
- QList<QListWidgetItem*> matches = ui->listWidget->findItems(current_search, Qt::MatchContains);
+ find_dialog->show();
+ find_dialog->raise();
+ find_dialog->activateWindow();
+}
- if (not (*last_search == current_search)) {
- *last_search = current_search;
- selected_match = 0;
- } else if (++selected_match >= matches.size()) selected_match = 0;
+void MainWindow::select_list_item(QListWidgetItem* item) {
+ on_listWidget_itemActivated(item);
+}
- if (not matches.isEmpty()) {
- ui->listWidget->scrollToItem(matches[selected_match], QAbstractItemView::EnsureVisible);
- ui->listWidget->setCurrentItem(matches[selected_match]);
- on_listWidget_itemActivated(matches[selected_match]);
- }
+void MainWindow::on_textInputSearch_textEdited(const QString &text) {
+ emit search_text_changed(text);
+}
- if (matches.size() > 0)
- ui->statusbar->showMessage(tr("Search result %1 out of %2")
- .arg(selected_match+1)
- .arg(matches.size()));
- else ui->statusbar->showMessage(tr("No search results."));
+void MainWindow::set_search_text(const QString &text) {
+ ui->textInputSearch->setText(text);
}
void MainWindow::relist_statuses() {
diff --git a/src/mainwindow.h b/src/mainwindow.h
index abf9acc..7b87880 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -9,6 +9,7 @@
#include "archive_parser.h"
#include "types.h"
#include "command_line.h"
+#include "finddialog.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
@@ -24,6 +25,13 @@ public:
void act_command_line(CommandLineParsedOptions &options, QCommandLineParser &parser);
+public slots:
+ void select_list_item(QListWidgetItem* item);
+ void set_search_text(const QString &text);
+
+signals:
+ void search_text_changed(const QString &text);
+
private slots:
void on_actionOpen_triggered(bool checked);
void on_actionQuit_triggered(bool checked);
@@ -39,6 +47,7 @@ private slots:
void on_actionRandom_status_triggered(bool checked);
void on_actionCopy_status_triggered(bool checked);
+ void on_textInputSearch_textEdited(const QString &text);
void on_buttonSearch_clicked();
void on_menuView_aboutToHide();
@@ -54,6 +63,8 @@ private:
void finish_listWidget_itemActivated(const QString& status_info);
void finish_open_file(const Archive::InitError& parse_error);
+ FindDialog* find_dialog = nullptr;
+
QString open_file_filename;
Ui::MainWindow *ui;