diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj
index 5f4a3154d5..a1a18ebc2e 100644
--- a/rpcs3/rpcs3.vcxproj
+++ b/rpcs3/rpcs3.vcxproj
@@ -912,6 +912,7 @@
true
+
@@ -1286,6 +1287,7 @@
.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"
+
diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters
index 0461e80cb9..87a76c0905 100644
--- a/rpcs3/rpcs3.vcxproj.filters
+++ b/rpcs3/rpcs3.vcxproj.filters
@@ -584,6 +584,9 @@
Gui\game list
+
+ Gui\misc dialogs
+
@@ -661,6 +664,9 @@
Io\evdev
+
+ Gui\misc dialogs
+
Gui\game list
diff --git a/rpcs3/rpcs3qt/find_dialog.cpp b/rpcs3/rpcs3qt/find_dialog.cpp
new file mode 100644
index 0000000000..ae059ab392
--- /dev/null
+++ b/rpcs3/rpcs3qt/find_dialog.cpp
@@ -0,0 +1,73 @@
+#include "find_dialog.h"
+
+#include
+
+find_dialog::find_dialog(QTextEdit* edit, QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f), m_text_edit(edit)
+{
+ setWindowTitle(tr("Find string"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ m_find_bar = new QLineEdit();
+ m_find_bar->setPlaceholderText(tr("Search..."));
+
+ 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"));
+
+ QHBoxLayout* button_layout = new QHBoxLayout();
+ button_layout->addWidget(m_find_first);
+ button_layout->addWidget(m_find_last);
+ button_layout->addWidget(m_find_next);
+ button_layout->addWidget(m_find_previous);
+
+ QVBoxLayout* layout = new QVBoxLayout();
+ layout->addWidget(m_find_bar);
+ layout->addLayout(button_layout);
+ setLayout(layout);
+
+ connect(m_find_first, &QPushButton::pressed, this, &find_dialog::find_first);
+ connect(m_find_last, &QPushButton::pressed, this, &find_dialog::find_last);
+ connect(m_find_next, &QPushButton::pressed, this, &find_dialog::find_next);
+ connect(m_find_previous, &QPushButton::pressed, this, &find_dialog::find_previous);
+
+ show();
+}
+
+find_dialog::~find_dialog()
+{
+}
+
+void find_dialog::find_first()
+{
+ if (!m_text_edit || m_find_bar->text().isEmpty())
+ return;
+
+ m_text_edit->moveCursor(QTextCursor::Start);
+ m_text_edit->find(m_find_bar->text());
+}
+
+void find_dialog::find_last()
+{
+ if (!m_text_edit || m_find_bar->text().isEmpty())
+ return;
+
+ m_text_edit->moveCursor(QTextCursor::End);
+ m_text_edit->find(m_find_bar->text(), QTextDocument::FindBackward);
+}
+
+void find_dialog::find_next()
+{
+ if (!m_text_edit || m_find_bar->text().isEmpty())
+ return;
+
+ m_text_edit->find(m_find_bar->text());
+}
+
+void find_dialog::find_previous()
+{
+ if (!m_text_edit || m_find_bar->text().isEmpty())
+ return;
+
+ m_text_edit->find(m_find_bar->text(), QTextDocument::FindBackward);
+}
diff --git a/rpcs3/rpcs3qt/find_dialog.h b/rpcs3/rpcs3qt/find_dialog.h
new file mode 100644
index 0000000000..4bcefe7e6c
--- /dev/null
+++ b/rpcs3/rpcs3qt/find_dialog.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+class find_dialog : public QDialog
+{
+public:
+ find_dialog(QTextEdit* edit, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
+ ~find_dialog();
+
+private:
+ QTextEdit* 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:
+ void find_first();
+ void find_last();
+ void find_next();
+ void find_previous();
+};
diff --git a/rpcs3/rpcs3qt/log_frame.cpp b/rpcs3/rpcs3qt/log_frame.cpp
index 8ee5a92813..e3d08b9ae5 100644
--- a/rpcs3/rpcs3qt/log_frame.cpp
+++ b/rpcs3/rpcs3qt/log_frame.cpp
@@ -102,22 +102,24 @@ static gui_listener s_gui_listener;
log_frame::log_frame(std::shared_ptr guiSettings, QWidget *parent) : QDockWidget(tr("Log"), parent), xgui_settings(guiSettings)
{
- QTabWidget* tabWidget = new QTabWidget;
+ m_tabWidget = new QTabWidget;
- m_log = new QTextEdit(tabWidget);
+ m_log = new QTextEdit(m_tabWidget);
m_log->setObjectName("log_frame");
m_log->setReadOnly(true);
m_log->setContextMenuPolicy(Qt::CustomContextMenu);
+ m_log->installEventFilter(this);
- m_tty = new QTextEdit(tabWidget);
+ m_tty = new QTextEdit(m_tabWidget);
m_tty->setObjectName("tty_frame");
m_tty->setReadOnly(true);
m_tty->setContextMenuPolicy(Qt::CustomContextMenu);
+ m_tty->installEventFilter(this);
- tabWidget->addTab(m_log, tr("Log"));
- tabWidget->addTab(m_tty, tr("TTY"));
+ m_tabWidget->addTab(m_log, tr("Log"));
+ m_tabWidget->addTab(m_tty, tr("TTY"));
- setWidget(tabWidget);
+ setWidget(m_tabWidget);
// Open or create TTY.log
m_tty_file.open(fs::get_config_dir() + "TTY.log", fs::read + fs::create);
@@ -259,6 +261,12 @@ void log_frame::CreateAndConnectActions()
menu->exec(mapToGlobal(pos));
});
+ connect(m_tabWidget, &QTabWidget::currentChanged, [this](int index)
+ {
+ if (m_find_dialog)
+ m_find_dialog->close();
+ });
+
LoadSettings();
}
@@ -435,3 +443,25 @@ void log_frame::closeEvent(QCloseEvent *event)
QDockWidget::closeEvent(event);
Q_EMIT LogFrameClosed();
}
+
+bool log_frame::eventFilter(QObject* object, QEvent* event)
+{
+ if (object != m_log && object != m_tty)
+ {
+ return QDockWidget::eventFilter(object, event);
+ }
+
+ if (event->type() == QEvent::KeyPress)
+ {
+ QKeyEvent* e = (QKeyEvent*)event;
+ if (e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_F)
+ {
+ if (m_find_dialog && m_find_dialog->isVisible())
+ m_find_dialog->close();
+
+ m_find_dialog = std::make_unique((QTextEdit*)object, this);
+ }
+ }
+
+ return QDockWidget::eventFilter(object, event);
+}
diff --git a/rpcs3/rpcs3qt/log_frame.h b/rpcs3/rpcs3qt/log_frame.h
index 76f2fad1c7..2348cffc82 100644
--- a/rpcs3/rpcs3qt/log_frame.h
+++ b/rpcs3/rpcs3qt/log_frame.h
@@ -4,6 +4,7 @@
#include "Utilities/Log.h"
#include "gui_settings.h"
+#include "find_dialog.h"
#include
@@ -12,6 +13,7 @@
#include
#include
#include
+#include
class log_frame : public QDockWidget
{
@@ -31,6 +33,7 @@ Q_SIGNALS:
protected:
/** Override inherited method from Qt to allow signalling when close happened.*/
void closeEvent(QCloseEvent* event);
+ bool eventFilter(QObject* object, QEvent* event) override;
private Q_SLOTS:
void UpdateUI();
private:
@@ -39,6 +42,10 @@ private:
void CreateAndConnectActions();
+ QTabWidget* m_tabWidget;
+
+ std::unique_ptr m_find_dialog;
+
QList m_color;
QColor m_color_stack;
QTextEdit *m_log;