mirror of
https://github.com/InoriRus/Kyty.git
synced 2026-08-28 05:06:40 +00:00
add launcher
This commit is contained in:
@@ -0,0 +1 @@
|
||||
#include "Configuration.h"
|
||||
@@ -0,0 +1,386 @@
|
||||
#include "ConfigurationEditDialog.h"
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "ConfigurationListWidget.h"
|
||||
#include "MainDialog.h"
|
||||
#include "MandatoryLineEdit.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QCheckBox>
|
||||
#include <QColor>
|
||||
#include <QComboBox>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QFileDialog>
|
||||
#include <QFlags>
|
||||
#include <QInternal>
|
||||
#include <QLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QList>
|
||||
#include <QListWidget>
|
||||
#include <QListWidgetItem>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QSettings>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
|
||||
#include "ui_configuration_edit_dialog.h"
|
||||
|
||||
constexpr char SETTINGS_CFG_DIALOG[] = "ConfigurationEditDialog";
|
||||
constexpr char SETTINGS_CFG_LAST_GEOMETRY[] = "geometry";
|
||||
constexpr char SETTINGS_LAST_BASE_DIR[] = "last_base_dir";
|
||||
constexpr char COLOR_SELECTED[] = "#e2ffe2";
|
||||
constexpr char COLOR_NOT_SELECTED[] = "#ffffff";
|
||||
|
||||
static void ChangeColor(QListWidgetItem* item)
|
||||
{
|
||||
if (item->checkState() == Qt::Checked)
|
||||
{
|
||||
item->setBackground(QColor(COLOR_SELECTED));
|
||||
} else
|
||||
{
|
||||
item->setBackground(QColor(COLOR_NOT_SELECTED));
|
||||
}
|
||||
}
|
||||
|
||||
ConfigurationEditDialog::ConfigurationEditDialog(Kyty::Configuration* info, ConfigurationListWidget* parent)
|
||||
: QDialog(parent, Qt::WindowCloseButtonHint), m_ui(new Ui::ConfigurationEditDialog), m_parent(parent)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
connect(m_ui->ok_button, &QPushButton::clicked, this, &ConfigurationEditDialog::save);
|
||||
connect(m_ui->clear_button, &QPushButton::clicked, this, &ConfigurationEditDialog::clear);
|
||||
connect(m_ui->test_button, &QPushButton::clicked, this, &ConfigurationEditDialog::test);
|
||||
connect(m_ui->browse_base_dir_button, &QPushButton::clicked, this, &ConfigurationEditDialog::browse_base_path);
|
||||
connect(m_ui->comboBox_shader_log_direction, &QComboBox::currentTextChanged,
|
||||
[=](const QString& text)
|
||||
{
|
||||
auto log = TextToEnum<Kyty::Configuration::ShaderLogDirection>(text);
|
||||
m_ui->lineEdit_shader_log_folder->setEnabled(log == Kyty::Configuration::ShaderLogDirection::File);
|
||||
});
|
||||
connect(m_ui->checkBox_cmd_dump, &QCheckBox::toggled, [=](bool flag) { m_ui->lineEdit_cmd_dump_folder->setEnabled(flag); });
|
||||
connect(m_ui->comboBox_printf_direction, &QComboBox::currentTextChanged,
|
||||
[=](const QString& text)
|
||||
{
|
||||
auto log = TextToEnum<Kyty::Configuration::LogDirection>(text);
|
||||
m_ui->lineEdit_printf_file->setEnabled(log == Kyty::Configuration::LogDirection::File);
|
||||
});
|
||||
connect(m_ui->comboBox_profiler_direction, &QComboBox::currentTextChanged,
|
||||
[=](const QString& text)
|
||||
{
|
||||
auto log = TextToEnum<Kyty::Configuration::ProfilerDirection>(text);
|
||||
m_ui->lineEdit_profiler_file->setEnabled(log == Kyty::Configuration::ProfilerDirection::File ||
|
||||
log == Kyty::Configuration::ProfilerDirection::FileAndNetwork);
|
||||
});
|
||||
connect(m_ui->base_directory_lineedit, &QLineEdit::textChanged, this, &ConfigurationEditDialog::scan_elfs);
|
||||
connect(m_ui->listWidget_elfs, &QListWidget::itemChanged, this, &ChangeColor);
|
||||
connect(m_ui->listWidget_libs, &QListWidget::itemChanged, this, &ChangeColor);
|
||||
connect(&m_process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||
[=](int /*exitCode*/, QProcess::ExitStatus /*exitStatus*/) { m_ui->test_button->setEnabled(true); });
|
||||
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
||||
restoreGeometry(g_last_geometry);
|
||||
|
||||
m_info = info;
|
||||
|
||||
Init();
|
||||
|
||||
scan_libs();
|
||||
scan_elfs();
|
||||
}
|
||||
|
||||
QString ConfigurationEditDialog::g_last_base_dir;
|
||||
QByteArray ConfigurationEditDialog::g_last_geometry;
|
||||
|
||||
ConfigurationEditDialog::~ConfigurationEditDialog()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::WriteSettings(QSettings* s)
|
||||
{
|
||||
s->beginGroup(SETTINGS_CFG_DIALOG);
|
||||
|
||||
if (!g_last_base_dir.isEmpty())
|
||||
{
|
||||
s->setValue(SETTINGS_LAST_BASE_DIR, g_last_base_dir);
|
||||
}
|
||||
|
||||
if (!g_last_geometry.isEmpty())
|
||||
{
|
||||
s->setValue(SETTINGS_CFG_LAST_GEOMETRY, g_last_geometry);
|
||||
}
|
||||
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::ReadSettings(QSettings* s)
|
||||
{
|
||||
s->beginGroup(SETTINGS_CFG_DIALOG);
|
||||
|
||||
g_last_base_dir = s->value(SETTINGS_LAST_BASE_DIR, g_last_base_dir).toString();
|
||||
g_last_geometry = s->value(SETTINGS_CFG_LAST_GEOMETRY, g_last_geometry).toByteArray();
|
||||
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void ListInit(QComboBox* combo, T value)
|
||||
{
|
||||
combo->clear();
|
||||
combo->addItems(EnumToList<T>());
|
||||
combo->setCurrentText(EnumToText(value));
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::Init()
|
||||
{
|
||||
m_ui->name_lineedit->setText(m_info->Name);
|
||||
m_ui->base_directory_lineedit->setText(m_info->BaseDir);
|
||||
ListInit(m_ui->comboBox_screen_resolution, m_info->screen_resolution);
|
||||
m_ui->checkBox_neo->setChecked(m_info->neo);
|
||||
m_ui->checkBox_shader_validation->setChecked(m_info->shader_validation_enabled);
|
||||
m_ui->checkBox_vulkan_validation->setChecked(m_info->vulkan_validation_enabled);
|
||||
ListInit(m_ui->comboBox_shader_optimization_type, m_info->shader_optimization_type);
|
||||
ListInit(m_ui->comboBox_shader_log_direction, m_info->shader_log_direction);
|
||||
m_ui->lineEdit_shader_log_folder->setText(m_info->shader_log_folder);
|
||||
m_ui->checkBox_cmd_dump->setChecked(m_info->command_buffer_dump_enabled);
|
||||
m_ui->lineEdit_cmd_dump_folder->setText(m_info->command_buffer_dump_folder);
|
||||
ListInit(m_ui->comboBox_printf_direction, m_info->printf_direction);
|
||||
m_ui->lineEdit_printf_file->setText(m_info->printf_output_file);
|
||||
ListInit(m_ui->comboBox_profiler_direction, m_info->profiler_direction);
|
||||
m_ui->lineEdit_profiler_file->setText(m_info->profiler_output_file);
|
||||
m_ui->checkBox_spirv_printf->setChecked(m_info->spirv_debug_printf_enabled);
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::SetTitle(const QString& str)
|
||||
{
|
||||
setWindowTitle(str);
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::moveEvent(QMoveEvent* event)
|
||||
{
|
||||
QDialog::moveEvent(event);
|
||||
g_last_geometry = saveGeometry();
|
||||
}
|
||||
|
||||
static void UpdateList(QStringList* list, QStringList* list_selected, QListWidget* list_widget)
|
||||
{
|
||||
list->clear();
|
||||
list_selected->clear();
|
||||
int libs_count = list_widget->count();
|
||||
for (int i = 0; i < libs_count; i++)
|
||||
{
|
||||
auto* item = list_widget->item(i);
|
||||
if ((item->flags() & Qt::ItemIsEnabled) != 0)
|
||||
{
|
||||
*list << item->text();
|
||||
if (item->checkState() == Qt::Checked)
|
||||
{
|
||||
*list_selected << item->text();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateInfo(Kyty::Configuration* info, Ui::ConfigurationEditDialog* ui)
|
||||
{
|
||||
info->Name = ui->name_lineedit->text();
|
||||
info->BaseDir = ui->base_directory_lineedit->text();
|
||||
info->screen_resolution = TextToEnum<Kyty::Configuration::Resolution>(ui->comboBox_screen_resolution->currentText());
|
||||
info->neo = ui->checkBox_neo->isChecked();
|
||||
info->vulkan_validation_enabled = ui->checkBox_vulkan_validation->isChecked();
|
||||
info->shader_validation_enabled = ui->checkBox_shader_validation->isChecked();
|
||||
info->shader_optimization_type =
|
||||
TextToEnum<Kyty::Configuration::ShaderOptimizationType>(ui->comboBox_shader_optimization_type->currentText());
|
||||
info->shader_log_direction = TextToEnum<Kyty::Configuration::ShaderLogDirection>(ui->comboBox_shader_log_direction->currentText());
|
||||
info->shader_log_folder = ui->lineEdit_shader_log_folder->text();
|
||||
info->command_buffer_dump_enabled = ui->checkBox_cmd_dump->isChecked();
|
||||
info->command_buffer_dump_folder = ui->lineEdit_cmd_dump_folder->text();
|
||||
info->printf_direction = TextToEnum<Kyty::Configuration::LogDirection>(ui->comboBox_printf_direction->currentText());
|
||||
info->printf_output_file = ui->lineEdit_printf_file->text();
|
||||
info->profiler_direction = TextToEnum<Kyty::Configuration::ProfilerDirection>(ui->comboBox_profiler_direction->currentText());
|
||||
info->profiler_output_file = ui->lineEdit_profiler_file->text();
|
||||
info->spirv_debug_printf_enabled = ui->checkBox_spirv_printf->isChecked();
|
||||
|
||||
info->elfs.clear();
|
||||
info->elfs_selected.clear();
|
||||
int libs_count = ui->listWidget_elfs->count();
|
||||
for (int i = 0; i < libs_count; i++)
|
||||
{
|
||||
auto* item = ui->listWidget_elfs->item(i);
|
||||
if ((item->flags() & Qt::ItemIsEnabled) != 0)
|
||||
{
|
||||
info->elfs << item->text();
|
||||
if (item->checkState() == Qt::Checked)
|
||||
{
|
||||
info->elfs_selected << item->text();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateList(&info->elfs, &info->elfs_selected, ui->listWidget_elfs);
|
||||
UpdateList(&info->libs, &info->libs_selected, ui->listWidget_libs);
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::update_info()
|
||||
{
|
||||
UpdateInfo(m_info, m_ui);
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::adjust_size()
|
||||
{
|
||||
this->adjustSize();
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::save()
|
||||
{
|
||||
if (MandatoryLineEdit::FindEmpty(this))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Save failed"), tr("Please fill all mandatory fields"));
|
||||
return;
|
||||
}
|
||||
|
||||
update_info();
|
||||
|
||||
emit accept();
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::browse_base_path()
|
||||
{
|
||||
QString text = m_ui->base_directory_lineedit->text();
|
||||
|
||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), text.isEmpty() ? g_last_base_dir : text);
|
||||
|
||||
if (!dir.isEmpty())
|
||||
{
|
||||
m_ui->base_directory_lineedit->setText(dir);
|
||||
g_last_base_dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::scan_elfs()
|
||||
{
|
||||
auto dir = m_ui->base_directory_lineedit->text();
|
||||
auto qdir = QDir(dir);
|
||||
bool dir_exists = !dir.isEmpty() && qdir.exists();
|
||||
|
||||
QStringList elfs;
|
||||
|
||||
if (dir_exists)
|
||||
{
|
||||
QDirIterator it(dir, QStringList({"*.elf", "*.prx", "*.sprx", "eboot.bin"}), QDir::Files, QDirIterator::Subdirectories);
|
||||
while (it.hasNext())
|
||||
{
|
||||
auto file = it.next();
|
||||
elfs << qdir.relativeFilePath(file);
|
||||
}
|
||||
}
|
||||
|
||||
m_ui->listWidget_elfs->clear();
|
||||
|
||||
int selected_num = 0;
|
||||
|
||||
for (const auto& elf: m_info->elfs)
|
||||
{
|
||||
bool not_enabled = !elfs.contains(elf);
|
||||
bool selected = m_info->elfs_selected.contains(elf);
|
||||
|
||||
auto* item = new QListWidgetItem(elf, m_ui->listWidget_elfs);
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||
|
||||
if (not_enabled)
|
||||
{
|
||||
item->setCheckState(Qt::Unchecked);
|
||||
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
|
||||
} else
|
||||
{
|
||||
item->setCheckState(selected ? Qt::Checked : Qt::Unchecked);
|
||||
}
|
||||
|
||||
selected_num += (selected ? 1 : 0);
|
||||
}
|
||||
|
||||
for (const auto& elf: elfs)
|
||||
{
|
||||
if (!m_info->elfs.contains(elf))
|
||||
{
|
||||
auto* item = new QListWidgetItem(elf, m_ui->listWidget_elfs);
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||
item->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
}
|
||||
|
||||
m_ui->listWidget_elfs->sortItems();
|
||||
|
||||
m_ui->test_button->setEnabled(m_process.state() == QProcess::NotRunning && dir_exists);
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::scan_libs()
|
||||
{
|
||||
QStringList libs = KYTY_LIBS;
|
||||
|
||||
m_ui->listWidget_libs->clear();
|
||||
|
||||
int selected_num = 0;
|
||||
|
||||
for (const auto& lib: m_info->libs)
|
||||
{
|
||||
bool not_enabled = !libs.contains(lib);
|
||||
bool selected = m_info->libs_selected.contains(lib);
|
||||
|
||||
auto* item = new QListWidgetItem(lib, m_ui->listWidget_libs);
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||
|
||||
if (not_enabled)
|
||||
{
|
||||
item->setCheckState(Qt::Unchecked);
|
||||
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
|
||||
} else
|
||||
{
|
||||
item->setCheckState(selected ? Qt::Checked : Qt::Unchecked);
|
||||
}
|
||||
|
||||
selected_num += (selected ? 1 : 0);
|
||||
}
|
||||
|
||||
for (const auto& lib: libs)
|
||||
{
|
||||
if (!m_info->libs.contains(lib))
|
||||
{
|
||||
auto* item = new QListWidgetItem(lib, m_ui->listWidget_libs);
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||
item->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
}
|
||||
|
||||
m_ui->listWidget_libs->sortItems();
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::clear()
|
||||
{
|
||||
auto* old_info = m_info;
|
||||
|
||||
m_info = new Kyty::Configuration;
|
||||
Init();
|
||||
delete m_info;
|
||||
|
||||
m_info = old_info;
|
||||
|
||||
scan_elfs();
|
||||
scan_libs();
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::test()
|
||||
{
|
||||
m_ui->test_button->setEnabled(false);
|
||||
|
||||
auto* info = new Kyty::Configuration;
|
||||
|
||||
UpdateInfo(info, m_ui);
|
||||
|
||||
m_parent->GetMainDialog()->RunInterpreter(&m_process, info, false);
|
||||
|
||||
delete info;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "ConfigurationItem.h"
|
||||
|
||||
#include "Configuration.h"
|
||||
|
||||
#include <QFont>
|
||||
#include <QIcon>
|
||||
#include <QSize>
|
||||
|
||||
ConfigurationItem::ConfigurationItem(Kyty::Configuration* info, QListWidget* parent): QListWidgetItem(parent), m_info(info)
|
||||
{
|
||||
setSizeHint(QSize(0, 18));
|
||||
if (m_info != nullptr)
|
||||
{
|
||||
setText(m_info->Name);
|
||||
}
|
||||
SetRunning(false);
|
||||
}
|
||||
|
||||
ConfigurationItem::~ConfigurationItem()
|
||||
{
|
||||
delete m_info;
|
||||
}
|
||||
|
||||
void ConfigurationItem::Update()
|
||||
{
|
||||
if (m_info != nullptr)
|
||||
{
|
||||
setText(m_info->Name);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigurationItem::SetRunning(bool state)
|
||||
{
|
||||
m_running = state;
|
||||
|
||||
QFont f = font();
|
||||
f.setBold(state);
|
||||
setFont(f);
|
||||
|
||||
if (m_running)
|
||||
{
|
||||
setIcon(QIcon(":/running"));
|
||||
} else
|
||||
{
|
||||
setIcon(QIcon(":/application"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
#include "ConfigurationListWidget.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "Configuration.h"
|
||||
#include "ConfigurationEditDialog.h"
|
||||
#include "ConfigurationItem.h"
|
||||
#include "MainDialog.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QAbstractItemView>
|
||||
#include <QAction>
|
||||
#include <QCursor>
|
||||
#include <QDialog>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QIcon>
|
||||
#include <QListWidget>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QSettings>
|
||||
#include <QToolButton>
|
||||
#include <QtCore>
|
||||
|
||||
#include "ui_configuration_list_widget.h"
|
||||
|
||||
constexpr char CONF_FILE_NAME[] = "Kyty.ini";
|
||||
constexpr char CONF_ORG_NAME[] = "Kyty";
|
||||
constexpr char CONF_APP_NAME[] = "Kyty";
|
||||
constexpr char CONF_SECTION_NAME[] = "ConfigurationList";
|
||||
|
||||
ConfigurationListWidget::ConfigurationListWidget(QWidget* parent): QWidget(parent), m_ui(new Ui::ConfigurationListWidget)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->delete_button->setEnabled(false);
|
||||
m_ui->edit_button->setEnabled(false);
|
||||
|
||||
m_ui->cfgs_list->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
connect(m_ui->add_button, &QPushButton::clicked, this, &ConfigurationListWidget::add_configuration);
|
||||
connect(m_ui->edit_button, &QPushButton::clicked, this, &ConfigurationListWidget::edit_configuration);
|
||||
connect(m_ui->delete_button, &QPushButton::clicked, this, &ConfigurationListWidget::delete_configuartion);
|
||||
connect(m_ui->cfgs_list, &QListWidget::itemClicked, this, &ConfigurationListWidget::list_itemClicked);
|
||||
connect(m_ui->cfgs_list, &QListWidget::customContextMenuRequested, this, &ConfigurationListWidget::show_context_menu);
|
||||
|
||||
m_ui->cfgs_list->setDragDropMode(QAbstractItemView::InternalMove);
|
||||
connect(m_ui->cfgs_list->model(), &QAbstractItemModel::rowsMoved, this, &ConfigurationListWidget::WriteSettings);
|
||||
|
||||
ReadSettings();
|
||||
}
|
||||
|
||||
ConfigurationListWidget::~ConfigurationListWidget()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void ConfigurationListWidget::WriteSettings()
|
||||
{
|
||||
QSettings* s = nullptr;
|
||||
QFile file(QDir(".").absoluteFilePath(CONF_FILE_NAME));
|
||||
if (file.exists())
|
||||
{
|
||||
s = new QSettings(CONF_FILE_NAME, QSettings::IniFormat);
|
||||
} else
|
||||
{
|
||||
s = new QSettings(QSettings::IniFormat, QSettings::SystemScope, CONF_ORG_NAME, CONF_APP_NAME);
|
||||
}
|
||||
|
||||
if (s != nullptr)
|
||||
{
|
||||
MainDialog::WriteSettings(s);
|
||||
ConfigurationEditDialog::WriteSettings(s);
|
||||
|
||||
s->remove(CONF_SECTION_NAME);
|
||||
s->beginWriteArray(CONF_SECTION_NAME);
|
||||
for (int i = 0; i < m_ui->cfgs_list->count(); i++)
|
||||
{
|
||||
auto* item = static_cast<ConfigurationItem*>(m_ui->cfgs_list->item(i));
|
||||
s->setArrayIndex(i);
|
||||
item->GetInfo()->WriteSettings(s);
|
||||
}
|
||||
s->endArray();
|
||||
}
|
||||
|
||||
delete s;
|
||||
}
|
||||
|
||||
void ConfigurationListWidget::ReadSettings()
|
||||
{
|
||||
QSettings* s = nullptr;
|
||||
QFile file(QDir(".").absoluteFilePath(CONF_FILE_NAME));
|
||||
if (file.exists())
|
||||
{
|
||||
s = new QSettings(CONF_FILE_NAME, QSettings::IniFormat);
|
||||
} else
|
||||
{
|
||||
s = new QSettings(QSettings::IniFormat, QSettings::SystemScope, CONF_ORG_NAME, CONF_APP_NAME);
|
||||
}
|
||||
|
||||
if (s != nullptr)
|
||||
{
|
||||
m_settings_file = s->fileName();
|
||||
|
||||
MainDialog::ReadSettings(s);
|
||||
ConfigurationEditDialog::ReadSettings(s);
|
||||
|
||||
int size = s->beginReadArray(CONF_SECTION_NAME);
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
s->setArrayIndex(i);
|
||||
auto* info = new Kyty::Configuration;
|
||||
info->ReadSettings(s);
|
||||
new ConfigurationItem(info, m_ui->cfgs_list);
|
||||
}
|
||||
s->endArray();
|
||||
}
|
||||
|
||||
delete s;
|
||||
}
|
||||
|
||||
void ConfigurationListWidget::add_configuration()
|
||||
{
|
||||
auto* info = new Kyty::Configuration;
|
||||
|
||||
ConfigurationEditDialog dlg(info, this);
|
||||
dlg.SetTitle(tr("New configuration"));
|
||||
|
||||
if (dlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
new ConfigurationItem(info, m_ui->cfgs_list);
|
||||
WriteSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigurationListWidget::edit_configuration()
|
||||
{
|
||||
auto* item = static_cast<ConfigurationItem*>(m_ui->cfgs_list->currentItem());
|
||||
|
||||
ConfigurationEditDialog dlg(item->GetInfo(), this);
|
||||
dlg.SetTitle(tr("Edit configuration"));
|
||||
|
||||
if (dlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
WriteSettings();
|
||||
item->Update();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigurationListWidget::delete_configuartion()
|
||||
{
|
||||
if (QMessageBox::Yes == QMessageBox::question(this, tr("Delete configuration"), tr("Do you want to delete configuration?")))
|
||||
{
|
||||
auto* item = static_cast<ConfigurationItem*>(m_ui->cfgs_list->takeItem(m_ui->cfgs_list->currentRow()));
|
||||
delete item;
|
||||
WriteSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigurationListWidget::run_configuration()
|
||||
{
|
||||
emit Run();
|
||||
}
|
||||
|
||||
void ConfigurationListWidget::list_itemClicked(QListWidgetItem* witem)
|
||||
{
|
||||
auto* item = static_cast<ConfigurationItem*>(witem);
|
||||
|
||||
m_ui->delete_button->setEnabled(!item->IsRunning());
|
||||
m_ui->edit_button->setEnabled(!item->IsRunning());
|
||||
|
||||
m_selected_item = item;
|
||||
|
||||
emit Select();
|
||||
}
|
||||
|
||||
void ConfigurationListWidget::show_context_menu(const QPoint& pos)
|
||||
{
|
||||
auto* item = static_cast<ConfigurationItem*>(m_ui->cfgs_list->itemAt(pos));
|
||||
|
||||
if (item != nullptr)
|
||||
{
|
||||
list_itemClicked(item);
|
||||
}
|
||||
|
||||
QMenu menu;
|
||||
|
||||
QAction* action_run = menu.addAction(tr("Run"), this, SLOT(run_configuration()));
|
||||
menu.addSeparator();
|
||||
/*QAction *action_new = */ menu.addAction(QIcon(":/add"), tr("New..."), this, SLOT(add_configuration()));
|
||||
QAction* action_edit = menu.addAction(QIcon(":/edit"), tr("Edit..."), this, SLOT(edit_configuration()));
|
||||
QAction* action_delete = menu.addAction(QIcon(":/delete"), tr("Delete"), this, SLOT(delete_configuartion()));
|
||||
|
||||
if (item != nullptr)
|
||||
{
|
||||
action_run->setDisabled(item->IsRunning());
|
||||
action_edit->setDisabled(item->IsRunning());
|
||||
action_delete->setDisabled(item->IsRunning());
|
||||
} else
|
||||
{
|
||||
action_run->setDisabled(true);
|
||||
action_edit->setDisabled(true);
|
||||
action_delete->setDisabled(true);
|
||||
}
|
||||
|
||||
if (!m_run_enabled)
|
||||
{
|
||||
action_run->setDisabled(true);
|
||||
}
|
||||
|
||||
menu.exec(QCursor::pos());
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#include "MainDialog.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QArgument>
|
||||
#include <QObject>
|
||||
#include <QStyleFactory>
|
||||
|
||||
class QStyle;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
MainDialog w;
|
||||
|
||||
QStyle* s = QStyleFactory::create("fusion");
|
||||
QApplication::setStyle(s);
|
||||
|
||||
QObject::connect(&a, &QApplication::aboutToQuit, &w, &MainDialog::Quit);
|
||||
|
||||
w.emit Start();
|
||||
|
||||
w.show();
|
||||
|
||||
return QApplication::exec();
|
||||
}
|
||||
@@ -0,0 +1,367 @@
|
||||
#include "MainDialog.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "Configuration.h"
|
||||
#include "ConfigurationItem.h"
|
||||
#include "ConfigurationListWidget.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QByteArray>
|
||||
#include <QDialog>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QIODevice>
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
#include <QProcess>
|
||||
#include <QPushButton>
|
||||
#include <QRadioButton>
|
||||
#include <QRegExp>
|
||||
#include <QSettings>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
#include <QVariant>
|
||||
#include <Q_STARTUPINFO>
|
||||
#include <QtCore>
|
||||
|
||||
#include "ui_main_dialog.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// IWYU pragma: no_include <minwindef.h>
|
||||
// IWYU pragma: no_include <processthreadsapi.h>
|
||||
|
||||
class QWidget;
|
||||
|
||||
constexpr char SCRIPT_EXE[] = "fc_script.exe";
|
||||
constexpr char CMD_EXE[] = "cmd.exe";
|
||||
constexpr char CONEMU_EXE[] = "C:/Program Files/ConEmu/ConEmu64.exe";
|
||||
constexpr char KYTY_MOUNT[] = "kyty_mount";
|
||||
constexpr char KYTY_EXECUTE[] = "kyty_execute";
|
||||
constexpr char KYTY_LOAD_ELF[] = "kyty_load_elf";
|
||||
constexpr char KYTY_LOAD_SYMBOLS[] = "kyty_load_symbols";
|
||||
constexpr char KYTY_INIT[] = "kyty_init";
|
||||
constexpr char KYTY_LUA_FILE[] = "kyty_run.lua";
|
||||
constexpr DWORD CMD_X_CHARS = 175;
|
||||
constexpr DWORD CMD_Y_CHARS = 1000;
|
||||
constexpr char SETTINGS_MAIN_DIALOG[] = "MainDialog";
|
||||
constexpr char SETTINGS_MAIN_LAST_GEOMETRY[] = "geometry";
|
||||
|
||||
class DetachableProcess: public QProcess
|
||||
{
|
||||
public:
|
||||
explicit DetachableProcess(QObject* parent = nullptr): QProcess(parent) {}
|
||||
void Detach()
|
||||
{
|
||||
this->waitForStarted();
|
||||
setProcessState(QProcess::NotRunning);
|
||||
}
|
||||
};
|
||||
|
||||
class MainDialogPrivate: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
KYTY_QT_CLASS_NO_COPY(MainDialogPrivate);
|
||||
|
||||
public:
|
||||
MainDialogPrivate() = default;
|
||||
~MainDialogPrivate() override;
|
||||
|
||||
void Setup(MainDialog* main_dialog);
|
||||
|
||||
/*slots:*/
|
||||
|
||||
void Update();
|
||||
void FindInterpreter();
|
||||
void Run();
|
||||
|
||||
[[nodiscard]] const QString& GetInterpreter() const { return m_interpreter; }
|
||||
|
||||
static void WriteSettings(QSettings* s);
|
||||
static void ReadSettings(QSettings* s);
|
||||
|
||||
private:
|
||||
static QByteArray g_last_geometry;
|
||||
|
||||
Ui::MainDialog* m_ui = {nullptr};
|
||||
MainDialog* m_main_dialog = nullptr;
|
||||
QString m_interpreter;
|
||||
DetachableProcess m_process;
|
||||
ConfigurationItem* m_running_item = nullptr;
|
||||
};
|
||||
|
||||
QByteArray MainDialogPrivate::g_last_geometry;
|
||||
|
||||
MainDialog::MainDialog(QWidget* parent): QDialog(parent), m_p(new MainDialogPrivate)
|
||||
{
|
||||
m_p->Setup(this);
|
||||
}
|
||||
|
||||
MainDialogPrivate::~MainDialogPrivate()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void MainDialogPrivate::Setup(MainDialog* main_dialog)
|
||||
{
|
||||
m_ui = new Ui::MainDialog;
|
||||
m_ui->setupUi(main_dialog);
|
||||
|
||||
setParent(main_dialog);
|
||||
m_main_dialog = main_dialog;
|
||||
m_ui->widget->SetMainDialog(main_dialog);
|
||||
|
||||
main_dialog->setWindowFlags(Qt::Dialog /*| Qt::MSWindowsFixedSizeDialogHint*/);
|
||||
|
||||
connect(main_dialog, &MainDialog::Start, this, &MainDialogPrivate::FindInterpreter, Qt::QueuedConnection);
|
||||
connect(m_ui->pushButton_Run, &QPushButton::clicked, this, &MainDialogPrivate::Run);
|
||||
connect(m_ui->widget, &ConfigurationListWidget::Select, this, &MainDialogPrivate::Update);
|
||||
connect(m_ui->widget, &ConfigurationListWidget::Run, this, &MainDialogPrivate::Run);
|
||||
connect(main_dialog, &MainDialog::Resize,
|
||||
[=]()
|
||||
{
|
||||
g_last_geometry = m_main_dialog->saveGeometry();
|
||||
m_ui->widget->WriteSettings();
|
||||
});
|
||||
|
||||
connect(&m_process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||
[=](int /*exitCode*/, QProcess::ExitStatus /*exitStatus*/)
|
||||
{
|
||||
m_running_item->SetRunning(false);
|
||||
Update();
|
||||
});
|
||||
|
||||
connect(main_dialog, &MainDialog::Quit, [=]() { m_process.Detach(); });
|
||||
|
||||
m_ui->label_settings_file->setText(tr("Settings file: ") + m_ui->widget->GetSettingsFile());
|
||||
|
||||
m_main_dialog->restoreGeometry(g_last_geometry);
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
void MainDialogPrivate::FindInterpreter()
|
||||
{
|
||||
QFile file(QDir(".").absoluteFilePath(SCRIPT_EXE));
|
||||
if (file.exists())
|
||||
{
|
||||
m_interpreter = file.fileName();
|
||||
} else
|
||||
{
|
||||
QFile file(QDir("..").absoluteFilePath(SCRIPT_EXE));
|
||||
if (file.exists())
|
||||
{
|
||||
m_interpreter = file.fileName();
|
||||
}
|
||||
}
|
||||
|
||||
bool found = QFile::exists(m_interpreter);
|
||||
|
||||
if (found)
|
||||
{
|
||||
m_ui->label_Interpreter->setText(tr("Emulator: ") + m_interpreter);
|
||||
|
||||
QProcess test;
|
||||
test.setProgram(m_interpreter);
|
||||
test.start();
|
||||
test.waitForFinished();
|
||||
|
||||
auto output = QString(test.readAllStandardOutput());
|
||||
auto lines = output.split(QRegExp("[\r\n]"), Qt::SkipEmptyParts);
|
||||
|
||||
if (lines.count() >= 2)
|
||||
{
|
||||
m_ui->label_Version->setText(tr("Version: ") + (lines.at(0).startsWith("exe_name") ? lines.at(1) : lines.at(0)));
|
||||
} else
|
||||
{
|
||||
found = false;
|
||||
}
|
||||
|
||||
found = found && lines.contains(QString("Lua function: ") + KYTY_MOUNT);
|
||||
found = found && lines.contains(QString("Lua function: ") + KYTY_EXECUTE);
|
||||
found = found && lines.contains(QString("Lua function: ") + KYTY_LOAD_ELF);
|
||||
found = found && lines.contains(QString("Lua function: ") + KYTY_LOAD_SYMBOLS);
|
||||
found = found && lines.contains(QString("Lua function: ") + KYTY_INIT);
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
QMessageBox::critical(m_main_dialog, tr("Error"), tr("Can't find emulator"));
|
||||
QApplication::quit();
|
||||
return;
|
||||
}
|
||||
|
||||
QFile console(CONEMU_EXE);
|
||||
bool con_emu = console.exists();
|
||||
|
||||
m_ui->radioButton_Cmd->setEnabled(true);
|
||||
m_ui->radioButton_Cmd->setChecked(!con_emu);
|
||||
m_ui->radioButton_ConEmu->setEnabled(con_emu);
|
||||
m_ui->radioButton_ConEmu->setChecked(con_emu);
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
static bool CreateLuaScript(Kyty::Configuration* info, const QString& file_name)
|
||||
{
|
||||
QFile file(file_name);
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
{
|
||||
QTextStream s(&file);
|
||||
|
||||
auto r = EnumToText(info->screen_resolution).split('x');
|
||||
|
||||
if (r.size() != 2)
|
||||
{
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
s << "local cfg = {\n";
|
||||
s << "\t ScreenWidth = " << r.at(0) << ";\n";
|
||||
s << "\t ScreenHeight = " << r.at(1) << ";\n";
|
||||
s << "\t Neo = " << (info->neo ? "true" : "false") << ";\n";
|
||||
s << "\t VulkanValidationEnabled = " << (info->vulkan_validation_enabled ? "true" : "false") << ";\n";
|
||||
s << "\t ShaderValidationEnabled = " << (info->shader_validation_enabled ? "true" : "false") << ";\n";
|
||||
s << "\t ShaderOptimizationType = '" << EnumToText(info->shader_optimization_type) << "';\n";
|
||||
s << "\t ShaderLogDirection = '" << EnumToText(info->shader_log_direction) << "';\n";
|
||||
s << "\t ShaderLogFolder = '" << info->shader_log_folder << "';\n";
|
||||
s << "\t CommandBufferDumpEnabled = " << (info->command_buffer_dump_enabled ? "true" : "false") << ";\n";
|
||||
s << "\t CommandBufferDumpFolder = '" << info->command_buffer_dump_folder << "';\n";
|
||||
s << "\t PrintfDirection = '" << EnumToText(info->printf_direction) << "';\n";
|
||||
s << "\t PrintfOutputFile = '" << info->printf_output_file << "';\n";
|
||||
s << "\t ProfilerDirection = '" << EnumToText(info->profiler_direction) << "';\n";
|
||||
s << "\t ProfilerOutputFile = '" << info->profiler_output_file << "';\n";
|
||||
s << "\t SpirvDebugPrintfEnabled = " << (info->spirv_debug_printf_enabled ? "true" : "false") << ";\n";
|
||||
s << "}\n";
|
||||
|
||||
s << KYTY_INIT << "(cfg);\n";
|
||||
s << KYTY_MOUNT << "('" << info->BaseDir << "', '/app0');\n";
|
||||
|
||||
for (const auto& elf: info->elfs_selected)
|
||||
{
|
||||
s << KYTY_LOAD_ELF << "('/app0/" << elf << "');\n";
|
||||
}
|
||||
|
||||
for (const auto& lib: info->libs_selected)
|
||||
{
|
||||
s << KYTY_LOAD_SYMBOLS << "('" << lib << "');\n";
|
||||
}
|
||||
|
||||
s << KYTY_EXECUTE << "();\n";
|
||||
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainDialog::RunInterpreter(QProcess* process, Kyty::Configuration* info, bool con_emu)
|
||||
{
|
||||
const auto& interpreter = m_p->GetInterpreter();
|
||||
|
||||
QFileInfo f(interpreter);
|
||||
auto dir = f.absoluteDir();
|
||||
|
||||
auto lua_file_name = dir.filePath(KYTY_LUA_FILE);
|
||||
|
||||
if (!CreateLuaScript(info, lua_file_name))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Can't create file:\n") + lua_file_name);
|
||||
QApplication::quit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (con_emu)
|
||||
{
|
||||
process->setProgram(CONEMU_EXE);
|
||||
process->setArguments({"-run", /*CMD_EXE, "/K", */ interpreter, lua_file_name});
|
||||
} else
|
||||
{
|
||||
process->setProgram(CMD_EXE);
|
||||
process->setArguments({"/K", interpreter, lua_file_name});
|
||||
}
|
||||
process->setWorkingDirectory(dir.path());
|
||||
process->setCreateProcessArgumentsModifier(
|
||||
[](QProcess::CreateProcessArguments* args)
|
||||
{
|
||||
args->flags |= static_cast<uint32_t>(CREATE_NEW_CONSOLE);
|
||||
args->startupInfo->dwFlags &= ~static_cast<DWORD>(STARTF_USESTDHANDLES);
|
||||
args->startupInfo->dwFlags |= static_cast<DWORD>(STARTF_USECOUNTCHARS);
|
||||
args->startupInfo->dwXCountChars = CMD_X_CHARS;
|
||||
args->startupInfo->dwYCountChars = CMD_Y_CHARS;
|
||||
// args->startupInfo->dwFlags |= static_cast<DWORD>(STARTF_USEFILLATTRIBUTE);
|
||||
// args->startupInfo->dwFillAttribute =
|
||||
// static_cast<DWORD>(BACKGROUND_BLUE) | static_cast<DWORD>(FOREGROUND_RED) | static_cast<DWORD>(FOREGROUND_INTENSITY);
|
||||
});
|
||||
process->start();
|
||||
process->waitForFinished(100);
|
||||
}
|
||||
|
||||
void MainDialog::WriteSettings(QSettings* s)
|
||||
{
|
||||
MainDialogPrivate::WriteSettings(s);
|
||||
}
|
||||
|
||||
void MainDialog::ReadSettings(QSettings* s)
|
||||
{
|
||||
MainDialogPrivate::ReadSettings(s);
|
||||
}
|
||||
|
||||
void MainDialog::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
emit Resize();
|
||||
QDialog::resizeEvent(event);
|
||||
}
|
||||
|
||||
void MainDialogPrivate::WriteSettings(QSettings* s)
|
||||
{
|
||||
s->beginGroup(SETTINGS_MAIN_DIALOG);
|
||||
|
||||
if (!g_last_geometry.isEmpty())
|
||||
{
|
||||
s->setValue(SETTINGS_MAIN_LAST_GEOMETRY, g_last_geometry);
|
||||
}
|
||||
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
void MainDialogPrivate::ReadSettings(QSettings* s)
|
||||
{
|
||||
s->beginGroup(SETTINGS_MAIN_DIALOG);
|
||||
|
||||
g_last_geometry = s->value(SETTINGS_MAIN_LAST_GEOMETRY, g_last_geometry).toByteArray();
|
||||
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
void MainDialogPrivate::Run()
|
||||
{
|
||||
m_running_item = m_ui->widget->GetSelectedItem();
|
||||
|
||||
m_running_item->SetRunning(true);
|
||||
|
||||
m_main_dialog->RunInterpreter(&m_process, m_running_item->GetInfo(), m_ui->radioButton_ConEmu->isChecked());
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
void MainDialogPrivate::Update()
|
||||
{
|
||||
const auto* item = m_ui->widget->GetSelectedItem();
|
||||
|
||||
bool run_enabled = (m_process.state() == QProcess::NotRunning && item != nullptr);
|
||||
|
||||
if (run_enabled && item != nullptr)
|
||||
{
|
||||
const auto* info = item->GetInfo();
|
||||
auto dir = info->BaseDir;
|
||||
run_enabled = !dir.isEmpty() && QDir(dir).exists();
|
||||
}
|
||||
|
||||
m_ui->pushButton_Run->setEnabled(run_enabled);
|
||||
m_ui->widget->SetRunEnabled(run_enabled);
|
||||
}
|
||||
|
||||
#include "MainDialog.moc"
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "MandatoryLineEdit.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QLine>
|
||||
#include <QPainter>
|
||||
#include <QPen>
|
||||
#include <QVariant>
|
||||
#include <QtCore>
|
||||
|
||||
class QPaintEvent;
|
||||
class QWidget;
|
||||
|
||||
MandatoryLineEdit::MandatoryLineEdit(QWidget* parent): QLineEdit(parent)
|
||||
{
|
||||
this->setProperty(MANDATORY_AND_EMPTY, true);
|
||||
|
||||
connect(this, &QLineEdit::textChanged, this, &MandatoryLineEdit::changed);
|
||||
}
|
||||
|
||||
void MandatoryLineEdit::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
QLineEdit::paintEvent(event);
|
||||
|
||||
if (this->property(MANDATORY_AND_EMPTY).toBool() && this->isEnabled())
|
||||
{
|
||||
QPainter painter(this);
|
||||
QLine line(4, this->height() - 4, this->width() - 4, this->height() - 4);
|
||||
painter.setPen(QPen(QColor(255, 0, 0), 1.0, Qt::DotLine));
|
||||
painter.drawLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
bool MandatoryLineEdit::FindEmpty(QObject* p)
|
||||
{
|
||||
const QList<QLineEdit*>& ch_list = p->findChildren<QLineEdit*>();
|
||||
|
||||
foreach (QLineEdit* ch, ch_list)
|
||||
{
|
||||
if (ch->isVisible() && ch->property(MANDATORY_AND_EMPTY).toBool() && ch->isEnabled())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MandatoryLineEdit::changed(const QString& text)
|
||||
{
|
||||
this->setProperty(MANDATORY_AND_EMPTY, text.isEmpty());
|
||||
}
|
||||
Reference in New Issue
Block a user