mirror of
https://github.com/izzy2lost/xenia-edge.git
synced 2026-07-06 00:20:26 -07:00
[UI] Fix bad UTF8 related crashes in Qt string processing
This commit is contained in:
@@ -39,6 +39,7 @@
|
||||
#include "xenia/ui/notification_widget_qt.h"
|
||||
#include "xenia/ui/postprocessing_dialog_qt.h"
|
||||
#include "xenia/ui/profile_dialog_qt.h"
|
||||
#include "xenia/ui/qt_util.h"
|
||||
#include "xenia/ui/xmp_dialog_qt.h"
|
||||
|
||||
#if XE_PLATFORM_WIN32
|
||||
@@ -219,6 +220,7 @@ namespace app {
|
||||
using xe::ui::FileDropEvent;
|
||||
using xe::ui::KeyEvent;
|
||||
using xe::ui::MenuItem;
|
||||
using xe::ui::SafeQString;
|
||||
using xe::ui::UIEvent;
|
||||
|
||||
using namespace xe::hid;
|
||||
@@ -1113,9 +1115,9 @@ void EmulatorWindow::ExportScreenshot(const xe::ui::RawImage& image) {
|
||||
app_context_.CallInUIThread([this, notification_text]() {
|
||||
auto* qt_window = dynamic_cast<ui::QtWindow*>(window_.get());
|
||||
if (qt_window) {
|
||||
auto* notification = new NotificationWidgetQt(
|
||||
qt_window->qwindow(), "Screenshot Created!",
|
||||
QString::fromStdString(notification_text), 3000);
|
||||
auto* notification =
|
||||
new NotificationWidgetQt(qt_window->qwindow(), "Screenshot Created!",
|
||||
SafeQString(notification_text), 3000);
|
||||
notification->Show();
|
||||
}
|
||||
});
|
||||
@@ -2151,7 +2153,7 @@ void EmulatorWindow::DisplayHotKeysConfig() {
|
||||
// Show Qt message box
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle("Controller Hotkeys");
|
||||
msgBox.setText(QString::fromStdString(msg));
|
||||
msgBox.setText(SafeQString(msg));
|
||||
msgBox.setIcon(QMessageBox::Information);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.exec();
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "xenia/kernel/xam/achievement_manager.h"
|
||||
#include "xenia/kernel/xam/profile_manager.h"
|
||||
#include "xenia/kernel/xam/xam_state.h"
|
||||
#include "xenia/ui/qt_util.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
@@ -45,6 +46,8 @@ struct Achievement;
|
||||
namespace xe {
|
||||
namespace ui {
|
||||
|
||||
using xe::ui::SafeQString;
|
||||
|
||||
AchievementsDialogQt::AchievementsDialogQt(
|
||||
QWidget* parent, kernel::KernelState* kernel_state,
|
||||
const kernel::xam::TitleInfo* title_info,
|
||||
@@ -401,7 +404,7 @@ QString AchievementsDialogQt::GetAchievementTitle(
|
||||
if (!title.empty() && title.back() == '\0') {
|
||||
title.pop_back();
|
||||
}
|
||||
return QString::fromStdString(title);
|
||||
return SafeQString(title);
|
||||
}
|
||||
|
||||
QString AchievementsDialogQt::GetAchievementDescription(
|
||||
@@ -415,7 +418,7 @@ QString AchievementsDialogQt::GetAchievementDescription(
|
||||
if (!desc.empty() && desc.back() == '\0') {
|
||||
desc.pop_back();
|
||||
}
|
||||
return QString::fromStdString(desc);
|
||||
return SafeQString(desc);
|
||||
} else {
|
||||
// Hide description when checkbox is not checked
|
||||
return QString();
|
||||
@@ -428,7 +431,7 @@ QString AchievementsDialogQt::GetAchievementDescription(
|
||||
if (!desc.empty() && desc.back() == '\0') {
|
||||
desc.pop_back();
|
||||
}
|
||||
return QString::fromStdString(desc);
|
||||
return SafeQString(desc);
|
||||
}
|
||||
|
||||
QString AchievementsDialogQt::GetUnlockedTime(
|
||||
@@ -442,7 +445,7 @@ QString AchievementsDialogQt::GetUnlockedTime(
|
||||
chrono::WinSystemClock::to_sys(achievement.unlock_time.to_time_point());
|
||||
auto unlock_time = std::chrono::system_clock::to_time_t(unlock_tp);
|
||||
|
||||
return QString::fromStdString(
|
||||
return SafeQString(
|
||||
fmt::format("{:%Y-%m-%d %H:%M}", fmt::localtime(unlock_time)));
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/config.h"
|
||||
#include "xenia/ui/config_helpers.h"
|
||||
#include "xenia/ui/qt_util.h"
|
||||
|
||||
#if XE_PLATFORM_LINUX
|
||||
#include <unistd.h>
|
||||
@@ -40,6 +41,8 @@ namespace {
|
||||
|
||||
// Use the shared enum options from config_helpers.h
|
||||
using xe::ui::GetKnownEnumOptions;
|
||||
using xe::ui::SafeQString;
|
||||
using xe::ui::SafeStdString;
|
||||
|
||||
#if XE_PLATFORM_LINUX
|
||||
// Check if a command exists in PATH by searching each directory
|
||||
@@ -178,7 +181,7 @@ void ConfigDialogQt::SetupUI() {
|
||||
|
||||
// Add categories in order
|
||||
for (const auto& category_name : category_order_) {
|
||||
category_list_->addItem(QString::fromStdString(category_name));
|
||||
category_list_->addItem(SafeQString(category_name));
|
||||
auto it = categories_.find(category_name);
|
||||
if (it != categories_.end()) {
|
||||
CreateCategoryPage(category_name, it->second);
|
||||
@@ -227,14 +230,13 @@ void ConfigDialogQt::CreateCategoryPage(
|
||||
|
||||
for (auto* var_info : vars) {
|
||||
// Create label with tooltip - left aligned
|
||||
auto* label = new QLabel(QString::fromStdString(var_info->name));
|
||||
auto* label = new QLabel(SafeQString(var_info->name));
|
||||
label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
if (!var_info->description.empty()) {
|
||||
// Format tooltip with rich text to enable word wrapping
|
||||
QString tooltip =
|
||||
QString("<p style='white-space: pre-wrap; max-width: 400px;'>%1</p>")
|
||||
.arg(QString::fromStdString(var_info->description)
|
||||
.toHtmlEscaped());
|
||||
.arg(SafeQString(var_info->description).toHtmlEscaped());
|
||||
label->setToolTip(tooltip);
|
||||
label->setToolTipDuration(5000); // Show for 5 seconds
|
||||
}
|
||||
@@ -297,7 +299,7 @@ QWidget* ConfigDialogQt::CreateEditorWidget(ConfigVarInfo* var_info) {
|
||||
|
||||
int current_index = -1;
|
||||
for (size_t i = 0; i < options.size(); ++i) {
|
||||
combo->addItem(QString::fromStdString(options[i]));
|
||||
combo->addItem(SafeQString(options[i]));
|
||||
if (options[i] == var_info->pending_value) {
|
||||
current_index = static_cast<int>(i);
|
||||
}
|
||||
@@ -318,22 +320,21 @@ QWidget* ConfigDialogQt::CreateEditorWidget(ConfigVarInfo* var_info) {
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
auto* line_edit = new QLineEdit();
|
||||
line_edit->setText(QString::fromStdString(var_info->pending_value));
|
||||
line_edit->setText(SafeQString(var_info->pending_value));
|
||||
connect(line_edit, &QLineEdit::textChanged, this,
|
||||
&ConfigDialogQt::OnValueChanged);
|
||||
layout->addWidget(line_edit);
|
||||
|
||||
auto* browse_button = new QPushButton("Browse...");
|
||||
connect(
|
||||
browse_button, &QPushButton::clicked, [this, line_edit, var_info]() {
|
||||
QString path = QFileDialog::getExistingDirectory(
|
||||
this,
|
||||
QString::fromStdString("Select Directory for " + var_info->name),
|
||||
line_edit->text());
|
||||
if (!path.isEmpty()) {
|
||||
line_edit->setText(path);
|
||||
}
|
||||
});
|
||||
connect(browse_button, &QPushButton::clicked,
|
||||
[this, line_edit, var_info]() {
|
||||
QString path = QFileDialog::getExistingDirectory(
|
||||
this, SafeQString("Select Directory for " + var_info->name),
|
||||
line_edit->text());
|
||||
if (!path.isEmpty()) {
|
||||
line_edit->setText(path);
|
||||
}
|
||||
});
|
||||
layout->addWidget(browse_button);
|
||||
|
||||
return container;
|
||||
@@ -358,7 +359,7 @@ QWidget* ConfigDialogQt::CreateEditorWidget(ConfigVarInfo* var_info) {
|
||||
} else {
|
||||
// Text input for all other types (string, double, etc.)
|
||||
auto* line_edit = new QLineEdit();
|
||||
line_edit->setText(QString::fromStdString(var_info->pending_value));
|
||||
line_edit->setText(SafeQString(var_info->pending_value));
|
||||
connect(line_edit, &QLineEdit::textChanged, this,
|
||||
&ConfigDialogQt::OnValueChanged);
|
||||
return line_edit;
|
||||
@@ -370,16 +371,16 @@ std::string ConfigDialogQt::GetEditorValue(QWidget* editor,
|
||||
if (auto* checkbox = qobject_cast<QCheckBox*>(editor)) {
|
||||
return checkbox->isChecked() ? "true" : "false";
|
||||
} else if (auto* combo = qobject_cast<QComboBox*>(editor)) {
|
||||
return combo->currentText().toStdString();
|
||||
return SafeStdString(combo->currentText());
|
||||
} else if (auto* spinbox = qobject_cast<QSpinBox*>(editor)) {
|
||||
return std::to_string(spinbox->value());
|
||||
} else if (auto* line_edit = qobject_cast<QLineEdit*>(editor)) {
|
||||
return line_edit->text().toStdString();
|
||||
return SafeStdString(line_edit->text());
|
||||
} else if (auto* container = qobject_cast<QWidget*>(editor)) {
|
||||
// For path containers, find the QLineEdit child
|
||||
auto* line_edit = container->findChild<QLineEdit*>();
|
||||
if (line_edit) {
|
||||
return line_edit->text().toStdString();
|
||||
return SafeStdString(line_edit->text());
|
||||
}
|
||||
}
|
||||
return "";
|
||||
@@ -548,7 +549,7 @@ void ConfigDialogQt::ResetToDefaults() {
|
||||
checkbox->setChecked(default_value == "true");
|
||||
} else if (auto* combo =
|
||||
qobject_cast<QComboBox*>(var_info.editor_widget)) {
|
||||
int index = combo->findText(QString::fromStdString(default_value));
|
||||
int index = combo->findText(SafeQString(default_value));
|
||||
if (index >= 0) {
|
||||
combo->setCurrentIndex(index);
|
||||
}
|
||||
@@ -561,12 +562,12 @@ void ConfigDialogQt::ResetToDefaults() {
|
||||
}
|
||||
} else if (auto* line_edit =
|
||||
qobject_cast<QLineEdit*>(var_info.editor_widget)) {
|
||||
line_edit->setText(QString::fromStdString(default_value));
|
||||
line_edit->setText(SafeQString(default_value));
|
||||
} else if (auto* container =
|
||||
qobject_cast<QWidget*>(var_info.editor_widget)) {
|
||||
auto* line_edit = container->findChild<QLineEdit*>();
|
||||
if (line_edit) {
|
||||
line_edit->setText(QString::fromStdString(default_value));
|
||||
line_edit->setText(SafeQString(default_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -655,8 +656,7 @@ void ConfigDialogQt::OnDiscardClicked() {
|
||||
checkbox->setChecked(var_info.current_value == "true");
|
||||
} else if (auto* combo =
|
||||
qobject_cast<QComboBox*>(var_info.editor_widget)) {
|
||||
int index =
|
||||
combo->findText(QString::fromStdString(var_info.current_value));
|
||||
int index = combo->findText(SafeQString(var_info.current_value));
|
||||
if (index >= 0) {
|
||||
combo->setCurrentIndex(index);
|
||||
}
|
||||
@@ -669,13 +669,12 @@ void ConfigDialogQt::OnDiscardClicked() {
|
||||
}
|
||||
} else if (auto* line_edit =
|
||||
qobject_cast<QLineEdit*>(var_info.editor_widget)) {
|
||||
line_edit->setText(QString::fromStdString(var_info.current_value));
|
||||
line_edit->setText(SafeQString(var_info.current_value));
|
||||
} else if (auto* container =
|
||||
qobject_cast<QWidget*>(var_info.editor_widget)) {
|
||||
auto* line_edit = container->findChild<QLineEdit*>();
|
||||
if (line_edit) {
|
||||
line_edit->setText(
|
||||
QString::fromStdString(var_info.current_value));
|
||||
line_edit->setText(SafeQString(var_info.current_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,11 +21,14 @@
|
||||
|
||||
#include "third_party/fmt/include/fmt/format.h"
|
||||
#include "xenia/base/system.h"
|
||||
#include "xenia/ui/qt_util.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace ui {
|
||||
|
||||
using xe::ui::SafeQString;
|
||||
|
||||
ContentInstallDialogQt::ContentInstallDialogQt(
|
||||
QWidget* parent, const std::filesystem::path& content_root,
|
||||
std::shared_ptr<std::vector<Emulator::ContentInstallEntry>> entries)
|
||||
@@ -199,11 +202,11 @@ void ContentInstallDialogQt::UpdateProgress() {
|
||||
|
||||
// Update name
|
||||
widgets.name_label->setText(
|
||||
QString("Name: %1").arg(QString::fromStdString(entry.name_)));
|
||||
QString("Name: %1").arg(SafeQString(entry.name_)));
|
||||
|
||||
// Update path with link
|
||||
QString path_str =
|
||||
QString::fromStdString(xe::path_to_utf8(entry.data_installation_path_));
|
||||
SafeQString(xe::path_to_utf8(entry.data_installation_path_));
|
||||
widgets.path_label->setText(
|
||||
QString("Installation Path: <a href=\"%1\">%1</a>").arg(path_str));
|
||||
|
||||
@@ -212,8 +215,7 @@ void ContentInstallDialogQt::UpdateProgress() {
|
||||
auto it = XContentTypeMap.find(entry.content_type_);
|
||||
if (it != XContentTypeMap.end()) {
|
||||
widgets.type_label->setText(
|
||||
QString("Content Type: %1")
|
||||
.arg(QString::fromStdString(it->second)));
|
||||
QString("Content Type: %1").arg(SafeQString(it->second)));
|
||||
}
|
||||
} else {
|
||||
widgets.type_label->setText("");
|
||||
@@ -230,7 +232,7 @@ void ContentInstallDialogQt::UpdateProgress() {
|
||||
entry.installation_result_);
|
||||
}
|
||||
|
||||
widgets.status_label->setText(QString::fromStdString(result));
|
||||
widgets.status_label->setText(SafeQString(result));
|
||||
|
||||
// Update progress bar
|
||||
if (entry.content_size_ > 0) {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "xenia/base/filesystem.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/string.h"
|
||||
#include "xenia/ui/qt_util.h"
|
||||
#include "xenia/ui/window_qt.h"
|
||||
|
||||
#if XE_PLATFORM_WIN32
|
||||
@@ -27,6 +28,8 @@
|
||||
namespace xe {
|
||||
namespace ui {
|
||||
|
||||
using xe::ui::SafeQString;
|
||||
|
||||
#if XE_PLATFORM_WIN32
|
||||
// Detect if running under Wine by checking for wine_get_version in ntdll
|
||||
static bool IsRunningOnWine() {
|
||||
@@ -85,7 +88,7 @@ bool QtFilePicker::Show(Window* parent_window) {
|
||||
}
|
||||
|
||||
// Use the custom title set via set_title(), or default based on mode
|
||||
QString title = QString::fromStdString(this->title());
|
||||
QString title = SafeQString(this->title());
|
||||
|
||||
auto* qt_window =
|
||||
parent_window ? dynamic_cast<QtWindow*>(parent_window) : nullptr;
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/config.h"
|
||||
#include "xenia/ui/config_helpers.h"
|
||||
#include "xenia/ui/qt_util.h"
|
||||
|
||||
namespace xe {
|
||||
namespace app {
|
||||
@@ -44,6 +45,8 @@ namespace {
|
||||
|
||||
// Use the shared enum options from config_helpers.h
|
||||
using xe::ui::GetKnownEnumOptions;
|
||||
using xe::ui::SafeQString;
|
||||
using xe::ui::SafeStdString;
|
||||
|
||||
// Helper to convert a RapidJSON value to string
|
||||
std::string JsonValueToString(const rapidjson::Value& value) {
|
||||
@@ -114,8 +117,8 @@ GameConfigDialogQt::GameConfigDialogQt(QWidget* parent,
|
||||
GameConfigDialogQt::~GameConfigDialogQt() = default;
|
||||
|
||||
void GameConfigDialogQt::SetupUI() {
|
||||
setWindowTitle(QString::fromStdString(
|
||||
fmt::format("Game Config Overrides - {}", game_title_)));
|
||||
setWindowTitle(
|
||||
SafeQString(fmt::format("Game Config Overrides - {}", game_title_)));
|
||||
setMinimumSize(800, 500);
|
||||
resize(900, 600);
|
||||
|
||||
@@ -253,8 +256,7 @@ void GameConfigDialogQt::LoadConfigOverrides() {
|
||||
overrides_table_->insertRow(row);
|
||||
|
||||
// Column 0: Variable name (non-editable text)
|
||||
auto* name_item =
|
||||
new QTableWidgetItem(QString::fromStdString(var_name));
|
||||
auto* name_item = new QTableWidgetItem(SafeQString(var_name));
|
||||
name_item->setFlags(name_item->flags() & ~Qt::ItemIsEditable);
|
||||
overrides_table_->setItem(row, 0, name_item);
|
||||
|
||||
@@ -276,9 +278,9 @@ void GameConfigDialogQt::LoadConfigOverrides() {
|
||||
} catch (const std::exception& e) {
|
||||
XELOGE("Failed to load game config {}: {}", xe::path_to_utf8(config_path),
|
||||
e.what());
|
||||
QMessageBox::warning(this, "Error Loading Config",
|
||||
QString::fromStdString(fmt::format(
|
||||
"Failed to load game config: {}", e.what())));
|
||||
QMessageBox::warning(
|
||||
this, "Error Loading Config",
|
||||
SafeQString(fmt::format("Failed to load game config: {}", e.what())));
|
||||
}
|
||||
|
||||
has_unsaved_changes_ = false;
|
||||
@@ -303,7 +305,7 @@ void GameConfigDialogQt::SaveConfigOverrides() {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string var_name = var_item->text().toStdString();
|
||||
std::string var_name = SafeStdString(var_item->text());
|
||||
|
||||
// Get value from the cell widget, not from a text item
|
||||
QWidget* value_widget = overrides_table_->cellWidget(row, 1);
|
||||
@@ -391,9 +393,9 @@ void GameConfigDialogQt::SaveConfigOverrides() {
|
||||
} catch (const std::exception& e) {
|
||||
XELOGE("Failed to save game config {}: {}", xe::path_to_utf8(config_path),
|
||||
e.what());
|
||||
QMessageBox::critical(this, "Error Saving Config",
|
||||
QString::fromStdString(fmt::format(
|
||||
"Failed to save game config: {}", e.what())));
|
||||
QMessageBox::critical(
|
||||
this, "Error Saving Config",
|
||||
SafeQString(fmt::format("Failed to save game config: {}", e.what())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,7 +414,7 @@ QWidget* GameConfigDialogQt::CreateEditorForCvar(
|
||||
auto* combo = new QComboBox();
|
||||
combo->addItem("true");
|
||||
combo->addItem("false");
|
||||
combo->setCurrentText(QString::fromStdString(current_value));
|
||||
combo->setCurrentText(SafeQString(current_value));
|
||||
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
[this, combo]() {
|
||||
has_unsaved_changes_ = true;
|
||||
@@ -432,7 +434,7 @@ QWidget* GameConfigDialogQt::CreateEditorForCvar(
|
||||
|
||||
int current_index = -1;
|
||||
for (size_t i = 0; i < options.size(); ++i) {
|
||||
combo->addItem(QString::fromStdString(options[i]));
|
||||
combo->addItem(SafeQString(options[i]));
|
||||
if (options[i] == current_value) {
|
||||
current_index = static_cast<int>(i);
|
||||
}
|
||||
@@ -461,7 +463,7 @@ QWidget* GameConfigDialogQt::CreateEditorForCvar(
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
auto* line_edit = new QLineEdit();
|
||||
line_edit->setText(QString::fromStdString(current_value));
|
||||
line_edit->setText(SafeQString(current_value));
|
||||
connect(line_edit, &QLineEdit::textChanged, [this, container]() {
|
||||
has_unsaved_changes_ = true;
|
||||
// Find which row this widget belongs to and update its bold state
|
||||
@@ -477,7 +479,7 @@ QWidget* GameConfigDialogQt::CreateEditorForCvar(
|
||||
auto* browse_button = new QPushButton("Browse...");
|
||||
connect(browse_button, &QPushButton::clicked, [this, line_edit, var]() {
|
||||
QString path = QFileDialog::getExistingDirectory(
|
||||
this, QString::fromStdString("Select Directory for " + var->name()),
|
||||
this, SafeQString("Select Directory for " + var->name()),
|
||||
line_edit->text());
|
||||
if (!path.isEmpty()) {
|
||||
line_edit->setText(path);
|
||||
@@ -515,7 +517,7 @@ QWidget* GameConfigDialogQt::CreateEditorForCvar(
|
||||
} else {
|
||||
// Text input for all other types (string, double, etc.)
|
||||
auto* line_edit = new QLineEdit();
|
||||
line_edit->setText(QString::fromStdString(current_value));
|
||||
line_edit->setText(SafeQString(current_value));
|
||||
connect(line_edit, &QLineEdit::textChanged, [this, line_edit]() {
|
||||
has_unsaved_changes_ = true;
|
||||
// Find which row this widget belongs to and update its bold state
|
||||
@@ -532,16 +534,16 @@ QWidget* GameConfigDialogQt::CreateEditorForCvar(
|
||||
|
||||
std::string GameConfigDialogQt::GetEditorValue(QWidget* editor) {
|
||||
if (auto* combo = qobject_cast<QComboBox*>(editor)) {
|
||||
return combo->currentText().toStdString();
|
||||
return SafeStdString(combo->currentText());
|
||||
} else if (auto* spinbox = qobject_cast<QSpinBox*>(editor)) {
|
||||
return std::to_string(spinbox->value());
|
||||
} else if (auto* line_edit = qobject_cast<QLineEdit*>(editor)) {
|
||||
return line_edit->text().toStdString();
|
||||
return SafeStdString(line_edit->text());
|
||||
} else if (auto* container = qobject_cast<QWidget*>(editor)) {
|
||||
// For path containers, find the QLineEdit child
|
||||
auto* line_edit = container->findChild<QLineEdit*>();
|
||||
if (line_edit) {
|
||||
return line_edit->text().toStdString();
|
||||
return SafeStdString(line_edit->text());
|
||||
}
|
||||
}
|
||||
return "";
|
||||
@@ -553,7 +555,7 @@ void GameConfigDialogQt::UpdateRowModifiedState(int row) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string var_name = name_item->text().toStdString();
|
||||
std::string var_name = SafeStdString(name_item->text());
|
||||
QWidget* value_widget = overrides_table_->cellWidget(row, 1);
|
||||
if (!value_widget) {
|
||||
return;
|
||||
@@ -599,8 +601,8 @@ void GameConfigDialogQt::OnAddOverrideClicked() {
|
||||
for (const auto& name : cvar_names) {
|
||||
auto* var = (*cvar::ConfigVars)[name];
|
||||
QString item_text =
|
||||
QString::fromStdString(fmt::format("{} ({})", name, var->category()));
|
||||
combo->addItem(item_text, QString::fromStdString(name));
|
||||
SafeQString(fmt::format("{} ({})", name, var->category()));
|
||||
combo->addItem(item_text, SafeQString(name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -632,7 +634,7 @@ void GameConfigDialogQt::OnAddOverrideClicked() {
|
||||
return;
|
||||
}
|
||||
|
||||
selected_var = (*cvar::ConfigVars)[var_name.toStdString()];
|
||||
selected_var = (*cvar::ConfigVars)[SafeStdString(var_name)];
|
||||
if (!selected_var) {
|
||||
return;
|
||||
}
|
||||
@@ -678,7 +680,7 @@ void GameConfigDialogQt::OnAddOverrideClicked() {
|
||||
QString value;
|
||||
|
||||
if (current_editor) {
|
||||
value = QString::fromStdString(GetEditorValue(current_editor));
|
||||
value = SafeQString(GetEditorValue(current_editor));
|
||||
}
|
||||
|
||||
if (var_name.isEmpty()) {
|
||||
@@ -710,7 +712,7 @@ void GameConfigDialogQt::OnAddOverrideClicked() {
|
||||
// We need to create a new one since the dialog's editor will be destroyed
|
||||
if (selected_var) {
|
||||
QWidget* value_editor =
|
||||
CreateEditorForCvar(selected_var, value.toStdString());
|
||||
CreateEditorForCvar(selected_var, SafeStdString(value));
|
||||
overrides_table_->setCellWidget(row, 1, value_editor);
|
||||
}
|
||||
|
||||
@@ -784,7 +786,7 @@ void GameConfigDialogQt::LoadRecommendedSettings() {
|
||||
if (!parse_result) {
|
||||
QMessageBox::warning(
|
||||
this, "Error Parsing Settings",
|
||||
QString::fromStdString(
|
||||
SafeQString(
|
||||
fmt::format("Failed to parse recommended settings: {} at offset {}",
|
||||
rapidjson::GetParseError_En(parse_result.Code()),
|
||||
parse_result.Offset())));
|
||||
@@ -827,7 +829,7 @@ void GameConfigDialogQt::LoadRecommendedSettings() {
|
||||
has_unsaved_changes_ = true;
|
||||
QMessageBox::information(
|
||||
this, "Settings Loaded",
|
||||
QString::fromStdString(
|
||||
SafeQString(
|
||||
fmt::format("Loaded {} recommended setting{} for this game.\n\n"
|
||||
"Don't forget to save your changes!",
|
||||
settings_applied, settings_applied == 1 ? "" : "s")));
|
||||
@@ -855,13 +857,13 @@ bool GameConfigDialogQt::ApplyRecommendedSetting(const std::string& var_name,
|
||||
// Check if this setting is already in the table
|
||||
for (int row = 0; row < overrides_table_->rowCount(); ++row) {
|
||||
auto* item = overrides_table_->item(row, 0);
|
||||
if (item && item->text().toStdString() == var_name) {
|
||||
if (item && SafeStdString(item->text()) == var_name) {
|
||||
// Update the existing entry
|
||||
QWidget* value_widget = overrides_table_->cellWidget(row, 1);
|
||||
if (value_widget) {
|
||||
// Update the widget with the new value
|
||||
if (auto* combo = qobject_cast<QComboBox*>(value_widget)) {
|
||||
int index = combo->findText(QString::fromStdString(value));
|
||||
int index = combo->findText(SafeQString(value));
|
||||
if (index >= 0) {
|
||||
combo->setCurrentIndex(index);
|
||||
}
|
||||
@@ -872,12 +874,12 @@ bool GameConfigDialogQt::ApplyRecommendedSetting(const std::string& var_name,
|
||||
XELOGW("Failed to parse integer value for {}: {}", var_name, value);
|
||||
}
|
||||
} else if (auto* line_edit = qobject_cast<QLineEdit*>(value_widget)) {
|
||||
line_edit->setText(QString::fromStdString(value));
|
||||
line_edit->setText(SafeQString(value));
|
||||
} else if (auto* container = qobject_cast<QWidget*>(value_widget)) {
|
||||
// For path containers, find the QLineEdit child
|
||||
auto* line_edit = container->findChild<QLineEdit*>();
|
||||
if (line_edit) {
|
||||
line_edit->setText(QString::fromStdString(value));
|
||||
line_edit->setText(SafeQString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -890,7 +892,7 @@ bool GameConfigDialogQt::ApplyRecommendedSetting(const std::string& var_name,
|
||||
overrides_table_->insertRow(row);
|
||||
|
||||
// Column 0: Variable name (non-editable text)
|
||||
auto* name_item = new QTableWidgetItem(QString::fromStdString(var_name));
|
||||
auto* name_item = new QTableWidgetItem(SafeQString(var_name));
|
||||
name_item->setFlags(name_item->flags() & ~Qt::ItemIsEditable);
|
||||
overrides_table_->setItem(row, 0, name_item);
|
||||
|
||||
|
||||
@@ -48,10 +48,14 @@
|
||||
#include "xenia/ui/game_config_dialog_qt.h"
|
||||
#include "xenia/ui/profile_dialog_qt.h"
|
||||
#include "xenia/ui/profile_editor_dialog_qt.h"
|
||||
#include "xenia/ui/qt_util.h"
|
||||
|
||||
namespace xe {
|
||||
namespace app {
|
||||
|
||||
using xe::ui::SafeQString;
|
||||
using xe::ui::SafeStdString;
|
||||
|
||||
GameListDialogQt::GameListDialogQt(QWidget* parent,
|
||||
EmulatorWindow* emulator_window)
|
||||
: QWidget(parent), emulator_window_(emulator_window) {
|
||||
@@ -597,9 +601,8 @@ void GameListDialogQt::PopulateTable() {
|
||||
|
||||
// Apply filter
|
||||
if (!filter_text.isEmpty()) {
|
||||
QString title = QString::fromStdString(entry.title_name).toLower();
|
||||
QString path =
|
||||
QString::fromStdString(entry.path_to_file.string()).toLower();
|
||||
QString title = SafeQString(entry.title_name).toLower();
|
||||
QString path = SafeQString(entry.path_to_file.string()).toLower();
|
||||
|
||||
if (!title.contains(filter_text) && !path.contains(filter_text)) {
|
||||
continue;
|
||||
@@ -661,9 +664,20 @@ void GameListDialogQt::PopulateTable() {
|
||||
bool file_corrupted = entry.title_name.empty();
|
||||
|
||||
// Title - large font
|
||||
QString display_title = file_corrupted
|
||||
? QString("File Corrupted")
|
||||
: QString::fromStdString(entry.title_name);
|
||||
QString display_title;
|
||||
if (file_corrupted) {
|
||||
display_title = QString("File Corrupted");
|
||||
} else {
|
||||
// Use fromUtf8 with error handling for potentially invalid data
|
||||
display_title =
|
||||
QString::fromUtf8(entry.title_name.c_str(),
|
||||
static_cast<qsizetype>(entry.title_name.size()));
|
||||
// If conversion failed or resulted in empty string, mark as corrupted
|
||||
if (display_title.isEmpty()) {
|
||||
display_title = QString("File Corrupted");
|
||||
file_corrupted = true;
|
||||
}
|
||||
}
|
||||
auto* title_label = new QLabel(display_title);
|
||||
title_label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
|
||||
title_label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
@@ -678,8 +692,7 @@ void GameListDialogQt::PopulateTable() {
|
||||
|
||||
// Path - smaller font (only show if path is available)
|
||||
if (!entry.path_to_file.empty()) {
|
||||
auto* path_label =
|
||||
new QLabel(QString::fromStdString(entry.path_to_file.string()));
|
||||
auto* path_label = new QLabel(SafeQString(entry.path_to_file.string()));
|
||||
path_label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
|
||||
path_label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
QFont path_font = path_label->font();
|
||||
@@ -721,8 +734,8 @@ void GameListDialogQt::PopulateTable() {
|
||||
row_layout->addWidget(title_container, 1); // Stretch factor
|
||||
|
||||
// Last played
|
||||
auto* last_played_label = new QLabel(
|
||||
QString::fromStdString(FormatLastPlayed(entry.last_run_time)));
|
||||
auto* last_played_label =
|
||||
new QLabel(SafeQString(FormatLastPlayed(entry.last_run_time)));
|
||||
last_played_label->setAlignment(Qt::AlignVCenter | Qt::AlignRight);
|
||||
last_played_label->setMinimumWidth(200);
|
||||
last_played_label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
@@ -734,7 +747,7 @@ void GameListDialogQt::PopulateTable() {
|
||||
// Store the path and title_id in the row for later retrieval
|
||||
table_widget_->setItem(row, 0, new QTableWidgetItem());
|
||||
table_widget_->item(row, 0)->setData(
|
||||
Qt::UserRole, QString::fromStdString(entry.path_to_file.string()));
|
||||
Qt::UserRole, SafeQString(entry.path_to_file.string()));
|
||||
table_widget_->item(row, 0)->setData(Qt::UserRole + 1, entry.title_id);
|
||||
}
|
||||
}
|
||||
@@ -766,7 +779,7 @@ void GameListDialogQt::OnGameDoubleClicked(int row, int column) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::filesystem::path path = path_str.toStdString();
|
||||
std::filesystem::path path = SafeStdString(path_str);
|
||||
LaunchGame(path, title_id);
|
||||
}
|
||||
|
||||
@@ -784,7 +797,7 @@ void GameListDialogQt::OnGameRightClicked(const QPoint& pos) {
|
||||
QString path_str = item->data(Qt::UserRole).toString();
|
||||
uint32_t title_id = item->data(Qt::UserRole + 1).toUInt();
|
||||
|
||||
std::filesystem::path path = path_str.toStdString();
|
||||
std::filesystem::path path = SafeStdString(path_str);
|
||||
bool has_path = !path_str.isEmpty();
|
||||
|
||||
// Get profile manager
|
||||
@@ -872,7 +885,7 @@ void GameListDialogQt::OnGameRightClicked(const QPoint& pos) {
|
||||
QString title_name;
|
||||
for (const auto& entry : game_entries_) {
|
||||
if (entry.title_id == title_id) {
|
||||
title_name = QString::fromStdString(entry.title_name);
|
||||
title_name = SafeQString(entry.title_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -938,16 +951,16 @@ void GameListDialogQt::OnGameRightClicked(const QPoint& pos) {
|
||||
QString title_name;
|
||||
for (const auto& entry : game_entries_) {
|
||||
if (entry.title_id == title_id) {
|
||||
title_name = QString::fromStdString(entry.title_name);
|
||||
title_name = SafeQString(entry.title_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (title_name.isEmpty()) {
|
||||
title_name = QString::fromStdString(fmt::format("{:08X}", title_id));
|
||||
title_name = SafeQString(fmt::format("{:08X}", title_id));
|
||||
}
|
||||
|
||||
auto* dialog = new GameConfigDialogQt(this, emulator_window_, title_id,
|
||||
title_name.toStdString());
|
||||
SafeStdString(title_name));
|
||||
dialog->exec();
|
||||
delete dialog;
|
||||
} else if (selected == compatibility_canary_action &&
|
||||
@@ -957,7 +970,7 @@ void GameListDialogQt::OnGameRightClicked(const QPoint& pos) {
|
||||
"https://github.com/xenia-canary/game-compatibility/issues";
|
||||
const std::string url =
|
||||
fmt::format("{}?q=is%3Aissue+is%3Aopen+{:08X}", base_url, title_id);
|
||||
QDesktopServices::openUrl(QUrl(QString::fromStdString(url)));
|
||||
QDesktopServices::openUrl(QUrl(SafeQString(url)));
|
||||
} else if (selected == compatibility_master_action &&
|
||||
compatibility_master_action) {
|
||||
// Open Master game compatibility page with this title ID
|
||||
@@ -965,7 +978,7 @@ void GameListDialogQt::OnGameRightClicked(const QPoint& pos) {
|
||||
"https://github.com/xenia-project/game-compatibility/issues";
|
||||
const std::string url =
|
||||
fmt::format("{}?q=is%3Aissue+is%3Aopen+{:08X}", base_url, title_id);
|
||||
QDesktopServices::openUrl(QUrl(QString::fromStdString(url)));
|
||||
QDesktopServices::openUrl(QUrl(SafeQString(url)));
|
||||
} else if (selected == remove_action) {
|
||||
RemoveTitleFromDashboard(title_id);
|
||||
}
|
||||
@@ -1139,7 +1152,7 @@ void GameListDialogQt::OnSelectionChanged() {
|
||||
QString path_str = item->data(Qt::UserRole).toString();
|
||||
uint32_t title_id = item->data(Qt::UserRole + 1).toUInt();
|
||||
if (!path_str.isEmpty()) {
|
||||
selected_game_path_ = path_str.toStdString();
|
||||
selected_game_path_ = SafeStdString(path_str);
|
||||
selected_game_title_id_ = title_id;
|
||||
UpdatePlayButtonState();
|
||||
return;
|
||||
@@ -1226,8 +1239,7 @@ void GameListDialogQt::UpdateProfileButtonState() {
|
||||
auto accounts = profile_manager->GetAccounts();
|
||||
auto account_it = accounts->find(profile->xuid());
|
||||
if (account_it != accounts->end()) {
|
||||
QString gamertag =
|
||||
QString::fromStdString(account_it->second.GetGamertagString());
|
||||
QString gamertag = SafeQString(account_it->second.GetGamertagString());
|
||||
profile_label_->setText(gamertag);
|
||||
profile_question_label_->setVisible(
|
||||
false); // Hide question mark when logged in
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "xenia/app/emulator_window.h"
|
||||
#include "xenia/base/cvar.h"
|
||||
#include "xenia/gpu/graphics_system.h"
|
||||
#include "xenia/ui/qt_util.h"
|
||||
|
||||
DECLARE_bool(postprocess_dither);
|
||||
DECLARE_double(postprocess_ffx_cas_additional_sharpness);
|
||||
@@ -31,6 +32,8 @@ DECLARE_string(postprocess_scaling_and_sharpening);
|
||||
namespace xe {
|
||||
namespace app {
|
||||
|
||||
using xe::ui::SafeQString;
|
||||
|
||||
PostProcessingDialogQt::PostProcessingDialogQt(QWidget* parent,
|
||||
EmulatorWindow* emulator_window)
|
||||
: QDialog(parent), emulator_window_(emulator_window) {
|
||||
@@ -446,8 +449,8 @@ void PostProcessingDialogQt::OnFsrSharpnessChanged(int value) {
|
||||
presenter->SetGuestOutputPaintConfigFromUIThread(config);
|
||||
|
||||
// Update label
|
||||
fsr_sharpness_value_label_->setText(QString::fromStdString(
|
||||
fmt::format("{} %", static_cast<int>(fsr_sharpness * 100))));
|
||||
fsr_sharpness_value_label_->setText(
|
||||
SafeQString(fmt::format("{} %", static_cast<int>(fsr_sharpness * 100))));
|
||||
|
||||
// Update cvar
|
||||
emulator_window_->UpdateFsrSharpnessCvar(fsr_sharpness);
|
||||
@@ -477,8 +480,8 @@ void PostProcessingDialogQt::OnCasSharpnessChanged(int value) {
|
||||
presenter->SetGuestOutputPaintConfigFromUIThread(config);
|
||||
|
||||
// Update label
|
||||
cas_sharpness_value_label_->setText(QString::fromStdString(
|
||||
fmt::format("{} %", static_cast<int>(cas_sharpness * 100))));
|
||||
cas_sharpness_value_label_->setText(
|
||||
SafeQString(fmt::format("{} %", static_cast<int>(cas_sharpness * 100))));
|
||||
|
||||
// Update cvar
|
||||
emulator_window_->UpdateCasSharpnessCvar(cas_sharpness);
|
||||
|
||||
@@ -25,11 +25,15 @@
|
||||
#include "xenia/kernel/xam/ui/title_info_ui.h"
|
||||
#include "xenia/kernel/xam/xam_state.h"
|
||||
#include "xenia/ui/profile_editor_dialog_qt.h"
|
||||
#include "xenia/ui/qt_util.h"
|
||||
#include "xenia/ui/window_qt.h"
|
||||
|
||||
namespace xe {
|
||||
namespace app {
|
||||
|
||||
using xe::ui::SafeQString;
|
||||
using xe::ui::SafeStdString;
|
||||
|
||||
ProfileDialogQt::ProfileDialogQt(QWidget* parent,
|
||||
EmulatorWindow* emulator_window)
|
||||
: QDialog(parent), emulator_window_(emulator_window) {
|
||||
@@ -206,7 +210,7 @@ void ProfileDialogQt::PopulateProfileList() {
|
||||
const uint8_t user_index =
|
||||
profile_manager->GetUserIndexAssignedToProfile(xuid);
|
||||
|
||||
QString gamertag = QString::fromStdString(account.GetGamertagString());
|
||||
QString gamertag = SafeQString(account.GetGamertagString());
|
||||
QString status = (user_index == XUserIndexAny)
|
||||
? " (Not logged in)"
|
||||
: fmt::format(" (Slot {})", user_index + 1).c_str();
|
||||
@@ -327,8 +331,8 @@ void ProfileDialogQt::OnProfileContextMenu(const QPoint& pos) {
|
||||
// Login to slot submenu
|
||||
QMenu* login_slot_menu = context_menu.addMenu("Login to slot:");
|
||||
for (uint8_t i = 1; i <= XUserMaxUserCount; i++) {
|
||||
QAction* slot_action = login_slot_menu->addAction(
|
||||
QString::fromStdString(fmt::format("slot {}", i)));
|
||||
QAction* slot_action =
|
||||
login_slot_menu->addAction(SafeQString(fmt::format("slot {}", i)));
|
||||
connect(slot_action, &QAction::triggered, [=, this]() {
|
||||
profile_manager->Login(xuid, i - 1);
|
||||
RefreshProfiles();
|
||||
@@ -382,8 +386,7 @@ void ProfileDialogQt::OnProfileContextMenu(const QPoint& pos) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString gamertag =
|
||||
QString::fromStdString(profile_it->second.GetGamertagString());
|
||||
QString gamertag = SafeQString(profile_it->second.GetGamertagString());
|
||||
|
||||
QMessageBox::StandardButton reply = QMessageBox::question(
|
||||
this, "Delete Profile",
|
||||
@@ -442,7 +445,7 @@ void ProfileDialogQt::OnCreateProfileClicked() {
|
||||
}
|
||||
|
||||
// Create the profile
|
||||
std::string gamertag_string = gamertag.toStdString();
|
||||
std::string gamertag_string = SafeStdString(gamertag);
|
||||
bool autologin = (profile_manager->GetAccountCount() == 0);
|
||||
|
||||
if (profile_manager->CreateProfile(gamertag_string, autologin, false)) {
|
||||
|
||||
@@ -30,11 +30,14 @@
|
||||
#include "xenia/kernel/xam/user_settings.h"
|
||||
#include "xenia/kernel/xam/user_tracker.h"
|
||||
#include "xenia/kernel/xam/xam_state.h"
|
||||
#include "xenia/ui/qt_util.h"
|
||||
|
||||
namespace xe {
|
||||
namespace app {
|
||||
|
||||
using namespace kernel::xam;
|
||||
using xe::ui::SafeQString;
|
||||
using xe::ui::SafeStdString;
|
||||
|
||||
// Language names
|
||||
static const char* kLanguageNames[] = {nullptr,
|
||||
@@ -361,7 +364,7 @@ void ProfileEditorDialogQt::SetupUI() {
|
||||
const auto profile = xam_state ? xam_state->GetUserProfile(xuid_) : nullptr;
|
||||
|
||||
setWindowTitle(QString("Gamercard Editor - %1")
|
||||
.arg(QString::fromStdString(current_data_.gamertag)));
|
||||
.arg(SafeQString(current_data_.gamertag)));
|
||||
setModal(false); // Non-modal like ProfileDialogQt
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setMinimumSize(900, 700);
|
||||
@@ -416,8 +419,7 @@ void ProfileEditorDialogQt::SetupUI() {
|
||||
|
||||
// Gamertag
|
||||
profile_layout->addWidget(new QLabel("Gamertag:"), row, 0);
|
||||
gamertag_edit_ =
|
||||
new QLineEdit(QString::fromStdString(current_data_.gamertag));
|
||||
gamertag_edit_ = new QLineEdit(SafeQString(current_data_.gamertag));
|
||||
gamertag_edit_->setMaxLength(15);
|
||||
connect(gamertag_edit_, &QLineEdit::textChanged, this,
|
||||
&ProfileEditorDialogQt::UpdateGamertagValidation);
|
||||
@@ -430,24 +432,21 @@ void ProfileEditorDialogQt::SetupUI() {
|
||||
|
||||
// Gamer Name
|
||||
profile_layout->addWidget(new QLabel("Gamer Name:"), row, 0);
|
||||
gamer_name_edit_ =
|
||||
new QLineEdit(QString::fromStdString(current_data_.gamer_name));
|
||||
gamer_name_edit_ = new QLineEdit(SafeQString(current_data_.gamer_name));
|
||||
gamer_name_edit_->setMaxLength(130); // 0x104 bytes = 130 UTF-16 characters
|
||||
gamer_name_edit_->setEnabled(profile != nullptr);
|
||||
profile_layout->addWidget(gamer_name_edit_, row++, 1);
|
||||
|
||||
// Gamer Motto
|
||||
profile_layout->addWidget(new QLabel("Gamer Motto:"), row, 0);
|
||||
gamer_motto_edit_ =
|
||||
new QLineEdit(QString::fromStdString(current_data_.gamer_motto));
|
||||
gamer_motto_edit_ = new QLineEdit(SafeQString(current_data_.gamer_motto));
|
||||
gamer_motto_edit_->setMaxLength(22); // 0x2C bytes = 22 UTF-16 characters
|
||||
gamer_motto_edit_->setEnabled(profile != nullptr);
|
||||
profile_layout->addWidget(gamer_motto_edit_, row++, 1);
|
||||
|
||||
// Gamer Bio
|
||||
profile_layout->addWidget(new QLabel("Gamer Bio:"), row, 0);
|
||||
gamer_bio_edit_ =
|
||||
new QTextEdit(QString::fromStdString(current_data_.gamer_bio));
|
||||
gamer_bio_edit_ = new QTextEdit(SafeQString(current_data_.gamer_bio));
|
||||
gamer_bio_edit_->setEnabled(profile != nullptr);
|
||||
gamer_bio_edit_->setMaximumHeight(100);
|
||||
// Limit bio to 500 characters (0x3E8 bytes = 500 UTF-16 characters)
|
||||
@@ -503,15 +502,13 @@ void ProfileEditorDialogQt::SetupUI() {
|
||||
|
||||
// Online XUID (read-only)
|
||||
online_layout->addWidget(new QLabel("Online XUID:"), row, 0);
|
||||
online_xuid_edit_ =
|
||||
new QLineEdit(QString::fromStdString(current_data_.online_xuid));
|
||||
online_xuid_edit_ = new QLineEdit(SafeQString(current_data_.online_xuid));
|
||||
online_xuid_edit_->setReadOnly(true);
|
||||
online_layout->addWidget(online_xuid_edit_, row++, 1);
|
||||
|
||||
// Online Domain (read-only)
|
||||
online_layout->addWidget(new QLabel("Online Domain:"), row, 0);
|
||||
online_domain_edit_ =
|
||||
new QLineEdit(QString::fromStdString(current_data_.online_domain));
|
||||
online_domain_edit_ = new QLineEdit(SafeQString(current_data_.online_domain));
|
||||
online_domain_edit_->setReadOnly(true);
|
||||
online_layout->addWidget(online_domain_edit_, row++, 1);
|
||||
|
||||
@@ -731,7 +728,7 @@ void ProfileEditorDialogQt::LoadProfileIcon() {
|
||||
}
|
||||
|
||||
bool ProfileEditorDialogQt::ValidateGamertagInput(const QString& text) {
|
||||
std::string gamertag = text.toStdString();
|
||||
std::string gamertag = SafeStdString(text);
|
||||
return ProfileManager::IsGamertagValid(gamertag);
|
||||
}
|
||||
|
||||
@@ -762,7 +759,7 @@ void ProfileEditorDialogQt::OnChangeIconClicked() {
|
||||
return;
|
||||
}
|
||||
|
||||
std::filesystem::path path = file_path.toStdString();
|
||||
std::filesystem::path path = SafeStdString(file_path);
|
||||
|
||||
if (!IsFilePngImage(path)) {
|
||||
QMessageBox::warning(this, "Invalid File",
|
||||
@@ -820,7 +817,7 @@ void ProfileEditorDialogQt::SaveProfileData() {
|
||||
auto account = account_original;
|
||||
|
||||
// Update gamertag
|
||||
std::string gamertag_str = gamertag_edit_->text().toStdString();
|
||||
std::string gamertag_str = SafeStdString(gamertag_edit_->text());
|
||||
std::u16string gamertag = xe::to_utf16(gamertag_str);
|
||||
string_util::copy_truncating(account.gamertag, gamertag,
|
||||
std::size(account.gamertag));
|
||||
@@ -864,7 +861,7 @@ void ProfileEditorDialogQt::SaveProfileData() {
|
||||
size_t max_utf16_chars) {
|
||||
// Convert QString to std::u16string using xe::to_utf16 for proper
|
||||
// conversion
|
||||
std::string utf8_text = text.toStdString();
|
||||
std::string utf8_text = SafeStdString(text);
|
||||
std::u16string new_value = xe::to_utf16(utf8_text);
|
||||
|
||||
// Truncate if exceeds max length (in UTF-16 characters)
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2025 Xenia Canary. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_UI_QT_UTIL_H_
|
||||
#define XENIA_UI_QT_UTIL_H_
|
||||
|
||||
#include <QString>
|
||||
#include <string>
|
||||
|
||||
namespace xe {
|
||||
namespace ui {
|
||||
|
||||
// Safely convert std::string to QString, handling invalid UTF-8 data
|
||||
// Uses QString::fromUtf8 which is more robust than fromStdString
|
||||
inline QString SafeQString(const std::string& str) {
|
||||
return QString::fromUtf8(str.c_str(), static_cast<qsizetype>(str.size()));
|
||||
}
|
||||
|
||||
// Safely convert QString to std::string, handling invalid UTF-8 data
|
||||
// Uses QString::toUtf8 which is more robust than toStdString
|
||||
inline std::string SafeStdString(const QString& qstr) {
|
||||
QByteArray utf8 = qstr.toUtf8();
|
||||
return std::string(utf8.constData(), utf8.size());
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_UI_QT_UTIL_H_
|
||||
@@ -16,10 +16,13 @@
|
||||
|
||||
#include "third_party/fmt/include/fmt/format.h"
|
||||
#include "xenia/app/emulator_window.h"
|
||||
#include "xenia/ui/qt_util.h"
|
||||
|
||||
namespace xe {
|
||||
namespace app {
|
||||
|
||||
using xe::ui::SafeQString;
|
||||
|
||||
XmpDialogQt::XmpDialogQt(QWidget* parent, EmulatorWindow* emulator_window)
|
||||
: QDialog(parent), emulator_window_(emulator_window) {
|
||||
SetupUI();
|
||||
@@ -246,8 +249,8 @@ void XmpDialogQt::UpdatePlayerState() {
|
||||
float volume = audio_player->GetVolume()->load();
|
||||
volume_slider_->blockSignals(true);
|
||||
volume_slider_->setValue(static_cast<int>(volume * 100));
|
||||
volume_value_label_->setText(QString::fromStdString(
|
||||
fmt::format("{}%", static_cast<int>(volume * 100))));
|
||||
volume_value_label_->setText(
|
||||
SafeQString(fmt::format("{}%", static_cast<int>(volume * 100))));
|
||||
volume_slider_->blockSignals(false);
|
||||
}
|
||||
|
||||
@@ -287,8 +290,7 @@ void XmpDialogQt::OnVolumeChanged(int value) {
|
||||
audio_player->SetVolume(volume);
|
||||
|
||||
// Update label
|
||||
volume_value_label_->setText(
|
||||
QString::fromStdString(fmt::format("{}%", value)));
|
||||
volume_value_label_->setText(SafeQString(fmt::format("{}%", value)));
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
Reference in New Issue
Block a user