mirror of
https://github.com/shadps4-emu/shadps4-qtlauncher.git
synced 2026-01-31 01:05:16 +01:00
Version Manager fixes (#177)
* Version Manager fixes * ordering * ordering + * fix issue 172 * Remove the message, because there are two messages * Check if version name starts with 'Pre-release' instead of exact match
This commit is contained in:
@@ -100,6 +100,11 @@ void SaveVersionList(std::vector<Version> const& versions, std::filesystem::path
|
||||
|
||||
void AddNewVersion(Version const& v, std::filesystem::path const& path) {
|
||||
auto versions = GetVersionList(path);
|
||||
auto it = std::remove_if(versions.begin(), versions.end(),
|
||||
[&](const Version& existing) { return existing.name == v.name; });
|
||||
if (it != versions.end())
|
||||
versions.erase(it, versions.end());
|
||||
|
||||
versions.push_back(v);
|
||||
SaveVersionList(versions, path);
|
||||
}
|
||||
|
||||
@@ -413,9 +413,9 @@ figure_creator_dialog::figure_creator_dialog(QWidget* parent, u8 slot) : QDialog
|
||||
QHBoxLayout* hbox_filters = new QHBoxLayout();
|
||||
QLabel* filter_label = new QLabel(tr("Filter by Series:"));
|
||||
QPushButton* btn_all = new QPushButton(tr("All"));
|
||||
QPushButton* btn_series1 = new QPushButton(tr("1.0"));
|
||||
QPushButton* btn_series2 = new QPushButton(tr("2.0"));
|
||||
QPushButton* btn_series3 = new QPushButton(tr("3.0"));
|
||||
QPushButton* btn_series1 = new QPushButton("1.0");
|
||||
QPushButton* btn_series2 = new QPushButton("2.0");
|
||||
QPushButton* btn_series3 = new QPushButton("3.0");
|
||||
|
||||
// Style the active filter button
|
||||
btn_all->setCheckable(true);
|
||||
|
||||
@@ -1426,25 +1426,72 @@ void MainWindow::RestartEmulator() {
|
||||
|
||||
void MainWindow::LoadVersionComboBox() {
|
||||
ui->versionComboBox->clear();
|
||||
ui->versionComboBox->addItem(tr("None"));
|
||||
ui->versionComboBox->setCurrentIndex(0);
|
||||
ui->versionComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
|
||||
QString savedVersionPath = m_gui_settings->GetValue(gui::vm_versionSelected).toString();
|
||||
auto versions = VersionManager::GetVersionList();
|
||||
|
||||
auto const& versions = VersionManager::GetVersionList();
|
||||
for (auto const& v : versions) {
|
||||
std::sort(versions.begin(), versions.end(), [](const auto& a, const auto& b) {
|
||||
auto getOrder = [](int type) {
|
||||
switch (type) {
|
||||
case 1: // Pre-release
|
||||
return 0;
|
||||
case 0: // Release
|
||||
return 1;
|
||||
case 2: // Local
|
||||
return 2;
|
||||
default:
|
||||
return 3;
|
||||
}
|
||||
};
|
||||
|
||||
int orderA = getOrder(static_cast<int>(a.type));
|
||||
int orderB = getOrder(static_cast<int>(b.type));
|
||||
|
||||
if (orderA != orderB)
|
||||
return orderA < orderB;
|
||||
|
||||
if (a.type == VersionManager::VersionType::Release) {
|
||||
static QRegularExpression versionRegex("^v\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)$");
|
||||
QRegularExpressionMatch matchA = versionRegex.match(QString::fromStdString(a.name));
|
||||
QRegularExpressionMatch matchB = versionRegex.match(QString::fromStdString(b.name));
|
||||
|
||||
if (matchA.hasMatch() && matchB.hasMatch()) {
|
||||
int majorA = matchA.captured(1).toInt();
|
||||
int minorA = matchA.captured(2).toInt();
|
||||
int patchA = matchA.captured(3).toInt();
|
||||
int majorB = matchB.captured(1).toInt();
|
||||
int minorB = matchB.captured(2).toInt();
|
||||
int patchB = matchB.captured(3).toInt();
|
||||
|
||||
if (majorA != majorB)
|
||||
return majorA > majorB;
|
||||
if (minorA != minorB)
|
||||
return minorA > minorB;
|
||||
return patchA > patchB;
|
||||
}
|
||||
}
|
||||
|
||||
return QString::fromStdString(a.name).compare(QString::fromStdString(b.name),
|
||||
Qt::CaseInsensitive) < 0;
|
||||
});
|
||||
|
||||
if (versions.empty()) {
|
||||
ui->versionComboBox->addItem(tr("None"));
|
||||
ui->versionComboBox->setCurrentIndex(0);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& v : versions) {
|
||||
ui->versionComboBox->addItem(QString::fromStdString(v.name),
|
||||
QString::fromStdString(v.path));
|
||||
}
|
||||
|
||||
int selectedIndex = ui->versionComboBox->findData(savedVersionPath);
|
||||
|
||||
if (selectedIndex >= 0) {
|
||||
ui->versionComboBox->setCurrentIndex(selectedIndex);
|
||||
} else if (ui->versionComboBox->count() > 0) {
|
||||
} else {
|
||||
ui->versionComboBox->setCurrentIndex(0);
|
||||
selectedIndex = 0;
|
||||
}
|
||||
|
||||
connect(ui->versionComboBox, QOverload<int>::of(&QComboBox::activated), this,
|
||||
@@ -1453,6 +1500,5 @@ void MainWindow::LoadVersionComboBox() {
|
||||
m_gui_settings->SetValue(gui::vm_versionSelected, fullPath);
|
||||
});
|
||||
|
||||
ui->versionComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
ui->versionComboBox->adjustSize();
|
||||
}
|
||||
|
||||
@@ -94,11 +94,11 @@ VersionDialog::VersionDialog(std::shared_ptr<gui_settings> gui_settings, QWidget
|
||||
exePath = QFileDialog::getOpenFileName(this, tr("Select executable"), QDir::rootPath(),
|
||||
tr("Executable (*.exe)"));
|
||||
#elif defined(Q_OS_LINUX)
|
||||
exePath = QFileDialog::getOpenFileName(this, tr("Select executable"), QDir::rootPath(),
|
||||
"Executable (*)");
|
||||
exePath = QFileDialog::getOpenFileName(this, tr("Select executable"), QDir::rootPath(),
|
||||
"Executable (*)");
|
||||
#elif defined(Q_OS_MACOS)
|
||||
exePath = QFileDialog::getOpenFileName(this, tr("Select executable"), QDir::rootPath(),
|
||||
"Executable (*.*)");
|
||||
exePath = QFileDialog::getOpenFileName(this, tr("Select executable"), QDir::rootPath(),
|
||||
"Executable (*.*)");
|
||||
#endif
|
||||
|
||||
if (exePath.isEmpty())
|
||||
@@ -114,6 +114,15 @@ VersionDialog::VersionDialog(std::shared_ptr<gui_settings> gui_settings, QWidget
|
||||
|
||||
version_name = version_name.trimmed();
|
||||
|
||||
if (version_name.startsWith("Pre-release", Qt::CaseInsensitive) ||
|
||||
version_name.startsWith("Pre-release-shadPS4", Qt::CaseInsensitive)) {
|
||||
QMessageBox::warning(this, tr("Error"),
|
||||
// clang-format off
|
||||
tr("It is not possible to create a version with a name that starts with:\n'Pre-release' or 'Pre-release-shadPS4'."));
|
||||
// clang-format on
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::find_if(version_list.cbegin(), version_list.cend(), [version_name](auto i) {
|
||||
return i.name == version_name.toStdString();
|
||||
}) != version_list.cend()) {
|
||||
@@ -124,8 +133,8 @@ VersionDialog::VersionDialog(std::shared_ptr<gui_settings> gui_settings, QWidget
|
||||
VersionManager::Version new_version = {
|
||||
.name = version_name.toStdString(),
|
||||
.path = exePath.toStdString(),
|
||||
.date = QDateTime::currentDateTime().toString("yyyy.MM.dd. HH:mm").toStdString(),
|
||||
.codename = "",
|
||||
.date = QDateTime::currentDateTime().toString("yyyy-MM-dd").toStdString(),
|
||||
.codename = tr("Local").toStdString(),
|
||||
.type = VersionManager::VersionType::Custom,
|
||||
};
|
||||
VersionManager::AddNewVersion(new_version);
|
||||
@@ -144,21 +153,63 @@ VersionDialog::VersionDialog(std::shared_ptr<gui_settings> gui_settings, QWidget
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the actual path of the invisible column folder
|
||||
QString versionName = selectedItem->text(1);
|
||||
QString fullPath = selectedItem->text(4);
|
||||
|
||||
if (fullPath.isEmpty()) {
|
||||
QMessageBox::critical(this, tr("Error"), tr("Failed to determine the folder path."));
|
||||
return;
|
||||
}
|
||||
auto reply = QMessageBox::question(this, tr("Delete version"),
|
||||
tr("Do you want to delete the version") +
|
||||
QString(" \"%1\" ?").arg(selectedItem->text(1)),
|
||||
QString(" \"%1\" ?").arg(versionName),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (reply == QMessageBox::Yes) {
|
||||
// not removing any files, as that might be a problem with local ones
|
||||
VersionManager::RemoveVersion(selectedItem->text(1).toStdString());
|
||||
LoadInstalledList();
|
||||
if (reply == QMessageBox::No)
|
||||
return;
|
||||
|
||||
// Check if it is of type Local (type == 2)
|
||||
auto versions = VersionManager::GetVersionList({});
|
||||
int versionType = 2;
|
||||
for (const auto& v : versions) {
|
||||
if (v.name == versionName.toStdString()) {
|
||||
versionType = static_cast<int>(v.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (versionType == 2) {
|
||||
VersionManager::RemoveVersion(versionName.toStdString());
|
||||
LoadInstalledList();
|
||||
return;
|
||||
}
|
||||
|
||||
QFileInfo info(fullPath);
|
||||
QString folderPath;
|
||||
if (info.exists() && info.isDir()) {
|
||||
folderPath = info.absoluteFilePath();
|
||||
} else {
|
||||
folderPath = info.absolutePath();
|
||||
}
|
||||
|
||||
if (folderPath.isEmpty()) {
|
||||
QMessageBox::critical(this, tr("Error"),
|
||||
tr("Failed to determine the folder to remove.") +
|
||||
QString("\n \"%1\"").arg(fullPath));
|
||||
return;
|
||||
}
|
||||
|
||||
QDir dirToRemove(folderPath);
|
||||
if (dirToRemove.exists()) {
|
||||
if (!dirToRemove.removeRecursively()) {
|
||||
QMessageBox::critical(this, tr("Error"),
|
||||
tr("Failed to delete folder.") +
|
||||
QString("\n \"%1\"").arg(folderPath));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
VersionManager::RemoveVersion(versionName.toStdString());
|
||||
LoadInstalledList();
|
||||
});
|
||||
|
||||
connect(ui->checkVersionDownloadButton, &QPushButton::clicked, this,
|
||||
@@ -309,6 +360,7 @@ void VersionDialog::DownloadListVersion() {
|
||||
}
|
||||
|
||||
void VersionDialog::InstallSelectedVersion() {
|
||||
disconnect(ui->downloadTreeWidget, &QTreeWidget::itemClicked, nullptr, nullptr);
|
||||
connect(
|
||||
ui->downloadTreeWidget, &QTreeWidget::itemClicked, this,
|
||||
[this](QTreeWidgetItem* item, int) {
|
||||
@@ -530,13 +582,25 @@ tr("First you need to choose a location to save the versions in\n'Path to save v
|
||||
this, tr("Confirm Download"),
|
||||
tr("Version %1 has been downloaded and selected.")
|
||||
.arg(versionName));
|
||||
|
||||
bool is_release = !versionName.contains("Pre-release");
|
||||
auto release_name = release["name"].toString();
|
||||
QString code_name = "";
|
||||
static constexpr QStringView marker = u" - codename ";
|
||||
int idx = release_name.indexOf(u" - codename ");
|
||||
if (idx != -1) {
|
||||
code_name = release_name.mid(idx + marker.size());
|
||||
|
||||
if (is_release) {
|
||||
static constexpr QStringView marker = u" - codename ";
|
||||
int idx = release_name.indexOf(marker);
|
||||
if (idx != -1)
|
||||
code_name = release_name.mid(idx + marker.size());
|
||||
} else {
|
||||
QRegularExpression re("-([a-fA-F0-9]{7,})$");
|
||||
QRegularExpressionMatch match = re.match(folderName);
|
||||
if (match.hasMatch()) {
|
||||
QString fullHash = match.captured(1);
|
||||
code_name = fullHash.left(7);
|
||||
} else {
|
||||
code_name = "unknown";
|
||||
}
|
||||
}
|
||||
std::filesystem::path exe_path =
|
||||
Common::FS::PathFromQString(executablePath);
|
||||
@@ -551,8 +615,9 @@ tr("First you need to choose a location to save the versions in\n'Path to save v
|
||||
.type = is_release ? VersionManager::VersionType::Release
|
||||
: VersionManager::VersionType::Nightly,
|
||||
};
|
||||
m_gui_settings->SetValue(gui::vm_versionSelected,
|
||||
QString(exe_path.c_str()));
|
||||
m_gui_settings->SetValue(
|
||||
gui::vm_versionSelected,
|
||||
QString::fromStdString(new_version.path));
|
||||
VersionManager::AddNewVersion(new_version);
|
||||
LoadInstalledList();
|
||||
});
|
||||
@@ -570,14 +635,59 @@ tr("First you need to choose a location to save the versions in\n'Path to save v
|
||||
void VersionDialog::LoadInstalledList() {
|
||||
const auto path = Common::FS::GetUserPath(Common::FS::PathType::LauncherDir) / "versions.json";
|
||||
auto versions = VersionManager::GetVersionList(path);
|
||||
auto const& selected_version =
|
||||
const auto& selected_version =
|
||||
m_gui_settings->GetValue(gui::vm_versionSelected).toString().toStdString();
|
||||
|
||||
std::sort(versions.begin(), versions.end(), [](const auto& a, const auto& b) {
|
||||
auto getOrder = [](int type) {
|
||||
switch (type) {
|
||||
case 1: // Pre-release
|
||||
return 0;
|
||||
case 0: // Release
|
||||
return 1;
|
||||
case 2: // Local
|
||||
return 2;
|
||||
default:
|
||||
return 3;
|
||||
}
|
||||
};
|
||||
|
||||
int orderA = getOrder(static_cast<int>(a.type));
|
||||
int orderB = getOrder(static_cast<int>(b.type));
|
||||
|
||||
if (orderA != orderB)
|
||||
return orderA < orderB;
|
||||
|
||||
if (a.type == VersionManager::VersionType::Release) {
|
||||
static QRegularExpression versionRegex("^v\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)$");
|
||||
QRegularExpressionMatch matchA = versionRegex.match(QString::fromStdString(a.name));
|
||||
QRegularExpressionMatch matchB = versionRegex.match(QString::fromStdString(b.name));
|
||||
|
||||
if (matchA.hasMatch() && matchB.hasMatch()) {
|
||||
int majorA = matchA.captured(1).toInt();
|
||||
int minorA = matchA.captured(2).toInt();
|
||||
int patchA = matchA.captured(3).toInt();
|
||||
int majorB = matchB.captured(1).toInt();
|
||||
int minorB = matchB.captured(2).toInt();
|
||||
int patchB = matchB.captured(3).toInt();
|
||||
|
||||
if (majorA != majorB)
|
||||
return majorA > majorB;
|
||||
if (minorA != minorB)
|
||||
return minorA > minorB;
|
||||
return patchA > patchB;
|
||||
}
|
||||
}
|
||||
|
||||
return QString::fromStdString(a.name).compare(QString::fromStdString(b.name),
|
||||
Qt::CaseInsensitive) < 0;
|
||||
});
|
||||
|
||||
ui->installedTreeWidget->clear();
|
||||
ui->installedTreeWidget->setColumnCount(5);
|
||||
ui->installedTreeWidget->setColumnHidden(4, true);
|
||||
|
||||
for (auto const& v : versions) {
|
||||
for (const auto& v : versions) {
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(ui->installedTreeWidget);
|
||||
item->setText(1, QString::fromStdString(v.name));
|
||||
item->setText(2, QString::fromStdString(v.codename));
|
||||
@@ -721,16 +831,19 @@ void VersionDialog::checkUpdatePre(const bool showMessage) {
|
||||
}
|
||||
|
||||
if (localHash.isEmpty()) {
|
||||
QMessageBox::StandardButton reply =
|
||||
QMessageBox::question(this, tr("No pre-release found"),
|
||||
// clang-format off
|
||||
tr("You don't have any pre-release installed yet.\nWould you like to download it now?"),
|
||||
// clang-format on
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (reply == QMessageBox::Yes) {
|
||||
installPreReleaseByTag(latestTag);
|
||||
auto* tree = ui->downloadTreeWidget;
|
||||
int topCount = tree->topLevelItemCount();
|
||||
|
||||
for (int i = 0; i < topCount; ++i) {
|
||||
QTreeWidgetItem* item = tree->topLevelItem(i);
|
||||
if (item && item->text(0).contains("Pre-release", Qt::CaseInsensitive)) {
|
||||
tree->setCurrentItem(item);
|
||||
tree->scrollToItem(item);
|
||||
tree->setFocus();
|
||||
emit tree->itemClicked(item, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (latestHash == localHash) {
|
||||
@@ -748,6 +861,9 @@ void VersionDialog::checkUpdatePre(const bool showMessage) {
|
||||
|
||||
void VersionDialog::showPreReleaseUpdateDialog(const QString& localHash, const QString& latestHash,
|
||||
const QString& latestTag) {
|
||||
if (localHash == "") {
|
||||
return;
|
||||
}
|
||||
QDialog dialog(this);
|
||||
dialog.setWindowTitle(tr("Auto Updater - Emulator"));
|
||||
|
||||
@@ -1061,13 +1177,22 @@ void VersionDialog::showDownloadDialog(const QString& tagName, const QString& do
|
||||
return;
|
||||
}
|
||||
|
||||
QString codename;
|
||||
QRegularExpression re("-([a-fA-F0-9]{7,})$");
|
||||
QRegularExpressionMatch match = re.match(tagName);
|
||||
if (match.hasMatch()) {
|
||||
QString fullHash = match.captured(1);
|
||||
codename = fullHash.left(7);
|
||||
} else {
|
||||
codename = "unknown";
|
||||
}
|
||||
|
||||
auto const exe = m_gui_settings->GetVersionExecutablePath(destFolder);
|
||||
VersionManager::Version new_version = {
|
||||
.name = "Pre-release",
|
||||
.path = exe.toStdString(),
|
||||
.date =
|
||||
QDateTime::currentDateTime().toString("yyyy.MM.dd. HH:mm").toStdString(),
|
||||
.codename = "",
|
||||
.date = QDateTime::currentDateTime().toString("yyyy-MM-dd").toStdString(),
|
||||
.codename = codename.toStdString(),
|
||||
.type = VersionManager::VersionType::Nightly,
|
||||
};
|
||||
VersionManager::UpdatePrerelease(new_version);
|
||||
|
||||
Reference in New Issue
Block a user