Qt: Implement config check in Utilities and log viewer

This commit is contained in:
Megamouse 2022-12-21 22:07:06 +01:00
parent f545532556
commit 96c6dc01eb
10 changed files with 341 additions and 13 deletions

View File

@ -80,7 +80,13 @@ namespace cfg
// Convert to string (optional) // Convert to string (optional)
virtual std::string to_string() const virtual std::string to_string() const
{ {
return{}; return {};
}
// Convert default to string (optional)
virtual std::string def_to_string() const
{
return {};
} }
// Try to convert from string (optional) // Try to convert from string (optional)
@ -89,7 +95,7 @@ namespace cfg
// Get string list (optional) // Get string list (optional)
virtual std::vector<std::string> to_list() const virtual std::vector<std::string> to_list() const
{ {
return{}; return {};
} }
// Set multiple values. Implementation-specific, optional. // Set multiple values. Implementation-specific, optional.
@ -163,6 +169,11 @@ namespace cfg
return m_value ? "true" : "false"; return m_value ? "true" : "false";
} }
std::string def_to_string() const override
{
return def ? "true" : "false";
}
bool from_string(std::string_view value, bool /*dynamic*/ = false) override bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{ {
if (value.size() != 4 && value.size() != 5) if (value.size() != 4 && value.size() != 5)
@ -232,6 +243,13 @@ namespace cfg
return result; // TODO: ??? return result; // TODO: ???
} }
std::string def_to_string() const override
{
std::string result;
fmt_class_string<T>::format(result, fmt_unveil<T>::get(def));
return result; // TODO: ???
}
bool from_string(std::string_view value, bool /*dynamic*/ = false) override bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{ {
u64 result; u64 result;
@ -297,6 +315,11 @@ namespace cfg
return std::to_string(m_value); return std::to_string(m_value);
} }
std::string def_to_string() const override
{
return std::to_string(def);
}
bool from_string(std::string_view value, bool /*dynamic*/ = false) override bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{ {
s64 result; s64 result;
@ -363,6 +386,11 @@ namespace cfg
return std::to_string(m_value); return std::to_string(m_value);
} }
std::string def_to_string() const override
{
return std::to_string(def);
}
bool from_string(std::string_view value, bool /*dynamic*/ = false) override bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{ {
f64 result; f64 result;
@ -437,6 +465,11 @@ namespace cfg
return std::to_string(m_value); return std::to_string(m_value);
} }
std::string def_to_string() const override
{
return std::to_string(def);
}
bool from_string(std::string_view value, bool /*dynamic*/ = false) override bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{ {
u64 result; u64 result;
@ -508,6 +541,11 @@ namespace cfg
return *m_value.load().get(); return *m_value.load().get();
} }
std::string def_to_string() const override
{
return def;
}
bool from_string(std::string_view value, bool /*dynamic*/ = false) override bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{ {
m_value = std::string(value); m_value = std::string(value);
@ -541,7 +579,7 @@ namespace cfg
std::vector<std::string> to_list() const override std::vector<std::string> to_list() const override
{ {
return{ m_set.begin(), m_set.end() }; return { m_set.begin(), m_set.end() };
} }
bool from_list(std::vector<std::string>&& list) override bool from_list(std::vector<std::string>&& list) override

View File

@ -209,6 +209,9 @@
<ClCompile Include="QTGeneratedFiles\Debug\moc_cheat_manager.cpp"> <ClCompile Include="QTGeneratedFiles\Debug\moc_cheat_manager.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_config_checker.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_custom_dialog.cpp"> <ClCompile Include="QTGeneratedFiles\Debug\moc_custom_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -431,6 +434,9 @@
<ClCompile Include="QTGeneratedFiles\Release\moc_cheat_manager.cpp"> <ClCompile Include="QTGeneratedFiles\Release\moc_cheat_manager.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_config_checker.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_custom_dialog.cpp"> <ClCompile Include="QTGeneratedFiles\Release\moc_custom_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -627,6 +633,7 @@
<ClCompile Include="rpcs3qt\camera_settings_dialog.cpp" /> <ClCompile Include="rpcs3qt\camera_settings_dialog.cpp" />
<ClCompile Include="rpcs3qt\cheat_manager.cpp" /> <ClCompile Include="rpcs3qt\cheat_manager.cpp" />
<ClCompile Include="rpcs3qt\config_adapter.cpp" /> <ClCompile Include="rpcs3qt\config_adapter.cpp" />
<ClCompile Include="rpcs3qt\config_checker.cpp" />
<ClCompile Include="rpcs3qt\curl_handle.cpp" /> <ClCompile Include="rpcs3qt\curl_handle.cpp" />
<ClCompile Include="rpcs3qt\custom_dialog.cpp" /> <ClCompile Include="rpcs3qt\custom_dialog.cpp" />
<ClCompile Include="rpcs3qt\custom_table_widget_item.cpp" /> <ClCompile Include="rpcs3qt\custom_table_widget_item.cpp" />
@ -960,6 +967,16 @@
</CustomBuild> </CustomBuild>
<ClInclude Include="rpcs3qt\category.h" /> <ClInclude Include="rpcs3qt\category.h" />
<ClInclude Include="rpcs3qt\config_adapter.h" /> <ClInclude Include="rpcs3qt\config_adapter.h" />
<CustomBuild Include="rpcs3qt\config_checker.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DHAVE_SDL2 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\libsdl-org\SDL\include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
</CustomBuild>
<ClInclude Include="rpcs3qt\curl_handle.h" /> <ClInclude Include="rpcs3qt\curl_handle.h" />
<ClInclude Include="rpcs3qt\custom_dock_widget.h" /> <ClInclude Include="rpcs3qt\custom_dock_widget.h" />
<CustomBuild Include="rpcs3qt\debugger_list.h"> <CustomBuild Include="rpcs3qt\debugger_list.h">

View File

@ -882,6 +882,15 @@
<ClCompile Include="Input\sdl_pad_handler.cpp"> <ClCompile Include="Input\sdl_pad_handler.cpp">
<Filter>Io\SDL</Filter> <Filter>Io\SDL</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="rpcs3qt\config_checker.cpp">
<Filter>Gui\log</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_config_checker.cpp">
<Filter>Generated Files\Debug</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_config_checker.cpp">
<Filter>Generated Files\Release</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Input\ds4_pad_handler.h"> <ClInclude Include="Input\ds4_pad_handler.h">
@ -1306,6 +1315,9 @@
<CustomBuild Include="rpcs3qt\pad_motion_settings_dialog.ui"> <CustomBuild Include="rpcs3qt\pad_motion_settings_dialog.ui">
<Filter>Form Files</Filter> <Filter>Form Files</Filter>
</CustomBuild> </CustomBuild>
<CustomBuild Include="rpcs3qt\config_checker.h">
<Filter>Gui\log</Filter>
</CustomBuild>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Image Include="rpcs3.ico" /> <Image Include="rpcs3.ico" />

View File

@ -11,6 +11,7 @@ set(SRC_FILES
cg_disasm_window.cpp cg_disasm_window.cpp
cheat_manager.cpp cheat_manager.cpp
config_adapter.cpp config_adapter.cpp
config_checker.cpp
curl_handle.cpp curl_handle.cpp
custom_dialog.cpp custom_dialog.cpp
custom_table_widget_item.cpp custom_table_widget_item.cpp

View File

@ -0,0 +1,213 @@
#include "stdafx.h"
#include "config_checker.h"
#include "Emu/system_config.h"
#include <QDialog>
#include <QDialogButtonBox>
#include <QMessageBox>
#include <QTextEdit>
#include <QVBoxLayout>
#include <QLabel>
LOG_CHANNEL(gui_log, "GUI");
config_checker::config_checker(QWidget* parent, const QString& path, bool is_log) : QDialog(parent)
{
setObjectName("config_checker");
setAttribute(Qt::WA_DeleteOnClose);
QVBoxLayout* layout = new QVBoxLayout();
QLabel* label = new QLabel(this);
layout->addWidget(label);
QString result;
if (check_config(path, result, is_log))
{
setWindowTitle(tr("Interesting!"));
if (result.isEmpty())
{
label->setText(tr("Found config.\nIt seems to match the default config."));
}
else
{
label->setText(tr("Found config.\nSome settings seem to deviate from the default config:"));
QTextEdit* text_box = new QTextEdit();
text_box->setReadOnly(true);
text_box->setHtml(result);
layout->addWidget(text_box);
resize(400, 600);
}
}
else
{
setWindowTitle(tr("Ooops!"));
label->setText(result);
}
QDialogButtonBox* box = new QDialogButtonBox(QDialogButtonBox::Close);
connect(box, &QDialogButtonBox::rejected, this, &QDialog::reject);
layout->addWidget(box);
setLayout(layout);
}
bool config_checker::check_config(QString content, QString& result, bool is_log)
{
cfg_root config{};
if (is_log)
{
const QString start_token = "SYS: Used configuration:\n";
const QString end_token = "\n·";
int start = content.indexOf(start_token);
int end = -1;
if (start >= 0)
{
start += start_token.count();
end = content.indexOf(end_token, start);
}
if (end < 0)
{
result = tr("Cannot find any config!");
return false;
}
content = content.mid(start, end - start);
}
if (!config.from_string(content.toStdString()))
{
gui_log.error("log_viewer: Failed to parse config:\n%s", content.toStdString());
result = tr("Cannot find any config!");
return false;
}
std::function<void(const cfg::_base*, std::string&, int)> print_diff_recursive;
print_diff_recursive = [&print_diff_recursive](const cfg::_base* base, std::string& diff, int indentation) -> void
{
if (!base)
{
return;
}
const auto indent = [](std::string& str, int indentation)
{
for (int i = 0; i < indentation * 2; i++)
{
str += "&nbsp;";
}
};
switch (base->get_type())
{
case cfg::type::node:
{
if (const auto& node = static_cast<const cfg::node*>(base))
{
std::string diff_tmp;
for (const auto& n : node->get_nodes())
{
print_diff_recursive(n, diff_tmp, indentation + 1);
}
if (!diff_tmp.empty())
{
indent(diff, indentation);
if (!base->get_name().empty())
{
fmt::append(diff, "<b>%s:</b><br>", base->get_name());
}
fmt::append(diff, "%s", diff_tmp);
}
}
break;
}
case cfg::type::_bool:
case cfg::type::_enum:
case cfg::type::_int:
case cfg::type::uint:
case cfg::type::string:
{
const std::string val = base->to_string();
const std::string def = base->def_to_string();
if (val != def)
{
indent(diff, indentation);
if (def.empty())
{
fmt::append(diff, "%s: <span style=\"color:red;\">%s</span><br>", base->get_name(), val);
}
else
{
fmt::append(diff, "%s: <span style=\"color:red;\">%s</span> <span style=\"color:gray;\">default:</span> <span style=\"color:green;\">%s</span><br>", base->get_name(), val, def);
}
}
break;
}
case cfg::type::set:
{
if (const auto& node = static_cast<const cfg::set_entry*>(base))
{
const std::vector<std::string> set_entries = node->to_list();
if (!set_entries.empty())
{
indent(diff, indentation);
fmt::append(diff, "<b>%s:</b><br>", base->get_name());
for (const std::string& entry : set_entries)
{
indent(diff, indentation + 1);
fmt::append(diff, "- <span style=\"color:red;\">%s</span><br>", entry);
}
}
}
break;
}
case cfg::type::log:
{
if (const auto& node = static_cast<const cfg::log_entry*>(base))
{
const auto& log_entries = node->get_map();
if (!log_entries.empty())
{
indent(diff, indentation);
fmt::append(diff, "<b>%s:</b><br>", base->get_name());
for (const auto& entry : log_entries)
{
indent(diff, indentation + 1);
fmt::append(diff, "<span style=\"color:red;\">%s: %s</span><br>", entry.first, entry.second);
}
}
}
break;
}
case cfg::type::map:
case cfg::type::device:
{
// Ignored
break;
}
}
};
std::string diff;
print_diff_recursive(&config, diff, 0);
result = QString::fromStdString(diff);
return true;
}

View File

@ -0,0 +1,13 @@
#pragma once
#include <QDialog>
class config_checker : public QDialog
{
Q_OBJECT
public:
config_checker(QWidget* parent, const QString& path, bool is_log);
bool check_config(QString content, QString& result, bool is_log);
};

View File

@ -145,6 +145,7 @@ namespace gui
const gui_save fd_ext_mself = gui_save(main_window, "lastExplorePathExMSELF", ""); const gui_save fd_ext_mself = gui_save(main_window, "lastExplorePathExMSELF", "");
const gui_save fd_ext_tar = gui_save(main_window, "lastExplorePathExTAR", ""); const gui_save fd_ext_tar = gui_save(main_window, "lastExplorePathExTAR", "");
const gui_save fd_insert_disc = gui_save(main_window, "lastExplorePathDISC", ""); const gui_save fd_insert_disc = gui_save(main_window, "lastExplorePathDISC", "");
const gui_save fd_cfg_check = gui_save(main_window, "lastExplorePathCfgChk", "");
const gui_save mw_debugger = gui_save(main_window, "debuggerVisible", false); const gui_save mw_debugger = gui_save(main_window, "debuggerVisible", false);
const gui_save mw_logger = gui_save(main_window, "loggerVisible", true); const gui_save mw_logger = gui_save(main_window, "loggerVisible", true);

View File

@ -4,6 +4,7 @@
#include "gui_settings.h" #include "gui_settings.h"
#include "syntax_highlighter.h" #include "syntax_highlighter.h"
#include "find_dialog.h" #include "find_dialog.h"
#include "config_checker.h"
#include <QApplication> #include <QApplication>
#include <QMenu> #include <QMenu>
@ -22,13 +23,6 @@
LOG_CHANNEL(gui_log, "GUI"); LOG_CHANNEL(gui_log, "GUI");
[[maybe_unused]] constexpr auto qstr = QString::fromStdString;
inline std::string sstr(const QString& _in)
{
return _in.toStdString();
}
log_viewer::log_viewer(std::shared_ptr<gui_settings> gui_settings) log_viewer::log_viewer(std::shared_ptr<gui_settings> gui_settings)
: m_gui_settings(std::move(gui_settings)) : m_gui_settings(std::move(gui_settings))
{ {
@ -70,6 +64,7 @@ void log_viewer::show_context_menu(const QPoint& pos)
QAction* open = new QAction(tr("&Open log file")); QAction* open = new QAction(tr("&Open log file"));
QAction* save = new QAction(tr("&Save filtered log")); QAction* save = new QAction(tr("&Save filtered log"));
QAction* filter = new QAction(tr("&Filter log")); QAction* filter = new QAction(tr("&Filter log"));
QAction* config = new QAction(tr("&Check config"));
QAction* timestamps = new QAction(tr("&Show Timestamps")); QAction* timestamps = new QAction(tr("&Show Timestamps"));
timestamps->setCheckable(true); timestamps->setCheckable(true);
@ -119,6 +114,8 @@ void log_viewer::show_context_menu(const QPoint& pos)
menu.addSeparator(); menu.addSeparator();
menu.addAction(save); menu.addAction(save);
menu.addSeparator(); menu.addSeparator();
menu.addAction(config);
menu.addSeparator();
menu.addAction(filter); menu.addAction(filter);
menu.addSeparator(); menu.addSeparator();
menu.addAction(timestamps); menu.addAction(timestamps);
@ -156,14 +153,20 @@ void log_viewer::show_context_menu(const QPoint& pos)
{ {
log_file.write(m_log_text->toPlainText().toUtf8()); log_file.write(m_log_text->toPlainText().toUtf8());
log_file.close(); log_file.close();
gui_log.success("Exported filtered log to file '%s'", sstr(file_path)); gui_log.success("Exported filtered log to file '%s'", file_path.toStdString());
} }
else else
{ {
gui_log.error("Failed to export filtered log to file '%s'", sstr(file_path)); gui_log.error("Failed to export filtered log to file '%s'", file_path.toStdString());
} }
}); });
connect(config, &QAction::triggered, this, [this]()
{
config_checker* dlg = new config_checker(this, m_full_log, true);
dlg->exec();
});
connect(filter, &QAction::triggered, this, [this]() connect(filter, &QAction::triggered, this, [this]()
{ {
m_filter_term = QInputDialog::getText(this, tr("Filter log"), tr("Enter text"), QLineEdit::EchoMode::Normal, m_filter_term); m_filter_term = QInputDialog::getText(this, tr("Filter log"), tr("Enter text"), QLineEdit::EchoMode::Normal, m_filter_term);
@ -230,7 +233,7 @@ void log_viewer::show_log()
} }
else else
{ {
gui_log.error("log_viewer: Failed to open %s", sstr(m_path_last)); gui_log.error("log_viewer: Failed to open %s", m_path_last.toStdString());
m_log_text->setPlainText(tr("Failed to open '%0'").arg(m_path_last)); m_log_text->setPlainText(tr("Failed to open '%0'").arg(m_path_last));
} }

View File

@ -31,6 +31,7 @@
#include "camera_settings_dialog.h" #include "camera_settings_dialog.h"
#include "ipc_settings_dialog.h" #include "ipc_settings_dialog.h"
#include "shortcut_utils.h" #include "shortcut_utils.h"
#include "config_checker.h"
#include <thread> #include <thread>
#include <charconv> #include <charconv>
@ -2375,6 +2376,29 @@ void main_window::CreateConnects()
viewer->show_log(); viewer->show_log();
}); });
connect(ui->toolsCheckConfigAct, &QAction::triggered, this, [this]
{
const QString path_last_cfg = m_gui_settings->GetValue(gui::fd_cfg_check).toString();
const QString file_path = QFileDialog::getOpenFileName(this, tr("Select rpcs3.log or config.yml"), path_last_cfg, tr("Log files (*.log);;Config Files (*.yml);;All files (*.*)"));
if (file_path.isEmpty())
{
// Aborted
return;
}
QFile file(file_path);
if (!file.exists() || !file.open(QIODevice::ReadOnly))
{
QMessageBox::warning(this, tr("Failed to open file"), tr("The file could not be opened:\n%0").arg(file_path));
return;
}
m_gui_settings->SetValue(gui::fd_cfg_check, QFileInfo(file_path).path());
config_checker* dlg = new config_checker(this, file.readAll(), file_path.endsWith(".log"));
dlg->exec();
});
connect(ui->toolskernel_explorerAct, &QAction::triggered, this, [this] connect(ui->toolskernel_explorerAct, &QAction::triggered, this, [this]
{ {
if (!m_kernel_explorer) if (!m_kernel_explorer)

View File

@ -268,6 +268,7 @@
<string>Utilities</string> <string>Utilities</string>
</property> </property>
<addaction name="actionLog_Viewer"/> <addaction name="actionLog_Viewer"/>
<addaction name="toolsCheckConfigAct"/>
<addaction name="toolsCgDisasmAct"/> <addaction name="toolsCgDisasmAct"/>
<addaction name="toolskernel_explorerAct"/> <addaction name="toolskernel_explorerAct"/>
<addaction name="toolsmemory_viewerAct"/> <addaction name="toolsmemory_viewerAct"/>
@ -1233,6 +1234,11 @@
<string>Insert Disc</string> <string>Insert Disc</string>
</property> </property>
</action> </action>
<action name="toolsCheckConfigAct">
<property name="text">
<string>Check Config</string>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<resources> <resources>