2016-02-29 08:52:15 +00:00
|
|
|
// Copyright 2016 Dolphin Emulator Project
|
2021-07-05 01:22:19 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2016-02-29 08:52:15 +00:00
|
|
|
|
|
|
|
#include <QComboBox>
|
|
|
|
#include <QCryptographicHash>
|
2018-05-13 19:43:57 +00:00
|
|
|
#include <QDir>
|
2016-02-29 08:52:15 +00:00
|
|
|
#include <QFormLayout>
|
|
|
|
#include <QGroupBox>
|
|
|
|
#include <QLabel>
|
|
|
|
#include <QLineEdit>
|
|
|
|
#include <QPushButton>
|
|
|
|
#include <QTextEdit>
|
|
|
|
|
2018-05-25 00:41:49 +00:00
|
|
|
#include "Core/ConfigManager.h"
|
2018-05-28 01:48:04 +00:00
|
|
|
|
2016-07-06 18:33:05 +00:00
|
|
|
#include "DiscIO/Blob.h"
|
|
|
|
#include "DiscIO/Enums.h"
|
2021-02-14 14:33:25 +00:00
|
|
|
#include "DiscIO/Volume.h"
|
2018-05-28 01:48:04 +00:00
|
|
|
|
2018-07-06 22:40:15 +00:00
|
|
|
#include "DolphinQt/Config/InfoWidget.h"
|
2021-10-10 02:28:59 +00:00
|
|
|
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
|
2018-07-06 22:40:15 +00:00
|
|
|
#include "DolphinQt/QtUtils/ImageConverter.h"
|
2018-05-28 01:48:04 +00:00
|
|
|
|
2017-12-31 19:33:36 +00:00
|
|
|
#include "UICommon/UICommon.h"
|
2016-02-29 08:52:15 +00:00
|
|
|
|
2017-12-31 19:33:36 +00:00
|
|
|
InfoWidget::InfoWidget(const UICommon::GameFile& game) : m_game(game)
|
2016-02-29 08:52:15 +00:00
|
|
|
{
|
2021-02-14 14:33:25 +00:00
|
|
|
m_volume = DiscIO::CreateVolume(m_game.GetFilePath());
|
|
|
|
|
2016-02-29 08:52:15 +00:00
|
|
|
QVBoxLayout* layout = new QVBoxLayout();
|
2018-03-17 15:07:51 +00:00
|
|
|
|
2020-06-21 18:41:50 +00:00
|
|
|
layout->addWidget(CreateFileDetails());
|
|
|
|
layout->addWidget(CreateGameDetails());
|
2018-05-25 00:20:52 +00:00
|
|
|
|
|
|
|
if (!game.GetLanguages().empty())
|
|
|
|
layout->addWidget(CreateBannerDetails());
|
2018-03-17 15:07:51 +00:00
|
|
|
|
2016-02-29 08:52:15 +00:00
|
|
|
setLayout(layout);
|
|
|
|
}
|
|
|
|
|
2021-02-14 14:33:25 +00:00
|
|
|
InfoWidget::~InfoWidget() = default;
|
|
|
|
|
2020-06-21 18:41:50 +00:00
|
|
|
QGroupBox* InfoWidget::CreateFileDetails()
|
|
|
|
{
|
|
|
|
QGroupBox* group = new QGroupBox(tr("File Details"));
|
|
|
|
QFormLayout* layout = new QFormLayout;
|
|
|
|
|
|
|
|
layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
|
|
|
|
|
|
|
QString path = QDir::toNativeSeparators(QString::fromStdString(m_game.GetFilePath()));
|
|
|
|
layout->addRow(tr("Path:"), CreateValueDisplay(path));
|
|
|
|
|
|
|
|
const std::string file_size = UICommon::FormatSize(m_game.GetFileSize());
|
|
|
|
|
|
|
|
if (!m_game.ShouldShowFileFormatDetails())
|
|
|
|
{
|
|
|
|
layout->addRow(tr("File Size:"), CreateValueDisplay(file_size));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-10-06 11:00:58 +00:00
|
|
|
const QString file_format = QStringLiteral("%1 (%2)")
|
|
|
|
.arg(QString::fromStdString(m_game.GetFileFormatName()))
|
|
|
|
.arg(QString::fromStdString(file_size));
|
2020-06-21 18:41:50 +00:00
|
|
|
layout->addRow(tr("File Format:"), CreateValueDisplay(file_format));
|
|
|
|
|
|
|
|
QString compression = QString::fromStdString(m_game.GetCompressionMethod());
|
|
|
|
if (compression.isEmpty())
|
|
|
|
compression = tr("No Compression");
|
|
|
|
layout->addRow(tr("Compression:"), CreateValueDisplay(compression));
|
|
|
|
|
|
|
|
if (m_game.GetBlockSize() > 0)
|
|
|
|
{
|
|
|
|
const std::string block_size = UICommon::FormatSize(m_game.GetBlockSize(), 0);
|
|
|
|
layout->addRow(tr("Block Size:"), CreateValueDisplay(block_size));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
group->setLayout(layout);
|
|
|
|
return group;
|
|
|
|
}
|
|
|
|
|
|
|
|
QGroupBox* InfoWidget::CreateGameDetails()
|
2016-02-29 08:52:15 +00:00
|
|
|
{
|
2018-05-27 14:27:29 +00:00
|
|
|
const QString UNKNOWN_NAME = tr("Unknown");
|
|
|
|
|
2020-06-21 18:41:50 +00:00
|
|
|
QGroupBox* group = new QGroupBox(tr("Game Details"));
|
2016-02-29 08:52:15 +00:00
|
|
|
QFormLayout* layout = new QFormLayout;
|
|
|
|
|
2018-05-30 15:05:07 +00:00
|
|
|
layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
|
|
|
|
2018-05-27 14:27:29 +00:00
|
|
|
const QString game_name = QString::fromStdString(m_game.GetInternalName());
|
|
|
|
|
|
|
|
bool is_disc_based = m_game.GetPlatform() == DiscIO::Platform::GameCubeDisc ||
|
|
|
|
m_game.GetPlatform() == DiscIO::Platform::WiiDisc;
|
|
|
|
|
2018-03-17 15:07:51 +00:00
|
|
|
QLineEdit* internal_name =
|
2018-05-27 14:27:29 +00:00
|
|
|
CreateValueDisplay(is_disc_based ? tr("%1 (Disc %2, Revision %3)")
|
|
|
|
.arg(game_name.isEmpty() ? UNKNOWN_NAME : game_name)
|
2020-09-23 09:42:22 +00:00
|
|
|
.arg(m_game.GetDiscNumber() + 1)
|
2018-05-27 14:27:29 +00:00
|
|
|
.arg(m_game.GetRevision()) :
|
|
|
|
tr("%1 (Revision %3)")
|
|
|
|
.arg(game_name.isEmpty() ? UNKNOWN_NAME : game_name)
|
|
|
|
.arg(m_game.GetRevision()));
|
2017-12-31 19:33:36 +00:00
|
|
|
|
|
|
|
QString game_id_string = QString::fromStdString(m_game.GetGameID());
|
2018-05-27 14:27:29 +00:00
|
|
|
|
2018-03-07 16:31:04 +00:00
|
|
|
if (const u64 title_id = m_game.GetTitleID())
|
|
|
|
game_id_string += QStringLiteral(" (%1)").arg(title_id, 16, 16, QLatin1Char('0'));
|
2018-05-27 14:27:29 +00:00
|
|
|
|
2018-03-07 16:31:04 +00:00
|
|
|
QLineEdit* game_id = CreateValueDisplay(game_id_string);
|
2017-12-31 19:33:36 +00:00
|
|
|
|
|
|
|
QLineEdit* country = CreateValueDisplay(DiscIO::GetName(m_game.GetCountry(), true));
|
2018-05-27 14:27:29 +00:00
|
|
|
|
2019-09-25 09:36:45 +00:00
|
|
|
const std::string game_maker = m_game.GetMaker(UICommon::GameFile::Variant::LongAndNotCustom);
|
2018-05-27 14:27:29 +00:00
|
|
|
|
|
|
|
QLineEdit* maker =
|
2018-06-05 18:25:15 +00:00
|
|
|
CreateValueDisplay((game_maker.empty() ? UNKNOWN_NAME.toStdString() : game_maker) + " (" +
|
2018-05-27 14:27:29 +00:00
|
|
|
m_game.GetMakerID() + ")");
|
2016-02-29 08:52:15 +00:00
|
|
|
|
2018-03-17 15:07:51 +00:00
|
|
|
layout->addRow(tr("Name:"), internal_name);
|
2016-02-29 08:52:15 +00:00
|
|
|
layout->addRow(tr("Game ID:"), game_id);
|
|
|
|
layout->addRow(tr("Country:"), country);
|
|
|
|
layout->addRow(tr("Maker:"), maker);
|
2018-05-25 00:41:49 +00:00
|
|
|
|
|
|
|
if (!m_game.GetApploaderDate().empty())
|
|
|
|
layout->addRow(tr("Apploader Date:"), CreateValueDisplay(m_game.GetApploaderDate()));
|
|
|
|
|
2021-02-14 14:33:25 +00:00
|
|
|
if (m_volume)
|
|
|
|
{
|
|
|
|
const DiscIO::Partition partition = m_volume->GetGamePartition();
|
|
|
|
const IOS::ES::TMDReader& tmd = m_volume->GetTMD(partition);
|
|
|
|
if (tmd.IsValid())
|
|
|
|
{
|
|
|
|
const auto ios = fmt::format("IOS{}", static_cast<u32>(tmd.GetIOSId()));
|
|
|
|
layout->addRow(tr("IOS Version:"), CreateValueDisplay(ios));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-29 08:52:15 +00:00
|
|
|
group->setLayout(layout);
|
|
|
|
return group;
|
|
|
|
}
|
|
|
|
|
|
|
|
QGroupBox* InfoWidget::CreateBannerDetails()
|
|
|
|
{
|
2017-07-23 12:53:53 +00:00
|
|
|
QGroupBox* group = new QGroupBox(tr("Banner Details"));
|
2016-02-29 08:52:15 +00:00
|
|
|
QFormLayout* layout = new QFormLayout;
|
|
|
|
|
2018-05-30 15:05:07 +00:00
|
|
|
layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
|
|
|
|
2016-02-29 08:52:15 +00:00
|
|
|
CreateLanguageSelector();
|
|
|
|
layout->addRow(tr("Show Language:"), m_language_selector);
|
2019-03-24 01:10:09 +00:00
|
|
|
|
2018-03-31 12:04:13 +00:00
|
|
|
if (m_game.GetPlatform() == DiscIO::Platform::GameCubeDisc)
|
2016-02-29 08:52:15 +00:00
|
|
|
{
|
2019-03-24 01:10:09 +00:00
|
|
|
layout->addRow(tr("Name:"), m_name = CreateValueDisplay());
|
|
|
|
layout->addRow(tr("Maker:"), m_maker = CreateValueDisplay());
|
|
|
|
layout->addRow(tr("Description:"), m_description = new QTextEdit());
|
|
|
|
m_description->setReadOnly(true);
|
2016-02-29 08:52:15 +00:00
|
|
|
}
|
2017-12-31 19:33:36 +00:00
|
|
|
else if (DiscIO::IsWii(m_game.GetPlatform()))
|
2016-02-29 08:52:15 +00:00
|
|
|
{
|
2019-03-24 01:10:09 +00:00
|
|
|
layout->addRow(tr("Name:"), m_name = CreateValueDisplay());
|
2016-02-29 08:52:15 +00:00
|
|
|
}
|
2017-08-22 00:56:51 +00:00
|
|
|
|
2019-03-24 01:10:09 +00:00
|
|
|
ChangeLanguage();
|
|
|
|
|
2017-12-31 19:33:36 +00:00
|
|
|
QPixmap banner = ToQPixmap(m_game.GetBannerImage());
|
|
|
|
if (!banner.isNull())
|
|
|
|
layout->addRow(tr("Banner:"), CreateBannerGraphic(banner));
|
2016-02-29 08:52:15 +00:00
|
|
|
|
|
|
|
group->setLayout(layout);
|
|
|
|
return group;
|
|
|
|
}
|
|
|
|
|
2017-12-31 19:33:36 +00:00
|
|
|
QWidget* InfoWidget::CreateBannerGraphic(const QPixmap& image)
|
2016-02-29 08:52:15 +00:00
|
|
|
{
|
|
|
|
QWidget* widget = new QWidget();
|
|
|
|
QHBoxLayout* layout = new QHBoxLayout();
|
|
|
|
|
|
|
|
QLabel* banner = new QLabel();
|
2017-12-31 19:33:36 +00:00
|
|
|
banner->setPixmap(image);
|
2016-02-29 08:52:15 +00:00
|
|
|
QPushButton* save = new QPushButton(tr("Save as..."));
|
|
|
|
connect(save, &QPushButton::clicked, this, &InfoWidget::SaveBanner);
|
|
|
|
|
|
|
|
layout->addWidget(banner);
|
|
|
|
layout->addWidget(save);
|
|
|
|
widget->setLayout(layout);
|
|
|
|
return widget;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InfoWidget::SaveBanner()
|
|
|
|
{
|
2021-10-10 02:28:59 +00:00
|
|
|
QString path = DolphinFileDialog::getSaveFileName(this, tr("Select a File"), QDir::currentPath(),
|
|
|
|
tr("PNG image file (*.png);; All Files (*)"));
|
2017-12-31 19:33:36 +00:00
|
|
|
ToQPixmap(m_game.GetBannerImage()).save(path, "PNG");
|
2016-02-29 08:52:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QLineEdit* InfoWidget::CreateValueDisplay(const QString& value)
|
|
|
|
{
|
2019-03-17 17:51:50 +00:00
|
|
|
QLineEdit* value_display = new QLineEdit(value, this);
|
2016-02-29 08:52:15 +00:00
|
|
|
value_display->setReadOnly(true);
|
|
|
|
value_display->setCursorPosition(0);
|
|
|
|
return value_display;
|
|
|
|
}
|
|
|
|
|
2017-12-31 19:33:36 +00:00
|
|
|
QLineEdit* InfoWidget::CreateValueDisplay(const std::string& value)
|
|
|
|
{
|
|
|
|
return CreateValueDisplay(QString::fromStdString(value));
|
|
|
|
}
|
|
|
|
|
2016-02-29 08:52:15 +00:00
|
|
|
void InfoWidget::CreateLanguageSelector()
|
|
|
|
{
|
2018-05-26 12:06:51 +00:00
|
|
|
const bool is_wii = DiscIO::IsWii(m_game.GetPlatform());
|
|
|
|
const DiscIO::Language preferred_language = SConfig::GetInstance().GetCurrentLanguage(is_wii);
|
|
|
|
|
2016-02-29 08:52:15 +00:00
|
|
|
m_language_selector = new QComboBox();
|
2017-12-31 19:33:36 +00:00
|
|
|
for (DiscIO::Language language : m_game.GetLanguages())
|
2016-02-29 08:52:15 +00:00
|
|
|
{
|
2017-12-31 19:33:36 +00:00
|
|
|
m_language_selector->addItem(QString::fromStdString(DiscIO::GetName(language, true)),
|
|
|
|
static_cast<int>(language));
|
2018-05-26 12:06:51 +00:00
|
|
|
if (language == preferred_language)
|
|
|
|
m_language_selector->setCurrentIndex(m_language_selector->count() - 1);
|
2016-02-29 08:52:15 +00:00
|
|
|
}
|
|
|
|
if (m_language_selector->count() == 1)
|
|
|
|
m_language_selector->setDisabled(true);
|
2018-05-25 00:20:52 +00:00
|
|
|
|
2019-07-30 13:35:46 +00:00
|
|
|
connect(m_language_selector, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
2017-06-30 09:24:09 +00:00
|
|
|
&InfoWidget::ChangeLanguage);
|
2016-02-29 08:52:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void InfoWidget::ChangeLanguage()
|
|
|
|
{
|
2016-07-06 18:33:05 +00:00
|
|
|
DiscIO::Language language =
|
|
|
|
static_cast<DiscIO::Language>(m_language_selector->currentData().toInt());
|
2019-03-24 01:10:09 +00:00
|
|
|
|
|
|
|
if (m_name)
|
|
|
|
m_name->setText(QString::fromStdString(m_game.GetLongName(language)));
|
|
|
|
|
|
|
|
if (m_maker)
|
|
|
|
m_maker->setText(QString::fromStdString(m_game.GetLongMaker(language)));
|
|
|
|
|
|
|
|
if (m_description)
|
|
|
|
m_description->setText(QString::fromStdString(m_game.GetDescription(language)));
|
2016-02-29 08:52:15 +00:00
|
|
|
}
|