Merge branch 'develop' of https://github.com/PrismLauncher/PrismLauncher into feat/launcher-updater
This commit is contained in:
@ -363,7 +363,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi
|
||||
// Shouldn't have to use lambdas here like this, but if I don't, the compiler throws a fit.
|
||||
// Template hell sucks...
|
||||
connect(APPLICATION->accounts().get(), &AccountList::defaultAccountChanged, [this] { defaultAccountChanged(); });
|
||||
connect(APPLICATION->accounts().get(), &AccountList::listChanged, [this] { repopulateAccountsMenu(); });
|
||||
connect(APPLICATION->accounts().get(), &AccountList::listChanged, [this] { defaultAccountChanged(); });
|
||||
|
||||
// Show initial account
|
||||
defaultAccountChanged();
|
||||
@ -872,7 +872,7 @@ void MainWindow::finalizeInstance(InstancePtr inst)
|
||||
} else {
|
||||
CustomMessageBox::selectable(this, tr("Error"),
|
||||
tr("The launcher cannot download Minecraft or update instances unless you have at least "
|
||||
"one account added.\nPlease add your Microsoft or Mojang account."),
|
||||
"one account added.\nPlease add a Microsoft account."),
|
||||
QMessageBox::Warning)
|
||||
->show();
|
||||
}
|
||||
|
@ -44,7 +44,8 @@
|
||||
BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList<BlockedMod>& mods)
|
||||
: QDialog(parent), ui(new Ui::BlockedModsDialog), m_mods(mods)
|
||||
{
|
||||
m_hashing_task = shared_qobject_ptr<ConcurrentTask>(new ConcurrentTask(this, "MakeHashesTask", 10));
|
||||
m_hashing_task = shared_qobject_ptr<ConcurrentTask>(
|
||||
new ConcurrentTask(this, "MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()));
|
||||
connect(m_hashing_task.get(), &Task::finished, this, &BlockedModsDialog::hashTaskFinished);
|
||||
|
||||
ui->setupUi(this);
|
||||
|
@ -1,115 +0,0 @@
|
||||
/* Copyright 2013-2021 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "LoginDialog.h"
|
||||
#include "ui_LoginDialog.h"
|
||||
|
||||
#include "minecraft/auth/AccountTask.h"
|
||||
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
LoginDialog::LoginDialog(QWidget* parent) : QDialog(parent), ui(new Ui::LoginDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->progressBar->setVisible(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
LoginDialog::~LoginDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
// Stage 1: User interaction
|
||||
void LoginDialog::accept()
|
||||
{
|
||||
setUserInputsEnabled(false);
|
||||
ui->progressBar->setVisible(true);
|
||||
|
||||
// Setup the login task and start it
|
||||
m_account = MinecraftAccount::createFromUsername(ui->userTextBox->text());
|
||||
m_loginTask = m_account->login(ui->passTextBox->text());
|
||||
connect(m_loginTask.get(), &Task::failed, this, &LoginDialog::onTaskFailed);
|
||||
connect(m_loginTask.get(), &Task::succeeded, this, &LoginDialog::onTaskSucceeded);
|
||||
connect(m_loginTask.get(), &Task::status, this, &LoginDialog::onTaskStatus);
|
||||
connect(m_loginTask.get(), &Task::progress, this, &LoginDialog::onTaskProgress);
|
||||
m_loginTask->start();
|
||||
}
|
||||
|
||||
void LoginDialog::setUserInputsEnabled(bool enable)
|
||||
{
|
||||
ui->userTextBox->setEnabled(enable);
|
||||
ui->passTextBox->setEnabled(enable);
|
||||
ui->buttonBox->setEnabled(enable);
|
||||
}
|
||||
|
||||
// Enable the OK button only when both textboxes contain something.
|
||||
void LoginDialog::on_userTextBox_textEdited(const QString& newText)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!newText.isEmpty() && !ui->passTextBox->text().isEmpty());
|
||||
}
|
||||
void LoginDialog::on_passTextBox_textEdited(const QString& newText)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty());
|
||||
}
|
||||
|
||||
void LoginDialog::onTaskFailed(const QString& reason)
|
||||
{
|
||||
// Set message
|
||||
auto lines = reason.split('\n');
|
||||
QString processed;
|
||||
for (auto line : lines) {
|
||||
if (line.size()) {
|
||||
processed += "<font color='red'>" + line + "</font><br />";
|
||||
} else {
|
||||
processed += "<br />";
|
||||
}
|
||||
}
|
||||
ui->label->setText(processed);
|
||||
|
||||
// Re-enable user-interaction
|
||||
setUserInputsEnabled(true);
|
||||
ui->progressBar->setVisible(false);
|
||||
}
|
||||
|
||||
void LoginDialog::onTaskSucceeded()
|
||||
{
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void LoginDialog::onTaskStatus(const QString& status)
|
||||
{
|
||||
ui->label->setText(status);
|
||||
}
|
||||
|
||||
void LoginDialog::onTaskProgress(qint64 current, qint64 total)
|
||||
{
|
||||
ui->progressBar->setMaximum(total);
|
||||
ui->progressBar->setValue(current);
|
||||
}
|
||||
|
||||
// Public interface
|
||||
MinecraftAccountPtr LoginDialog::newAccount(QWidget* parent, QString msg)
|
||||
{
|
||||
LoginDialog dlg(parent);
|
||||
dlg.ui->label->setText(msg);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
return dlg.m_account;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/* Copyright 2013-2021 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QEventLoop>
|
||||
#include <QtWidgets/QDialog>
|
||||
|
||||
#include "minecraft/auth/MinecraftAccount.h"
|
||||
#include "tasks/Task.h"
|
||||
|
||||
namespace Ui {
|
||||
class LoginDialog;
|
||||
}
|
||||
|
||||
class LoginDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
~LoginDialog();
|
||||
|
||||
static MinecraftAccountPtr newAccount(QWidget* parent, QString message);
|
||||
|
||||
private:
|
||||
explicit LoginDialog(QWidget* parent = 0);
|
||||
|
||||
void setUserInputsEnabled(bool enable);
|
||||
|
||||
protected slots:
|
||||
void accept();
|
||||
|
||||
void onTaskFailed(const QString& reason);
|
||||
void onTaskSucceeded();
|
||||
void onTaskStatus(const QString& status);
|
||||
void onTaskProgress(qint64 current, qint64 total);
|
||||
|
||||
void on_userTextBox_textEdited(const QString& newText);
|
||||
void on_passTextBox_textEdited(const QString& newText);
|
||||
|
||||
private:
|
||||
Ui::LoginDialog* ui;
|
||||
MinecraftAccountPtr m_account;
|
||||
Task::Ptr m_loginTask;
|
||||
};
|
@ -1,77 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LoginDialog</class>
|
||||
<widget class="QDialog" name="LoginDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>421</width>
|
||||
<height>198</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Add Account</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string notr="true">Message label placeholder.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="userTextBox">
|
||||
<property name="placeholderText">
|
||||
<string>Email</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="passTextBox">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -3,6 +3,9 @@
|
||||
#include "CustomMessageBox.h"
|
||||
#include "ProgressDialog.h"
|
||||
#include "ScrollMessageBox.h"
|
||||
#include "minecraft/mod/tasks/GetModDependenciesTask.h"
|
||||
#include "modplatform/ModIndex.h"
|
||||
#include "modplatform/flame/FlameAPI.h"
|
||||
#include "ui_ReviewMessageBox.h"
|
||||
|
||||
#include "Markdown.h"
|
||||
@ -41,7 +44,8 @@ ModUpdateDialog::ModUpdateDialog(QWidget* parent,
|
||||
, m_parent(parent)
|
||||
, m_mod_model(mods)
|
||||
, m_candidates(search_for)
|
||||
, m_second_try_metadata(new ConcurrentTask())
|
||||
, m_second_try_metadata(
|
||||
new ConcurrentTask(nullptr, "Second Metadata Search", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()))
|
||||
, m_instance(instance)
|
||||
{
|
||||
ReviewMessageBox::setGeometry(0, 0, 800, 600);
|
||||
@ -124,6 +128,8 @@ void ModUpdateDialog::checkCandidates()
|
||||
return;
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<GetModDependenciesTask::PackDependency>> selectedVers;
|
||||
|
||||
// Add found updates for Modrinth
|
||||
if (m_modrinth_check_task) {
|
||||
auto modrinth_updates = m_modrinth_check_task->getUpdatable();
|
||||
@ -133,6 +139,7 @@ void ModUpdateDialog::checkCandidates()
|
||||
appendMod(updatable);
|
||||
m_tasks.insert(updatable.name, updatable.download);
|
||||
}
|
||||
selectedVers.append(m_modrinth_check_task->getDependencies());
|
||||
}
|
||||
|
||||
// Add found updated for Flame
|
||||
@ -144,6 +151,7 @@ void ModUpdateDialog::checkCandidates()
|
||||
appendMod(updatable);
|
||||
m_tasks.insert(updatable.name, updatable.download);
|
||||
}
|
||||
selectedVers.append(m_flame_check_task->getDependencies());
|
||||
}
|
||||
|
||||
// Report failed update checking
|
||||
@ -178,6 +186,49 @@ void ModUpdateDialog::checkCandidates()
|
||||
}
|
||||
}
|
||||
|
||||
{ // dependencies
|
||||
auto depTask = makeShared<GetModDependenciesTask>(this, m_instance, m_mod_model.get(), selectedVers);
|
||||
|
||||
connect(depTask.get(), &Task::failed, this,
|
||||
[&](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); });
|
||||
|
||||
connect(depTask.get(), &Task::succeeded, this, [&]() {
|
||||
QStringList warnings = depTask->warnings();
|
||||
if (warnings.count()) {
|
||||
CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->exec();
|
||||
}
|
||||
});
|
||||
|
||||
ProgressDialog progress_dialog_deps(m_parent);
|
||||
progress_dialog_deps.setSkipButton(true, tr("Abort"));
|
||||
progress_dialog_deps.setWindowTitle(tr("Checking for dependencies..."));
|
||||
auto dret = progress_dialog_deps.execWithTask(depTask.get());
|
||||
|
||||
// If the dialog was skipped / some download error happened
|
||||
if (dret == QDialog::DialogCode::Rejected) {
|
||||
m_aborted = true;
|
||||
QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
static FlameAPI api;
|
||||
|
||||
auto getRequiredBy = depTask->getRequiredBy();
|
||||
|
||||
for (auto dep : depTask->getDependecies()) {
|
||||
auto changelog = dep->version.changelog;
|
||||
if (dep->pack->provider == ModPlatform::ResourceProvider::FLAME)
|
||||
changelog = api.getModFileChangelog(dep->version.addonId.toInt(), dep->version.fileId.toInt());
|
||||
auto download_task = makeShared<ResourceDownloadTask>(dep->pack, dep->version, m_mod_model);
|
||||
CheckUpdateTask::UpdatableMod updatable = {
|
||||
dep->pack->name, dep->version.hash, "", dep->version.version, dep->version.version_type,
|
||||
changelog, dep->pack->provider, download_task
|
||||
};
|
||||
|
||||
appendMod(updatable, getRequiredBy.value(dep->version.addonId.toString()));
|
||||
m_tasks.insert(updatable.name, updatable.download);
|
||||
}
|
||||
}
|
||||
|
||||
// If there's no mod to be updated
|
||||
if (ui->modTreeWidget->topLevelItemCount() == 0) {
|
||||
m_no_updates = true;
|
||||
@ -236,6 +287,10 @@ auto ModUpdateDialog::ensureMetadata() -> bool
|
||||
if (skip_rest)
|
||||
continue;
|
||||
|
||||
if (candidate->type() == ResourceType::FOLDER) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (confirm_rest) {
|
||||
addToTmp(candidate, provider_rest);
|
||||
should_try_others.insert(candidate->internal_id(), try_others_rest);
|
||||
@ -346,7 +401,7 @@ void ModUpdateDialog::onMetadataFailed(Mod* mod, bool try_others, ModPlatform::R
|
||||
}
|
||||
}
|
||||
|
||||
void ModUpdateDialog::appendMod(CheckUpdateTask::UpdatableMod const& info)
|
||||
void ModUpdateDialog::appendMod(CheckUpdateTask::UpdatableMod const& info, QStringList requiredBy)
|
||||
{
|
||||
auto item_top = new QTreeWidgetItem(ui->modTreeWidget);
|
||||
item_top->setCheckState(0, Qt::CheckState::Checked);
|
||||
@ -362,6 +417,26 @@ void ModUpdateDialog::appendMod(CheckUpdateTask::UpdatableMod const& info)
|
||||
auto new_version_item = new QTreeWidgetItem(item_top);
|
||||
new_version_item->setText(0, tr("New version: %1").arg(info.new_version));
|
||||
|
||||
if (info.new_version_type.has_value()) {
|
||||
auto new_version_type_itme = new QTreeWidgetItem(item_top);
|
||||
new_version_type_itme->setText(0, tr("New Version Type: %1").arg(info.new_version_type.value().toString()));
|
||||
}
|
||||
|
||||
if (!requiredBy.isEmpty()) {
|
||||
auto requiredByItem = new QTreeWidgetItem(item_top);
|
||||
if (requiredBy.length() == 1) {
|
||||
requiredByItem->setText(0, tr("Required by: %1").arg(requiredBy.back()));
|
||||
} else {
|
||||
requiredByItem->setText(0, tr("Required by:"));
|
||||
auto i = 0;
|
||||
for (auto req : requiredBy) {
|
||||
auto reqItem = new QTreeWidgetItem(requiredByItem);
|
||||
reqItem->setText(0, req);
|
||||
reqItem->insertChildren(i++, { reqItem });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto changelog_item = new QTreeWidgetItem(item_top);
|
||||
changelog_item->setText(0, tr("Changelog of the latest version"));
|
||||
|
||||
|
@ -23,7 +23,7 @@ class ModUpdateDialog final : public ReviewMessageBox {
|
||||
|
||||
void checkCandidates();
|
||||
|
||||
void appendMod(const CheckUpdateTask::UpdatableMod& info);
|
||||
void appendMod(const CheckUpdateTask::UpdatableMod& info, QStringList requiredBy = {});
|
||||
|
||||
const QList<ResourceDownloadTask::Ptr> getTasks();
|
||||
auto indexDir() const -> QDir { return m_mod_model->indexDir(); }
|
||||
|
@ -127,35 +127,12 @@ void ResourceDownloadDialog::connectButtons()
|
||||
|
||||
static ModPlatform::ProviderCapabilities ProviderCaps;
|
||||
|
||||
QStringList getRequiredBy(QList<ResourceDownloadDialog::DownloadTaskPtr> tasks, ResourceDownloadDialog::DownloadTaskPtr pack)
|
||||
{
|
||||
auto addonId = pack->getPack()->addonId;
|
||||
auto provider = pack->getPack()->provider;
|
||||
auto version = pack->getVersionID();
|
||||
auto req = QStringList();
|
||||
for (auto& task : tasks) {
|
||||
if (provider != task->getPack()->provider)
|
||||
continue;
|
||||
auto deps = task->getVersion().dependencies;
|
||||
if (auto dep = std::find_if(deps.begin(), deps.end(),
|
||||
[addonId, provider, version](const ModPlatform::Dependency& d) {
|
||||
return d.type == ModPlatform::DependencyType::REQUIRED &&
|
||||
(provider == ModPlatform::ResourceProvider::MODRINTH && d.addonId.toString().isEmpty()
|
||||
? version == d.version
|
||||
: d.addonId == addonId);
|
||||
});
|
||||
dep != deps.end()) {
|
||||
req.append(task->getName());
|
||||
}
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
void ResourceDownloadDialog::confirm()
|
||||
{
|
||||
auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString()));
|
||||
confirm_dialog->retranslateUi(resourcesString());
|
||||
|
||||
QHash<QString, QStringList> getRequiredBy;
|
||||
if (auto task = getModDependenciesTask(); task) {
|
||||
connect(task.get(), &Task::failed, this,
|
||||
[&](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); });
|
||||
@ -180,6 +157,7 @@ void ResourceDownloadDialog::confirm()
|
||||
} else {
|
||||
for (auto dep : task->getDependecies())
|
||||
addResource(dep->pack, dep->version);
|
||||
getRequiredBy = task->getRequiredBy();
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,7 +167,8 @@ void ResourceDownloadDialog::confirm()
|
||||
});
|
||||
for (auto& task : selected) {
|
||||
confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath(),
|
||||
ProviderCaps.name(task->getProvider()), getRequiredBy(selected, task) });
|
||||
ProviderCaps.name(task->getProvider()), getRequiredBy.value(task->getPack()->addonId.toString()),
|
||||
task->getVersion().version_type.toString() });
|
||||
}
|
||||
|
||||
if (confirm_dialog->exec()) {
|
||||
|
@ -77,6 +77,10 @@ void ReviewMessageBox::appendResource(ResourceInformation&& info)
|
||||
itemTop->insertChildren(childIndx++, { requiredByItem });
|
||||
}
|
||||
|
||||
auto versionTypeItem = new QTreeWidgetItem(itemTop);
|
||||
versionTypeItem->setText(0, tr("Version Type: %1").arg(info.version_type));
|
||||
itemTop->insertChildren(childIndx++, { versionTypeItem });
|
||||
|
||||
ui->modTreeWidget->addTopLevelItem(itemTop);
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ class ReviewMessageBox : public QDialog {
|
||||
QString custom_file_path{};
|
||||
QString provider;
|
||||
QStringList required_by;
|
||||
QString version_type;
|
||||
};
|
||||
|
||||
void appendResource(ResourceInformation&& info);
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "net/NetJob.h"
|
||||
|
||||
#include "ui/dialogs/CustomMessageBox.h"
|
||||
#include "ui/dialogs/LoginDialog.h"
|
||||
#include "ui/dialogs/MSALoginDialog.h"
|
||||
#include "ui/dialogs/OfflineLoginDialog.h"
|
||||
#include "ui/dialogs/ProgressDialog.h"
|
||||
@ -64,8 +63,7 @@ AccountListPage::AccountListPage(QWidget* parent) : QMainWindow(parent), ui(new
|
||||
ui->setupUi(this);
|
||||
ui->listView->setEmptyString(
|
||||
tr("Welcome!\n"
|
||||
"If you're new here, you can select the \"Add Microsoft\" or \"Add Mojang\" buttons to link your Microsoft and/or Mojang "
|
||||
"accounts."));
|
||||
"If you're new here, you can select the \"Add Microsoft\" button to link your Microsoft account."));
|
||||
ui->listView->setEmptyMode(VersionListView::String);
|
||||
ui->listView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
@ -74,7 +72,6 @@ AccountListPage::AccountListPage(QWidget* parent) : QMainWindow(parent), ui(new
|
||||
ui->listView->setModel(m_accounts.get());
|
||||
ui->listView->header()->setSectionResizeMode(AccountList::VListColumns::ProfileNameColumn, QHeaderView::Stretch);
|
||||
ui->listView->header()->setSectionResizeMode(AccountList::VListColumns::NameColumn, QHeaderView::Stretch);
|
||||
ui->listView->header()->setSectionResizeMode(AccountList::VListColumns::MigrationColumn, QHeaderView::ResizeToContents);
|
||||
ui->listView->header()->setSectionResizeMode(AccountList::VListColumns::TypeColumn, QHeaderView::ResizeToContents);
|
||||
ui->listView->header()->setSectionResizeMode(AccountList::VListColumns::StatusColumn, QHeaderView::ResizeToContents);
|
||||
ui->listView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
@ -139,19 +136,6 @@ void AccountListPage::listChanged()
|
||||
updateButtonStates();
|
||||
}
|
||||
|
||||
void AccountListPage::on_actionAddMojang_triggered()
|
||||
{
|
||||
MinecraftAccountPtr account =
|
||||
LoginDialog::newAccount(this, tr("Please enter your Mojang account email and password to add your account."));
|
||||
|
||||
if (account) {
|
||||
m_accounts->addAccount(account);
|
||||
if (m_accounts->count() == 1) {
|
||||
m_accounts->setDefaultAccount(account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AccountListPage::on_actionAddMicrosoft_triggered()
|
||||
{
|
||||
MinecraftAccountPtr account =
|
||||
@ -169,7 +153,7 @@ void AccountListPage::on_actionAddOffline_triggered()
|
||||
{
|
||||
if (!m_accounts->anyAccountIsValid()) {
|
||||
QMessageBox::warning(this, tr("Error"),
|
||||
tr("You must add a Microsoft or Mojang account that owns Minecraft before you can add an offline account."
|
||||
tr("You must add a Microsoft account that owns Minecraft before you can add an offline account."
|
||||
"<br><br>"
|
||||
"If you have lost your account you can contact Microsoft for support."));
|
||||
return;
|
||||
|
@ -70,7 +70,6 @@ class AccountListPage : public QMainWindow, public BasePage {
|
||||
void retranslate() override;
|
||||
|
||||
public slots:
|
||||
void on_actionAddMojang_triggered();
|
||||
void on_actionAddMicrosoft_triggered();
|
||||
void on_actionAddOffline_triggered();
|
||||
void on_actionRemove_triggered();
|
||||
|
@ -53,7 +53,6 @@
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="actionAddMicrosoft"/>
|
||||
<addaction name="actionAddMojang"/>
|
||||
<addaction name="actionAddOffline"/>
|
||||
<addaction name="actionRefresh"/>
|
||||
<addaction name="actionRemove"/>
|
||||
@ -63,11 +62,6 @@
|
||||
<addaction name="actionUploadSkin"/>
|
||||
<addaction name="actionDeleteSkin"/>
|
||||
</widget>
|
||||
<action name="actionAddMojang">
|
||||
<property name="text">
|
||||
<string>Add &Mojang</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRemove">
|
||||
<property name="text">
|
||||
<string>Remo&ve</string>
|
||||
|
@ -189,6 +189,9 @@ void LauncherPage::applySettings()
|
||||
|
||||
s->set("MenuBarInsteadOfToolBar", ui->preferMenuBarCheckBox->isChecked());
|
||||
|
||||
s->set("NumberOfConcurrentTasks", ui->numberOfConcurrentTasksSpinBox->value());
|
||||
s->set("NumberOfConcurrentDownloads", ui->numberOfConcurrentDownloadsSpinBox->value());
|
||||
|
||||
// Console settings
|
||||
s->set("ShowConsole", ui->showConsoleCheck->isChecked());
|
||||
s->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked());
|
||||
@ -236,6 +239,9 @@ void LauncherPage::loadSettings()
|
||||
#endif
|
||||
ui->preferMenuBarCheckBox->setChecked(s->get("MenuBarInsteadOfToolBar").toBool());
|
||||
|
||||
ui->numberOfConcurrentTasksSpinBox->setValue(s->get("NumberOfConcurrentTasks").toInt());
|
||||
ui->numberOfConcurrentDownloadsSpinBox->setValue(s->get("NumberOfConcurrentDownloads").toInt());
|
||||
|
||||
// Console settings
|
||||
ui->showConsoleCheck->setChecked(s->get("ShowConsole").toBool());
|
||||
ui->autoCloseConsoleCheck->setChecked(s->get("AutoCloseConsole").toBool());
|
||||
|
@ -189,6 +189,43 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="miscellaneousGroupBox">
|
||||
<property name="title">
|
||||
<string>Miscellaneous</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="numberOfConcurrentTasksLabel">
|
||||
<property name="text">
|
||||
<string>Number of concurrent tasks</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="numberOfConcurrentTasksSpinBox">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="numberOfConcurrentDownloadsLabel">
|
||||
<property name="text">
|
||||
<string>Number of concurrent downloads</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="numberOfConcurrentDownloadsSpinBox">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
|
@ -175,7 +175,7 @@ void ModFolderPage::installMods()
|
||||
|
||||
ResourceDownload::ModDownloadDialog mdownload(this, m_model, m_instance);
|
||||
if (mdownload.exec()) {
|
||||
ConcurrentTask* tasks = new ConcurrentTask(this);
|
||||
auto tasks = new ConcurrentTask(this, "Download Mods", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt());
|
||||
connect(tasks, &Task::failed, [this, tasks](QString reason) {
|
||||
CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show();
|
||||
tasks->deleteLater();
|
||||
@ -206,6 +206,14 @@ void ModFolderPage::installMods()
|
||||
|
||||
void ModFolderPage::updateMods()
|
||||
{
|
||||
if (m_instance->typeName() != "Minecraft")
|
||||
return; // this is a null instance or a legacy instance
|
||||
|
||||
auto profile = static_cast<MinecraftInstance*>(m_instance)->getPackProfile();
|
||||
if (!profile->getModLoaders().has_value()) {
|
||||
QMessageBox::critical(this, tr("Error"), tr("Please install a mod loader first!"));
|
||||
return;
|
||||
}
|
||||
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
|
||||
|
||||
auto mods_list = m_model->selectedMods(selection);
|
||||
@ -234,7 +242,7 @@ void ModFolderPage::updateMods()
|
||||
}
|
||||
|
||||
if (update_dialog.exec()) {
|
||||
ConcurrentTask* tasks = new ConcurrentTask(this);
|
||||
auto tasks = new ConcurrentTask(this, "Download Mods", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt());
|
||||
connect(tasks, &Task::failed, [this, tasks](QString reason) {
|
||||
CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show();
|
||||
tasks->deleteLater();
|
||||
|
@ -72,7 +72,8 @@ void ResourcePackPage::downloadRPs()
|
||||
|
||||
ResourceDownload::ResourcePackDownloadDialog mdownload(this, std::static_pointer_cast<ResourcePackFolderModel>(m_model), m_instance);
|
||||
if (mdownload.exec()) {
|
||||
auto tasks = new ConcurrentTask(this);
|
||||
auto tasks =
|
||||
new ConcurrentTask(this, "Download Resource Pack", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt());
|
||||
connect(tasks, &Task::failed, [this, tasks](QString reason) {
|
||||
CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show();
|
||||
tasks->deleteLater();
|
||||
|
@ -65,7 +65,7 @@ void ShaderPackPage::downloadShaders()
|
||||
|
||||
ResourceDownload::ShaderPackDownloadDialog mdownload(this, std::static_pointer_cast<ShaderPackFolderModel>(m_model), m_instance);
|
||||
if (mdownload.exec()) {
|
||||
auto tasks = new ConcurrentTask(this);
|
||||
auto tasks = new ConcurrentTask(this, "Download Shaders", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt());
|
||||
connect(tasks, &Task::failed, [this, tasks](QString reason) {
|
||||
CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show();
|
||||
tasks->deleteLater();
|
||||
|
@ -74,7 +74,8 @@ void TexturePackPage::downloadTPs()
|
||||
|
||||
ResourceDownload::TexturePackDownloadDialog mdownload(this, std::static_pointer_cast<TexturePackFolderModel>(m_model), m_instance);
|
||||
if (mdownload.exec()) {
|
||||
auto tasks = new ConcurrentTask(this);
|
||||
auto tasks =
|
||||
new ConcurrentTask(this, "Download Texture Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt());
|
||||
connect(tasks, &Task::failed, [this, tasks](QString reason) {
|
||||
CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show();
|
||||
tasks->deleteLater();
|
||||
|
@ -411,7 +411,7 @@ void VersionPage::on_actionDownload_All_triggered()
|
||||
if (!APPLICATION->accounts()->anyAccountIsValid()) {
|
||||
CustomMessageBox::selectable(this, tr("Error"),
|
||||
tr("Cannot download Minecraft or update instances unless you have at least "
|
||||
"one account added.\nPlease add your Microsoft or Mojang account."),
|
||||
"one account added.\nPlease add a Microsoft account."),
|
||||
QMessageBox::Warning)
|
||||
->show();
|
||||
return;
|
||||
|
@ -131,8 +131,10 @@ void ModPage::updateVersionList()
|
||||
}
|
||||
|
||||
// Only add the version if it's valid or using the 'Any' filter, but never if the version is opted out
|
||||
if ((valid || m_filter->versions.empty()) && !optedOut(version))
|
||||
m_ui->versionSelectionBox->addItem(version.version, QVariant(i));
|
||||
if ((valid || m_filter->versions.empty()) && !optedOut(version)) {
|
||||
auto release_type = version.version_type.isValid() ? QString(" [%1]").arg(version.version_type.toString()) : "";
|
||||
m_ui->versionSelectionBox->addItem(QString("%1%2").arg(version.version, release_type), QVariant(i));
|
||||
}
|
||||
}
|
||||
if (m_ui->versionSelectionBox->count() == 0) {
|
||||
m_ui->versionSelectionBox->addItem(tr("No valid version found!"), QVariant(-1));
|
||||
|
@ -31,6 +31,9 @@ QHash<ResourceModel*, bool> ResourceModel::s_running_models;
|
||||
ResourceModel::ResourceModel(ResourceAPI* api) : QAbstractListModel(), m_api(api)
|
||||
{
|
||||
s_running_models.insert(this, true);
|
||||
#ifndef LAUNCHER_TEST
|
||||
m_current_info_job.setMaxConcurrent(APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt());
|
||||
#endif
|
||||
}
|
||||
|
||||
ResourceModel::~ResourceModel()
|
||||
|
@ -266,6 +266,9 @@ void ResourcePage::updateVersionList()
|
||||
if (optedOut(version))
|
||||
continue;
|
||||
|
||||
auto release_type = current_pack->versions[i].version_type.isValid()
|
||||
? QString(" [%1]").arg(current_pack->versions[i].version_type.toString())
|
||||
: "";
|
||||
m_ui->versionSelectionBox->addItem(current_pack->versions[i].version, QVariant(i));
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,8 @@ void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelInde
|
||||
}
|
||||
|
||||
for (auto version : current.versions) {
|
||||
ui->versionSelectionBox->addItem(version.version, QVariant(version.downloadUrl));
|
||||
auto release_type = version.version_type.isValid() ? QString(" [%1]").arg(version.version_type.toString()) : "";
|
||||
ui->versionSelectionBox->addItem(QString("%1%2").arg(version.version, release_type), QVariant(version.downloadUrl));
|
||||
}
|
||||
|
||||
QVariant current_updated;
|
||||
|
@ -217,12 +217,13 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI
|
||||
qDebug() << *response;
|
||||
qWarning() << "Error while reading modrinth modpack version: " << e.cause();
|
||||
}
|
||||
|
||||
for (auto version : current.versions) {
|
||||
auto release_type = version.version_type.isValid() ? QString(" [%1]").arg(version.version_type.toString()) : "";
|
||||
if (!version.name.contains(version.version))
|
||||
ui->versionSelectionBox->addItem(QString("%1 — %2").arg(version.name, version.version), QVariant(version.id));
|
||||
ui->versionSelectionBox->addItem(QString("%1 — %2%3").arg(version.name, version.version, release_type),
|
||||
QVariant(version.id));
|
||||
else
|
||||
ui->versionSelectionBox->addItem(version.name, QVariant(version.id));
|
||||
ui->versionSelectionBox->addItem(QString("%1%2").arg(version.name, release_type), QVariant(version.id));
|
||||
}
|
||||
|
||||
QVariant current_updated;
|
||||
|
@ -82,7 +82,7 @@ class VersionSelectWidget : public QWidget {
|
||||
void selectedVersionChanged(BaseVersion::Ptr version);
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent*);
|
||||
virtual void closeEvent(QCloseEvent*) override;
|
||||
|
||||
private slots:
|
||||
void onTaskSucceeded();
|
||||
|
Reference in New Issue
Block a user