mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-20 02:53:57 +00:00
Merge branch 'fixPropertiesWindowScaling' into 'main'
fix: Properties Window Scaling See merge request citron/emulator!75
This commit is contained in:
@@ -53,7 +53,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="profile_player_1">
|
<widget class="QComboBox" name="profile_player_1">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="profile_player_2">
|
<widget class="QComboBox" name="profile_player_2">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
@@ -123,7 +123,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="profile_player_3">
|
<widget class="QComboBox" name="profile_player_3">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="profile_player_4">
|
<widget class="QComboBox" name="profile_player_4">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
@@ -193,7 +193,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="profile_player_5">
|
<widget class="QComboBox" name="profile_player_5">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
@@ -228,7 +228,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="profile_player_6">
|
<widget class="QComboBox" name="profile_player_6">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
@@ -263,7 +263,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="profile_player_7">
|
<widget class="QComboBox" name="profile_player_7">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
@@ -298,7 +298,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="profile_player_8">
|
<widget class="QComboBox" name="profile_player_8">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
|
|||||||
@@ -51,28 +51,33 @@
|
|||||||
ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name,
|
ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name,
|
||||||
std::vector<VkDeviceInfo::Record>& vk_device_records,
|
std::vector<VkDeviceInfo::Record>& vk_device_records,
|
||||||
Core::System& system_)
|
Core::System& system_)
|
||||||
: QDialog(parent),
|
: QDialog(parent),
|
||||||
ui(std::make_unique<Ui::ConfigurePerGame>()), title_id{title_id_}, system{system_},
|
ui(std::make_unique<Ui::ConfigurePerGame>()), title_id{title_id_}, system{system_},
|
||||||
builder{std::make_unique<ConfigurationShared::Builder>(this, !system_.IsPoweredOn())},
|
builder{std::make_unique<ConfigurationShared::Builder>(this, !system_.IsPoweredOn())},
|
||||||
tab_group{std::make_shared<std::vector<ConfigurationShared::Tab*>>()} {
|
tab_group{std::make_shared<std::vector<ConfigurationShared::Tab*>>()} {
|
||||||
const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name));
|
const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name));
|
||||||
const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename())
|
const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename())
|
||||||
: fmt::format("{:016X}", title_id);
|
: fmt::format("{:016X}", title_id);
|
||||||
game_config = std::make_unique<QtConfig>(config_file_name, Config::ConfigType::PerGameConfig);
|
game_config = std::make_unique<QtConfig>(config_file_name, Config::ConfigType::PerGameConfig);
|
||||||
addons_tab = std::make_unique<ConfigurePerGameAddons>(system_, this);
|
addons_tab = std::make_unique<ConfigurePerGameAddons>(system_, this);
|
||||||
audio_tab = std::make_unique<ConfigureAudio>(system_, tab_group, *builder, this);
|
audio_tab = std::make_unique<ConfigureAudio>(system_, tab_group, *builder, this);
|
||||||
cpu_tab = std::make_unique<ConfigureCpu>(system_, tab_group, *builder, this);
|
cpu_tab = std::make_unique<ConfigureCpu>(system_, tab_group, *builder, this);
|
||||||
graphics_advanced_tab =
|
graphics_advanced_tab =
|
||||||
std::make_unique<ConfigureGraphicsAdvanced>(system_, tab_group, *builder, this);
|
std::make_unique<ConfigureGraphicsAdvanced>(system_, tab_group, *builder, this);
|
||||||
graphics_tab = std::make_unique<ConfigureGraphics>(
|
graphics_tab = std::make_unique<ConfigureGraphics>(
|
||||||
system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); },
|
system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); },
|
||||||
[](Settings::AspectRatio, Settings::ResolutionSetup) {}, tab_group, *builder, this);
|
[](Settings::AspectRatio, Settings::ResolutionSetup) {}, tab_group, *builder, this);
|
||||||
input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this);
|
input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this);
|
||||||
linux_tab = std::make_unique<ConfigureLinuxTab>(system_, tab_group, *builder, this);
|
linux_tab = std::make_unique<ConfigureLinuxTab>(system_, tab_group, *builder, this);
|
||||||
system_tab = std::make_unique<ConfigureSystem>(system_, tab_group, *builder, this);
|
system_tab = std::make_unique<ConfigureSystem>(system_, tab_group, *builder, this);
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
// THIS IS THE NEW FIX: Force a minimum height on the window.
|
||||||
|
setMinimumHeight(400);
|
||||||
|
|
||||||
|
layout()->setSizeConstraint(QLayout::SetDefaultConstraint);
|
||||||
|
|
||||||
ui->tabWidget->addTab(addons_tab.get(), tr("Add-Ons"));
|
ui->tabWidget->addTab(addons_tab.get(), tr("Add-Ons"));
|
||||||
ui->tabWidget->addTab(system_tab.get(), tr("System"));
|
ui->tabWidget->addTab(system_tab.get(), tr("System"));
|
||||||
ui->tabWidget->addTab(cpu_tab.get(), tr("CPU"));
|
ui->tabWidget->addTab(cpu_tab.get(), tr("CPU"));
|
||||||
@@ -83,10 +88,10 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
|
|||||||
|
|
||||||
// Only show Linux tab on Unix
|
// Only show Linux tab on Unix
|
||||||
linux_tab->setVisible(false);
|
linux_tab->setVisible(false);
|
||||||
#ifdef __unix__
|
#ifdef __unix__
|
||||||
linux_tab->setVisible(true);
|
linux_tab->setVisible(true);
|
||||||
ui->tabWidget->addTab(linux_tab.get(), tr("Linux"));
|
ui->tabWidget->addTab(linux_tab.get(), tr("Linux"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setFocusPolicy(Qt::ClickFocus);
|
setFocusPolicy(Qt::ClickFocus);
|
||||||
setWindowTitle(tr("Properties"));
|
setWindowTitle(tr("Properties"));
|
||||||
@@ -115,15 +120,15 @@ void ConfigurePerGame::ApplyConfiguration() {
|
|||||||
input_tab->ApplyConfiguration();
|
input_tab->ApplyConfiguration();
|
||||||
|
|
||||||
if (Settings::IsDockedMode() && Settings::values.players.GetValue()[0].controller_type ==
|
if (Settings::IsDockedMode() && Settings::values.players.GetValue()[0].controller_type ==
|
||||||
Settings::ControllerType::Handheld) {
|
Settings::ControllerType::Handheld) {
|
||||||
Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld);
|
Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld);
|
||||||
Settings::values.use_docked_mode.SetGlobal(true);
|
Settings::values.use_docked_mode.SetGlobal(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
system.ApplySettings();
|
system.ApplySettings();
|
||||||
Settings::LogSettings();
|
Settings::LogSettings();
|
||||||
|
|
||||||
game_config->SaveAllValues();
|
game_config->SaveAllValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigurePerGame::changeEvent(QEvent* event) {
|
void ConfigurePerGame::changeEvent(QEvent* event) {
|
||||||
@@ -159,300 +164,300 @@ void ConfigurePerGame::LoadConfiguration() {
|
|||||||
QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper());
|
QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper());
|
||||||
|
|
||||||
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
|
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
|
||||||
system.GetContentProvider()};
|
system.GetContentProvider()};
|
||||||
const auto control = pm.GetControlMetadata();
|
const auto control = pm.GetControlMetadata();
|
||||||
const auto loader = Loader::GetLoader(system, file);
|
const auto loader = Loader::GetLoader(system, file);
|
||||||
|
|
||||||
if (control.first != nullptr) {
|
if (control.first != nullptr) {
|
||||||
ui->display_version->setText(QString::fromStdString(control.first->GetVersionString()));
|
ui->display_version->setText(QString::fromStdString(control.first->GetVersionString()));
|
||||||
ui->display_name->setText(QString::fromStdString(control.first->GetApplicationName()));
|
ui->display_name->setText(QString::fromStdString(control.first->GetApplicationName()));
|
||||||
ui->display_developer->setText(QString::fromStdString(control.first->GetDeveloperName()));
|
ui->display_developer->setText(QString::fromStdString(control.first->GetDeveloperName()));
|
||||||
} else {
|
} else {
|
||||||
std::string title;
|
std::string title;
|
||||||
if (loader->ReadTitle(title) == Loader::ResultStatus::Success)
|
if (loader->ReadTitle(title) == Loader::ResultStatus::Success)
|
||||||
ui->display_name->setText(QString::fromStdString(title));
|
ui->display_name->setText(QString::fromStdString(title));
|
||||||
|
|
||||||
FileSys::NACP nacp;
|
FileSys::NACP nacp;
|
||||||
if (loader->ReadControlData(nacp) == Loader::ResultStatus::Success)
|
if (loader->ReadControlData(nacp) == Loader::ResultStatus::Success)
|
||||||
ui->display_developer->setText(QString::fromStdString(nacp.GetDeveloperName()));
|
ui->display_developer->setText(QString::fromStdString(nacp.GetDeveloperName()));
|
||||||
|
|
||||||
ui->display_version->setText(QStringLiteral("1.0.0"));
|
ui->display_version->setText(QStringLiteral("1.0.0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (control.second != nullptr) {
|
if (control.second != nullptr) {
|
||||||
scene->clear();
|
|
||||||
|
|
||||||
QPixmap map;
|
|
||||||
const auto bytes = control.second->ReadAllBytes();
|
|
||||||
map.loadFromData(bytes.data(), static_cast<u32>(bytes.size()));
|
|
||||||
|
|
||||||
scene->addPixmap(map.scaled(ui->icon_view->width(), ui->icon_view->height(),
|
|
||||||
Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
|
||||||
} else {
|
|
||||||
std::vector<u8> bytes;
|
|
||||||
if (loader->ReadIcon(bytes) == Loader::ResultStatus::Success) {
|
|
||||||
scene->clear();
|
scene->clear();
|
||||||
|
|
||||||
QPixmap map;
|
QPixmap map;
|
||||||
|
const auto bytes = control.second->ReadAllBytes();
|
||||||
map.loadFromData(bytes.data(), static_cast<u32>(bytes.size()));
|
map.loadFromData(bytes.data(), static_cast<u32>(bytes.size()));
|
||||||
|
|
||||||
scene->addPixmap(map.scaled(ui->icon_view->width(), ui->icon_view->height(),
|
scene->addPixmap(map.scaled(ui->icon_view->width(), ui->icon_view->height(),
|
||||||
Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||||
}
|
} else {
|
||||||
}
|
std::vector<u8> bytes;
|
||||||
|
if (loader->ReadIcon(bytes) == Loader::ResultStatus::Success) {
|
||||||
|
scene->clear();
|
||||||
|
|
||||||
ui->display_filename->setText(QString::fromStdString(file->GetName()));
|
QPixmap map;
|
||||||
|
map.loadFromData(bytes.data(), static_cast<u32>(bytes.size()));
|
||||||
|
|
||||||
ui->display_format->setText(
|
scene->addPixmap(map.scaled(ui->icon_view->width(), ui->icon_view->height(),
|
||||||
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())));
|
Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||||
|
|
||||||
const auto valueText = ReadableByteSize(file->GetSize());
|
|
||||||
ui->display_size->setText(valueText);
|
|
||||||
|
|
||||||
// Display Build ID(s) if available
|
|
||||||
std::string base_build_id_hex;
|
|
||||||
std::string update_build_id_hex;
|
|
||||||
|
|
||||||
// Try to get build ID based on file type
|
|
||||||
const auto file_type = loader->GetFileType();
|
|
||||||
|
|
||||||
if (file_type == Loader::FileType::NSO) {
|
|
||||||
// For NSO files, read the build ID directly from the header
|
|
||||||
if (file->GetSize() >= 0x100) {
|
|
||||||
std::array<u8, 0x100> header_data{};
|
|
||||||
if (file->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
|
||||||
// Build ID is at offset 0x40 in NSO header
|
|
||||||
std::array<u8, 0x20> build_id{};
|
|
||||||
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
|
||||||
base_build_id_hex = Common::HexToString(build_id, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (file_type == Loader::FileType::DeconstructedRomDirectory) {
|
|
||||||
// For deconstructed ROM directories, read from the main NSO file
|
ui->display_filename->setText(QString::fromStdString(file->GetName()));
|
||||||
const auto main_dir = file->GetContainingDirectory();
|
|
||||||
if (main_dir) {
|
ui->display_format->setText(
|
||||||
const auto main_nso = main_dir->GetFile("main");
|
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())));
|
||||||
if (main_nso && main_nso->GetSize() >= 0x100) {
|
|
||||||
|
const auto valueText = ReadableByteSize(file->GetSize());
|
||||||
|
ui->display_size->setText(valueText);
|
||||||
|
|
||||||
|
// Display Build ID(s) if available
|
||||||
|
std::string base_build_id_hex;
|
||||||
|
std::string update_build_id_hex;
|
||||||
|
|
||||||
|
// Try to get build ID based on file type
|
||||||
|
const auto file_type = loader->GetFileType();
|
||||||
|
|
||||||
|
if (file_type == Loader::FileType::NSO) {
|
||||||
|
// For NSO files, read the build ID directly from the header
|
||||||
|
if (file->GetSize() >= 0x100) {
|
||||||
std::array<u8, 0x100> header_data{};
|
std::array<u8, 0x100> header_data{};
|
||||||
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
if (file->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
||||||
// Build ID is at offset 0x40 in NSO header
|
// Build ID is at offset 0x40 in NSO header
|
||||||
std::array<u8, 0x20> build_id{};
|
std::array<u8, 0x20> build_id{};
|
||||||
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
||||||
base_build_id_hex = Common::HexToString(build_id, false);
|
base_build_id_hex = Common::HexToString(build_id, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (file_type == Loader::FileType::DeconstructedRomDirectory) {
|
||||||
|
// For deconstructed ROM directories, read from the main NSO file
|
||||||
|
const auto main_dir = file->GetContainingDirectory();
|
||||||
|
if (main_dir) {
|
||||||
|
const auto main_nso = main_dir->GetFile("main");
|
||||||
|
if (main_nso && main_nso->GetSize() >= 0x100) {
|
||||||
|
std::array<u8, 0x100> header_data{};
|
||||||
|
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
||||||
|
// Build ID is at offset 0x40 in NSO header
|
||||||
|
std::array<u8, 0x20> build_id{};
|
||||||
|
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
||||||
|
base_build_id_hex = Common::HexToString(build_id, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// For other file types (XCI, NSP, NCA), try to extract build ID directly
|
||||||
|
try {
|
||||||
|
if (file_type == Loader::FileType::XCI) {
|
||||||
|
// For XCI files, try to construct with the proper parameters
|
||||||
|
try {
|
||||||
|
// First try to get the program ID from the XCI to use proper parameters
|
||||||
|
FileSys::XCI xci_temp(file);
|
||||||
|
if (xci_temp.GetStatus() == Loader::ResultStatus::Success) {
|
||||||
|
// Try to get the program NCA from the secure partition
|
||||||
|
FileSys::XCI xci(file, title_id, 0); // Use detected title_id
|
||||||
|
if (xci.GetStatus() == Loader::ResultStatus::Success) {
|
||||||
|
auto program_nca = xci.GetNCAByType(FileSys::NCAContentType::Program);
|
||||||
|
if (program_nca && program_nca->GetStatus() == Loader::ResultStatus::Success) {
|
||||||
|
auto exefs = program_nca->GetExeFS();
|
||||||
|
if (exefs) {
|
||||||
|
auto main_nso = exefs->GetFile("main");
|
||||||
|
if (main_nso && main_nso->GetSize() >= 0x100) {
|
||||||
|
std::array<u8, 0x100> header_data{};
|
||||||
|
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
||||||
|
std::array<u8, 0x20> build_id{};
|
||||||
|
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
||||||
|
base_build_id_hex = Common::HexToString(build_id, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
// XCI might be encrypted or have other issues
|
||||||
|
// Fall back to checking if it's installed in the content provider
|
||||||
|
const auto& content_provider = system.GetContentProvider();
|
||||||
|
auto base_nca = content_provider.GetEntry(title_id, FileSys::ContentRecordType::Program);
|
||||||
|
if (base_nca && base_nca->GetStatus() == Loader::ResultStatus::Success) {
|
||||||
|
auto exefs = base_nca->GetExeFS();
|
||||||
|
if (exefs) {
|
||||||
|
auto main_nso = exefs->GetFile("main");
|
||||||
|
if (main_nso && main_nso->GetSize() >= 0x100) {
|
||||||
|
std::array<u8, 0x100> header_data{};
|
||||||
|
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
||||||
|
std::array<u8, 0x20> build_id{};
|
||||||
|
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
||||||
|
base_build_id_hex = Common::HexToString(build_id, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (file_type == Loader::FileType::NSP) {
|
||||||
|
// For NSP files, try to construct and parse directly
|
||||||
|
FileSys::NSP nsp(file);
|
||||||
|
if (nsp.GetStatus() == Loader::ResultStatus::Success) {
|
||||||
|
auto exefs = nsp.GetExeFS();
|
||||||
|
if (exefs) {
|
||||||
|
auto main_nso = exefs->GetFile("main");
|
||||||
|
if (main_nso && main_nso->GetSize() >= 0x100) {
|
||||||
|
std::array<u8, 0x100> header_data{};
|
||||||
|
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
||||||
|
std::array<u8, 0x20> build_id{};
|
||||||
|
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
||||||
|
base_build_id_hex = Common::HexToString(build_id, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (file_type == Loader::FileType::NCA) {
|
||||||
|
// For NCA files, try to construct and parse directly
|
||||||
|
FileSys::NCA nca(file);
|
||||||
|
if (nca.GetStatus() == Loader::ResultStatus::Success) {
|
||||||
|
auto exefs = nca.GetExeFS();
|
||||||
|
if (exefs) {
|
||||||
|
auto main_nso = exefs->GetFile("main");
|
||||||
|
if (main_nso && main_nso->GetSize() >= 0x100) {
|
||||||
|
std::array<u8, 0x100> header_data{};
|
||||||
|
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
||||||
|
std::array<u8, 0x20> build_id{};
|
||||||
|
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
||||||
|
base_build_id_hex = Common::HexToString(build_id, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
// If anything fails, continue without the build ID
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// For other file types (XCI, NSP, NCA), try to extract build ID directly
|
// Try to get update build ID from patch manager and content provider
|
||||||
try {
|
try {
|
||||||
if (file_type == Loader::FileType::XCI) {
|
// Method 1: Try through patch manager (more reliable for updates)
|
||||||
// For XCI files, try to construct with the proper parameters
|
const FileSys::PatchManager pm_update{title_id, system.GetFileSystemController(),
|
||||||
try {
|
system.GetContentProvider()};
|
||||||
// First try to get the program ID from the XCI to use proper parameters
|
|
||||||
FileSys::XCI xci_temp(file);
|
// Check if patch manager has update information
|
||||||
if (xci_temp.GetStatus() == Loader::ResultStatus::Success) {
|
const auto update_version = pm_update.GetGameVersion();
|
||||||
// Try to get the program NCA from the secure partition
|
if (update_version.has_value() && update_version.value() > 0) {
|
||||||
FileSys::XCI xci(file, title_id, 0); // Use detected title_id
|
// There's an update, try to get its build ID through the patch manager
|
||||||
if (xci.GetStatus() == Loader::ResultStatus::Success) {
|
// The patch manager should have access to the update NCA
|
||||||
auto program_nca = xci.GetNCAByType(FileSys::NCAContentType::Program);
|
|
||||||
if (program_nca && program_nca->GetStatus() == Loader::ResultStatus::Success) {
|
// Try to get the update NCA through the patch manager's content provider
|
||||||
auto exefs = program_nca->GetExeFS();
|
const auto& content_provider = system.GetContentProvider();
|
||||||
if (exefs) {
|
const auto update_title_id = FileSys::GetUpdateTitleID(title_id);
|
||||||
auto main_nso = exefs->GetFile("main");
|
auto update_nca = content_provider.GetEntry(update_title_id, FileSys::ContentRecordType::Program);
|
||||||
if (main_nso && main_nso->GetSize() >= 0x100) {
|
|
||||||
std::array<u8, 0x100> header_data{};
|
if (update_nca && update_nca->GetStatus() == Loader::ResultStatus::Success) {
|
||||||
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
auto exefs = update_nca->GetExeFS();
|
||||||
std::array<u8, 0x20> build_id{};
|
if (exefs) {
|
||||||
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
auto main_nso = exefs->GetFile("main");
|
||||||
base_build_id_hex = Common::HexToString(build_id, false);
|
if (main_nso && main_nso->GetSize() >= 0x100) {
|
||||||
}
|
std::array<u8, 0x100> header_data{};
|
||||||
}
|
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
||||||
}
|
std::array<u8, 0x20> build_id{};
|
||||||
}
|
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
||||||
}
|
update_build_id_hex = Common::HexToString(build_id, false);
|
||||||
}
|
}
|
||||||
} catch (...) {
|
|
||||||
// XCI might be encrypted or have other issues
|
|
||||||
// Fall back to checking if it's installed in the content provider
|
|
||||||
const auto& content_provider = system.GetContentProvider();
|
|
||||||
auto base_nca = content_provider.GetEntry(title_id, FileSys::ContentRecordType::Program);
|
|
||||||
if (base_nca && base_nca->GetStatus() == Loader::ResultStatus::Success) {
|
|
||||||
auto exefs = base_nca->GetExeFS();
|
|
||||||
if (exefs) {
|
|
||||||
auto main_nso = exefs->GetFile("main");
|
|
||||||
if (main_nso && main_nso->GetSize() >= 0x100) {
|
|
||||||
std::array<u8, 0x100> header_data{};
|
|
||||||
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
|
||||||
std::array<u8, 0x20> build_id{};
|
|
||||||
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
|
||||||
base_build_id_hex = Common::HexToString(build_id, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (file_type == Loader::FileType::NSP) {
|
|
||||||
// For NSP files, try to construct and parse directly
|
|
||||||
FileSys::NSP nsp(file);
|
|
||||||
if (nsp.GetStatus() == Loader::ResultStatus::Success) {
|
|
||||||
auto exefs = nsp.GetExeFS();
|
|
||||||
if (exefs) {
|
|
||||||
auto main_nso = exefs->GetFile("main");
|
|
||||||
if (main_nso && main_nso->GetSize() >= 0x100) {
|
|
||||||
std::array<u8, 0x100> header_data{};
|
|
||||||
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
|
||||||
std::array<u8, 0x20> build_id{};
|
|
||||||
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
|
||||||
base_build_id_hex = Common::HexToString(build_id, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (file_type == Loader::FileType::NCA) {
|
|
||||||
// For NCA files, try to construct and parse directly
|
// Method 2: If patch manager approach didn't work, try direct content provider access
|
||||||
FileSys::NCA nca(file);
|
if (update_build_id_hex.empty()) {
|
||||||
if (nca.GetStatus() == Loader::ResultStatus::Success) {
|
const auto& content_provider = system.GetContentProvider();
|
||||||
auto exefs = nca.GetExeFS();
|
const auto update_title_id = FileSys::GetUpdateTitleID(title_id);
|
||||||
if (exefs) {
|
auto update_nca = content_provider.GetEntry(update_title_id, FileSys::ContentRecordType::Program);
|
||||||
auto main_nso = exefs->GetFile("main");
|
|
||||||
if (main_nso && main_nso->GetSize() >= 0x100) {
|
if (update_nca && update_nca->GetStatus() == Loader::ResultStatus::Success) {
|
||||||
std::array<u8, 0x100> header_data{};
|
auto exefs = update_nca->GetExeFS();
|
||||||
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
if (exefs) {
|
||||||
std::array<u8, 0x20> build_id{};
|
auto main_nso = exefs->GetFile("main");
|
||||||
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
if (main_nso && main_nso->GetSize() >= 0x100) {
|
||||||
base_build_id_hex = Common::HexToString(build_id, false);
|
std::array<u8, 0x100> header_data{};
|
||||||
|
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
||||||
|
std::array<u8, 0x20> build_id{};
|
||||||
|
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
||||||
|
update_build_id_hex = Common::HexToString(build_id, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// Method 3: Try to use the patch manager's GetPatches to detect updates
|
||||||
|
if (update_build_id_hex.empty()) {
|
||||||
|
const auto patches = pm_update.GetPatches();
|
||||||
|
for (const auto& patch : patches) {
|
||||||
|
if (patch.type == FileSys::PatchType::Update && patch.enabled) {
|
||||||
|
// There's an enabled update patch, but we couldn't get its build ID
|
||||||
|
// This indicates an update is available but not currently loaded
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// If anything fails, continue without the build ID
|
// If update build ID extraction fails, continue with just base
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Try to get update build ID from patch manager and content provider
|
// Try to get the actual running build ID from system (this will be the update if one is applied)
|
||||||
try {
|
const auto& system_build_id = system.GetApplicationProcessBuildID();
|
||||||
// Method 1: Try through patch manager (more reliable for updates)
|
const auto system_build_id_hex = Common::HexToString(system_build_id, false);
|
||||||
const FileSys::PatchManager pm_update{title_id, system.GetFileSystemController(),
|
|
||||||
system.GetContentProvider()};
|
|
||||||
|
|
||||||
// Check if patch manager has update information
|
// If we have a system build ID and it's different from the base, it's likely the update
|
||||||
const auto update_version = pm_update.GetGameVersion();
|
if (!system_build_id_hex.empty() && system_build_id_hex != std::string(64, '0')) {
|
||||||
if (update_version.has_value() && update_version.value() > 0) {
|
if (!base_build_id_hex.empty() && system_build_id_hex != base_build_id_hex) {
|
||||||
// There's an update, try to get its build ID through the patch manager
|
// System build ID is different from base, so it's the update
|
||||||
// The patch manager should have access to the update NCA
|
update_build_id_hex = system_build_id_hex;
|
||||||
|
} else if (base_build_id_hex.empty()) {
|
||||||
// Try to get the update NCA through the patch manager's content provider
|
// No base build ID found, use system as base
|
||||||
const auto& content_provider = system.GetContentProvider();
|
base_build_id_hex = system_build_id_hex;
|
||||||
const auto update_title_id = FileSys::GetUpdateTitleID(title_id);
|
|
||||||
auto update_nca = content_provider.GetEntry(update_title_id, FileSys::ContentRecordType::Program);
|
|
||||||
|
|
||||||
if (update_nca && update_nca->GetStatus() == Loader::ResultStatus::Success) {
|
|
||||||
auto exefs = update_nca->GetExeFS();
|
|
||||||
if (exefs) {
|
|
||||||
auto main_nso = exefs->GetFile("main");
|
|
||||||
if (main_nso && main_nso->GetSize() >= 0x100) {
|
|
||||||
std::array<u8, 0x100> header_data{};
|
|
||||||
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
|
||||||
std::array<u8, 0x20> build_id{};
|
|
||||||
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
|
||||||
update_build_id_hex = Common::HexToString(build_id, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method 2: If patch manager approach didn't work, try direct content provider access
|
// Additional check: if we still don't have an update build ID but we know there's an update
|
||||||
if (update_build_id_hex.empty()) {
|
// (from the Add-Ons tab showing v1.0.1 etc), try alternative detection methods
|
||||||
const auto& content_provider = system.GetContentProvider();
|
bool update_detected = false;
|
||||||
const auto update_title_id = FileSys::GetUpdateTitleID(title_id);
|
if (update_build_id_hex.empty() && !base_build_id_hex.empty()) {
|
||||||
auto update_nca = content_provider.GetEntry(update_title_id, FileSys::ContentRecordType::Program);
|
// Check if the patch manager indicates an update is available
|
||||||
|
const auto update_version = pm.GetGameVersion();
|
||||||
if (update_nca && update_nca->GetStatus() == Loader::ResultStatus::Success) {
|
if (update_version.has_value() && update_version.value() > 0) {
|
||||||
auto exefs = update_nca->GetExeFS();
|
update_detected = true;
|
||||||
if (exefs) {
|
|
||||||
auto main_nso = exefs->GetFile("main");
|
|
||||||
if (main_nso && main_nso->GetSize() >= 0x100) {
|
|
||||||
std::array<u8, 0x100> header_data{};
|
|
||||||
if (main_nso->ReadBytes(header_data.data(), 0x100, 0) == 0x100) {
|
|
||||||
std::array<u8, 0x20> build_id{};
|
|
||||||
std::memcpy(build_id.data(), header_data.data() + 0x40, 0x20);
|
|
||||||
update_build_id_hex = Common::HexToString(build_id, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Method 3: Try to use the patch manager's GetPatches to detect updates
|
// Also check patches
|
||||||
if (update_build_id_hex.empty()) {
|
const auto patches = pm.GetPatches();
|
||||||
const auto patches = pm_update.GetPatches();
|
|
||||||
for (const auto& patch : patches) {
|
for (const auto& patch : patches) {
|
||||||
if (patch.type == FileSys::PatchType::Update && patch.enabled) {
|
if (patch.type == FileSys::PatchType::Update && patch.enabled) {
|
||||||
// There's an enabled update patch, but we couldn't get its build ID
|
update_detected = true;
|
||||||
// This indicates an update is available but not currently loaded
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (...) {
|
|
||||||
// If update build ID extraction fails, continue with just base
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to get the actual running build ID from system (this will be the update if one is applied)
|
// Display the Build IDs in separate fields
|
||||||
const auto& system_build_id = system.GetApplicationProcessBuildID();
|
bool has_base = !base_build_id_hex.empty() && base_build_id_hex != std::string(64, '0');
|
||||||
const auto system_build_id_hex = Common::HexToString(system_build_id, false);
|
bool has_update = !update_build_id_hex.empty() && update_build_id_hex != std::string(64, '0');
|
||||||
|
|
||||||
// If we have a system build ID and it's different from the base, it's likely the update
|
// Set Base Build ID
|
||||||
if (!system_build_id_hex.empty() && system_build_id_hex != std::string(64, '0')) {
|
if (has_base) {
|
||||||
if (!base_build_id_hex.empty() && system_build_id_hex != base_build_id_hex) {
|
ui->display_build_id->setText(QString::fromStdString(base_build_id_hex));
|
||||||
// System build ID is different from base, so it's the update
|
} else {
|
||||||
update_build_id_hex = system_build_id_hex;
|
ui->display_build_id->setText(tr("Not Available"));
|
||||||
} else if (base_build_id_hex.empty()) {
|
|
||||||
// No base build ID found, use system as base
|
|
||||||
base_build_id_hex = system_build_id_hex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Additional check: if we still don't have an update build ID but we know there's an update
|
|
||||||
// (from the Add-Ons tab showing v1.0.1 etc), try alternative detection methods
|
|
||||||
bool update_detected = false;
|
|
||||||
if (update_build_id_hex.empty() && !base_build_id_hex.empty()) {
|
|
||||||
// Check if the patch manager indicates an update is available
|
|
||||||
const auto update_version = pm.GetGameVersion();
|
|
||||||
if (update_version.has_value() && update_version.value() > 0) {
|
|
||||||
update_detected = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also check patches
|
// Set Update Build ID
|
||||||
const auto patches = pm.GetPatches();
|
if (has_update) {
|
||||||
for (const auto& patch : patches) {
|
ui->display_update_build_id->setText(QString::fromStdString(update_build_id_hex));
|
||||||
if (patch.type == FileSys::PatchType::Update && patch.enabled) {
|
} else if (update_detected) {
|
||||||
update_detected = true;
|
ui->display_update_build_id->setText(tr("Available (Run game to show)"));
|
||||||
break;
|
} else {
|
||||||
}
|
ui->display_update_build_id->setText(tr("Not Available"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Display the Build IDs in separate fields
|
|
||||||
bool has_base = !base_build_id_hex.empty() && base_build_id_hex != std::string(64, '0');
|
|
||||||
bool has_update = !update_build_id_hex.empty() && update_build_id_hex != std::string(64, '0');
|
|
||||||
|
|
||||||
// Set Base Build ID
|
|
||||||
if (has_base) {
|
|
||||||
ui->display_build_id->setText(QString::fromStdString(base_build_id_hex));
|
|
||||||
} else {
|
|
||||||
ui->display_build_id->setText(tr("Not Available"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set Update Build ID
|
|
||||||
if (has_update) {
|
|
||||||
ui->display_update_build_id->setText(QString::fromStdString(update_build_id_hex));
|
|
||||||
} else if (update_detected) {
|
|
||||||
ui->display_update_build_id->setText(tr("Available (Run game to show)"));
|
|
||||||
} else {
|
|
||||||
ui->display_update_build_id->setText(tr("Not Available"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,220 +23,262 @@
|
|||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QScrollArea" name="scrollArea">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Maximum" vsizetype="Expanding">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="title">
|
<property name="minimumSize">
|
||||||
<string>Info</string>
|
<size>
|
||||||
|
<width>320</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<property name="horizontalScrollBarPolicy">
|
||||||
<item alignment="Qt::AlignHCenter">
|
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||||
<widget class="QGraphicsView" name="icon_view">
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="widgetResizable">
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
<bool>true</bool>
|
||||||
<horstretch>0</horstretch>
|
</property>
|
||||||
<verstretch>0</verstretch>
|
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||||
</sizepolicy>
|
<property name="geometry">
|
||||||
</property>
|
<rect>
|
||||||
<property name="minimumSize">
|
<x>0</x>
|
||||||
<size>
|
<y>0</y>
|
||||||
<width>256</width>
|
<width>318</width>
|
||||||
<height>256</height>
|
<height>538</height>
|
||||||
</size>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
<size>
|
<property name="leftMargin">
|
||||||
<width>256</width>
|
<number>0</number>
|
||||||
<height>256</height>
|
</property>
|
||||||
</size>
|
<property name="topMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<property name="verticalScrollBarPolicy">
|
</property>
|
||||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
<property name="rightMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<property name="horizontalScrollBarPolicy">
|
</property>
|
||||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
<property name="bottomMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<property name="interactive">
|
</property>
|
||||||
<bool>false</bool>
|
<item>
|
||||||
</property>
|
<!-- The original GroupBox is now INSIDE the scroll area -->
|
||||||
</widget>
|
<widget class="QGroupBox" name="groupBox">
|
||||||
</item>
|
<property name="title">
|
||||||
<item>
|
<string>Info</string>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
</property>
|
||||||
<item row="6" column="1">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<widget class="QLineEdit" name="display_size">
|
<item alignment="Qt::AlignHCenter">
|
||||||
<property name="enabled">
|
<widget class="QGraphicsView" name="icon_view">
|
||||||
<bool>true</bool>
|
<property name="sizePolicy">
|
||||||
</property>
|
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||||
<property name="readOnly">
|
<horstretch>0</horstretch>
|
||||||
<bool>true</bool>
|
<verstretch>0</verstretch>
|
||||||
</property>
|
</sizepolicy>
|
||||||
</widget>
|
</property>
|
||||||
</item>
|
<property name="minimumSize">
|
||||||
<item row="3" column="1">
|
<size>
|
||||||
<widget class="QLineEdit" name="display_version">
|
<width>256</width>
|
||||||
<property name="enabled">
|
<height>256</height>
|
||||||
<bool>true</bool>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
<property name="maximumSize">
|
||||||
<bool>true</bool>
|
<size>
|
||||||
</property>
|
<width>256</width>
|
||||||
</widget>
|
<height>256</height>
|
||||||
</item>
|
</size>
|
||||||
<item row="1" column="0">
|
</property>
|
||||||
<widget class="QLabel" name="label">
|
<property name="verticalScrollBarPolicy">
|
||||||
<property name="text">
|
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||||
<string>Name</string>
|
</property>
|
||||||
</property>
|
<property name="horizontalScrollBarPolicy">
|
||||||
</widget>
|
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||||
</item>
|
</property>
|
||||||
<item row="4" column="0">
|
<property name="interactive">
|
||||||
<widget class="QLabel" name="label_4">
|
<bool>false</bool>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>Title ID</string>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
</widget>
|
<item>
|
||||||
</item>
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<item row="4" column="1">
|
<item row="6" column="1">
|
||||||
<widget class="QLineEdit" name="display_title_id">
|
<widget class="QLineEdit" name="display_size">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QLineEdit" name="display_filename">
|
<widget class="QLineEdit" name="display_version">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="1" column="0">
|
||||||
<widget class="QLineEdit" name="display_format">
|
<widget class="QLabel" name="label">
|
||||||
<property name="enabled">
|
<property name="text">
|
||||||
<bool>true</bool>
|
<string>Name</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
</widget>
|
||||||
<bool>true</bool>
|
</item>
|
||||||
</property>
|
<item row="4" column="0">
|
||||||
</widget>
|
<widget class="QLabel" name="label_4">
|
||||||
</item>
|
<property name="text">
|
||||||
<item row="7" column="0">
|
<string>Title ID</string>
|
||||||
<widget class="QLabel" name="label_7">
|
</property>
|
||||||
<property name="text">
|
</widget>
|
||||||
<string>Filename</string>
|
</item>
|
||||||
</property>
|
<item row="4" column="1">
|
||||||
</widget>
|
<widget class="QLineEdit" name="display_title_id">
|
||||||
</item>
|
<property name="enabled">
|
||||||
<item row="1" column="1">
|
<bool>true</bool>
|
||||||
<widget class="QLineEdit" name="display_name">
|
</property>
|
||||||
<property name="enabled">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
</widget>
|
||||||
<bool>true</bool>
|
</item>
|
||||||
</property>
|
<item row="7" column="1">
|
||||||
</widget>
|
<widget class="QLineEdit" name="display_filename">
|
||||||
</item>
|
<property name="enabled">
|
||||||
<item row="2" column="1">
|
<bool>true</bool>
|
||||||
<widget class="QLineEdit" name="display_developer">
|
</property>
|
||||||
<property name="enabled">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
</widget>
|
||||||
<bool>true</bool>
|
</item>
|
||||||
</property>
|
<item row="5" column="1">
|
||||||
</widget>
|
<widget class="QLineEdit" name="display_format">
|
||||||
</item>
|
<property name="enabled">
|
||||||
<item row="5" column="0">
|
<bool>true</bool>
|
||||||
<widget class="QLabel" name="label_5">
|
</property>
|
||||||
<property name="text">
|
<property name="readOnly">
|
||||||
<string>Format</string>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="7" column="0">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_7">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Version</string>
|
<string>Filename</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="1" column="1">
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLineEdit" name="display_name">
|
||||||
<property name="text">
|
<property name="enabled">
|
||||||
<string>Size</string>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="readOnly">
|
||||||
</item>
|
<bool>true</bool>
|
||||||
<item row="2" column="0">
|
</property>
|
||||||
<widget class="QLabel" name="label_2">
|
</widget>
|
||||||
<property name="text">
|
</item>
|
||||||
<string>Developer</string>
|
<item row="2" column="1">
|
||||||
</property>
|
<widget class="QLineEdit" name="display_developer">
|
||||||
</widget>
|
<property name="enabled">
|
||||||
</item>
|
<bool>true</bool>
|
||||||
<item row="8" column="0">
|
</property>
|
||||||
<widget class="QLabel" name="label_build_id">
|
<property name="readOnly">
|
||||||
<property name="text">
|
<bool>true</bool>
|
||||||
<string>Base Build ID</string>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
</widget>
|
</item>
|
||||||
</item>
|
<item row="5" column="0">
|
||||||
<item row="8" column="1">
|
<widget class="QLabel" name="label_5">
|
||||||
<widget class="QLineEdit" name="display_build_id">
|
<property name="text">
|
||||||
<property name="enabled">
|
<string>Format</string>
|
||||||
<bool>true</bool>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
<property name="readOnly">
|
</item>
|
||||||
<bool>true</bool>
|
<item row="3" column="0">
|
||||||
</property>
|
<widget class="QLabel" name="label_3">
|
||||||
</widget>
|
<property name="text">
|
||||||
</item>
|
<string>Version</string>
|
||||||
<item row="9" column="0">
|
</property>
|
||||||
<widget class="QLabel" name="label_update_build_id">
|
</widget>
|
||||||
<property name="text">
|
</item>
|
||||||
<string>Update Build ID</string>
|
<item row="6" column="0">
|
||||||
</property>
|
<widget class="QLabel" name="label_6">
|
||||||
</widget>
|
<property name="text">
|
||||||
</item>
|
<string>Size</string>
|
||||||
<item row="9" column="1">
|
</property>
|
||||||
<widget class="QLineEdit" name="display_update_build_id">
|
</widget>
|
||||||
<property name="enabled">
|
</item>
|
||||||
<bool>true</bool>
|
<item row="2" column="0">
|
||||||
</property>
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="readOnly">
|
<property name="text">
|
||||||
<bool>true</bool>
|
<string>Developer</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item row="8" column="0">
|
||||||
</item>
|
<widget class="QLabel" name="label_build_id">
|
||||||
<item>
|
<property name="text">
|
||||||
<spacer name="verticalSpacer">
|
<string>Base Build ID</string>
|
||||||
<property name="orientation">
|
</property>
|
||||||
<enum>Qt::Vertical</enum>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
<property name="sizeHint" stdset="0">
|
<item row="8" column="1">
|
||||||
<size>
|
<widget class="QLineEdit" name="display_build_id">
|
||||||
<width>20</width>
|
<property name="enabled">
|
||||||
<height>40</height>
|
<bool>true</bool>
|
||||||
</size>
|
</property>
|
||||||
</property>
|
<property name="readOnly">
|
||||||
</spacer>
|
<bool>true</bool>
|
||||||
</item>
|
</property>
|
||||||
</layout>
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
|
<widget class="QLabel" name="label_update_build_id">
|
||||||
|
<property name="text">
|
||||||
|
<string>Update Build ID</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="1">
|
||||||
|
<widget class="QLineEdit" name="display_update_build_id">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
<!-- END OF NEW SCROLL AREA -->
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="VerticalLayout">
|
<layout class="QVBoxLayout" name="VerticalLayout">
|
||||||
@@ -248,6 +290,12 @@
|
|||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>-1</number>
|
<number>-1</number>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
Reference in New Issue
Block a user