From b258eac215c791b2a8eed10cecbbf9551c87f0b9 Mon Sep 17 00:00:00 2001 From: Petr Mrázek Date: Mon, 22 Nov 2021 03:55:16 +0100 Subject: NOISSUE continue reshuffling the codebase --- launcher/ui/pages/global/AccountListPage.cpp | 260 +++++++++++ launcher/ui/pages/global/AccountListPage.h | 85 ++++ launcher/ui/pages/global/AccountListPage.ui | 129 ++++++ launcher/ui/pages/global/CustomCommandsPage.cpp | 51 +++ launcher/ui/pages/global/CustomCommandsPage.h | 55 +++ launcher/ui/pages/global/ExternalToolsPage.cpp | 233 ++++++++++ launcher/ui/pages/global/ExternalToolsPage.h | 74 +++ launcher/ui/pages/global/ExternalToolsPage.ui | 194 ++++++++ launcher/ui/pages/global/JavaPage.cpp | 153 +++++++ launcher/ui/pages/global/JavaPage.h | 72 +++ launcher/ui/pages/global/JavaPage.ui | 260 +++++++++++ launcher/ui/pages/global/LanguagePage.cpp | 51 +++ launcher/ui/pages/global/LanguagePage.h | 60 +++ launcher/ui/pages/global/LauncherPage.cpp | 466 +++++++++++++++++++ launcher/ui/pages/global/LauncherPage.h | 103 +++++ launcher/ui/pages/global/LauncherPage.ui | 584 ++++++++++++++++++++++++ launcher/ui/pages/global/MinecraftPage.cpp | 91 ++++ launcher/ui/pages/global/MinecraftPage.h | 70 +++ launcher/ui/pages/global/MinecraftPage.ui | 196 ++++++++ launcher/ui/pages/global/PasteEEPage.cpp | 81 ++++ launcher/ui/pages/global/PasteEEPage.h | 62 +++ launcher/ui/pages/global/PasteEEPage.ui | 128 ++++++ launcher/ui/pages/global/ProxyPage.cpp | 106 +++++ launcher/ui/pages/global/ProxyPage.h | 66 +++ launcher/ui/pages/global/ProxyPage.ui | 203 ++++++++ 25 files changed, 3833 insertions(+) create mode 100644 launcher/ui/pages/global/AccountListPage.cpp create mode 100644 launcher/ui/pages/global/AccountListPage.h create mode 100644 launcher/ui/pages/global/AccountListPage.ui create mode 100644 launcher/ui/pages/global/CustomCommandsPage.cpp create mode 100644 launcher/ui/pages/global/CustomCommandsPage.h create mode 100644 launcher/ui/pages/global/ExternalToolsPage.cpp create mode 100644 launcher/ui/pages/global/ExternalToolsPage.h create mode 100644 launcher/ui/pages/global/ExternalToolsPage.ui create mode 100644 launcher/ui/pages/global/JavaPage.cpp create mode 100644 launcher/ui/pages/global/JavaPage.h create mode 100644 launcher/ui/pages/global/JavaPage.ui create mode 100644 launcher/ui/pages/global/LanguagePage.cpp create mode 100644 launcher/ui/pages/global/LanguagePage.h create mode 100644 launcher/ui/pages/global/LauncherPage.cpp create mode 100644 launcher/ui/pages/global/LauncherPage.h create mode 100644 launcher/ui/pages/global/LauncherPage.ui create mode 100644 launcher/ui/pages/global/MinecraftPage.cpp create mode 100644 launcher/ui/pages/global/MinecraftPage.h create mode 100644 launcher/ui/pages/global/MinecraftPage.ui create mode 100644 launcher/ui/pages/global/PasteEEPage.cpp create mode 100644 launcher/ui/pages/global/PasteEEPage.h create mode 100644 launcher/ui/pages/global/PasteEEPage.ui create mode 100644 launcher/ui/pages/global/ProxyPage.cpp create mode 100644 launcher/ui/pages/global/ProxyPage.h create mode 100644 launcher/ui/pages/global/ProxyPage.ui (limited to 'launcher/ui/pages/global') diff --git a/launcher/ui/pages/global/AccountListPage.cpp b/launcher/ui/pages/global/AccountListPage.cpp new file mode 100644 index 00000000..816dce47 --- /dev/null +++ b/launcher/ui/pages/global/AccountListPage.cpp @@ -0,0 +1,260 @@ +/* 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 "AccountListPage.h" +#include "ui_AccountListPage.h" + +#include +#include + +#include + +#include "net/NetJob.h" + +#include "ui/dialogs/ProgressDialog.h" +#include "ui/dialogs/LoginDialog.h" +#include "ui/dialogs/MSALoginDialog.h" +#include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/SkinUploadDialog.h" + +#include "tasks/Task.h" +#include "minecraft/auth/AccountTask.h" +#include "minecraft/services/SkinDelete.h" + +#include "Application.h" + +#include "BuildConfig.h" + +#include "Secrets.h" + +AccountListPage::AccountListPage(QWidget *parent) + : QMainWindow(parent), ui(new Ui::AccountListPage) +{ + ui->setupUi(this); + ui->listView->setEmptyString(tr( + "Welcome!\n" + "If you're new here, you can click the \"Add\" button to add your Mojang or Minecraft account." + )); + ui->listView->setEmptyMode(VersionListView::String); + ui->listView->setContextMenuPolicy(Qt::CustomContextMenu); + + m_accounts = APPLICATION->accounts(); + + ui->listView->setModel(m_accounts.get()); + ui->listView->header()->setSectionResizeMode(0, QHeaderView::Stretch); + ui->listView->header()->setSectionResizeMode(1, QHeaderView::Stretch); + ui->listView->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents); + ui->listView->setSelectionMode(QAbstractItemView::SingleSelection); + + // Expand the account column + + QItemSelectionModel *selectionModel = ui->listView->selectionModel(); + + connect(selectionModel, &QItemSelectionModel::selectionChanged, [this](const QItemSelection &sel, const QItemSelection &dsel) { + updateButtonStates(); + }); + connect(ui->listView, &VersionListView::customContextMenuRequested, this, &AccountListPage::ShowContextMenu); + + connect(m_accounts.get(), &AccountList::listChanged, this, &AccountListPage::listChanged); + connect(m_accounts.get(), &AccountList::listActivityChanged, this, &AccountListPage::listChanged); + connect(m_accounts.get(), &AccountList::defaultAccountChanged, this, &AccountListPage::listChanged); + + updateButtonStates(); + + // Xbox authentication won't work without a client identifier, so disable the button if it is missing + ui->actionAddMicrosoft->setVisible(Secrets::hasMSAClientID()); +} + +AccountListPage::~AccountListPage() +{ + delete ui; +} + +void AccountListPage::ShowContextMenu(const QPoint& pos) +{ + auto menu = ui->toolBar->createContextMenu(this, tr("Context menu")); + menu->exec(ui->listView->mapToGlobal(pos)); + delete menu; +} + +void AccountListPage::changeEvent(QEvent* event) +{ + if (event->type() == QEvent::LanguageChange) + { + ui->retranslateUi(this); + } + QMainWindow::changeEvent(event); +} + +QMenu * AccountListPage::createPopupMenu() +{ + QMenu* filteredMenu = QMainWindow::createPopupMenu(); + filteredMenu->removeAction(ui->toolBar->toggleViewAction() ); + return filteredMenu; +} + + +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() +{ + if(BuildConfig.BUILD_PLATFORM == "osx64") { + CustomMessageBox::selectable( + this, + tr("Microsoft Accounts not available"), + tr( + "Microsoft accounts are only usable on macOS 10.13 or newer, with fully updated MultiMC.\n\n" + "Please update both your operating system and MultiMC." + ), + QMessageBox::Warning + )->exec(); + return; + } + MinecraftAccountPtr account = MSALoginDialog::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_actionRemove_triggered() +{ + QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes(); + if (selection.size() > 0) + { + QModelIndex selected = selection.first(); + m_accounts->removeAccount(selected); + } +} + +void AccountListPage::on_actionRefresh_triggered() { + QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes(); + if (selection.size() > 0) { + QModelIndex selected = selection.first(); + MinecraftAccountPtr account = selected.data(AccountList::PointerRole).value(); + AuthSessionPtr session = std::make_shared(); + auto task = account->refresh(session); + if (task) { + ProgressDialog progDialog(this); + progDialog.execWithTask(task.get()); + // TODO: respond to results of the task + } + } +} + + +void AccountListPage::on_actionSetDefault_triggered() +{ + QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes(); + if (selection.size() > 0) + { + QModelIndex selected = selection.first(); + MinecraftAccountPtr account = selected.data(AccountList::PointerRole).value(); + m_accounts->setDefaultAccount(account); + } +} + +void AccountListPage::on_actionNoDefault_triggered() +{ + m_accounts->setDefaultAccount(nullptr); +} + +void AccountListPage::updateButtonStates() +{ + // If there is no selection, disable buttons that require something selected. + QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes(); + bool hasSelection = selection.size() > 0; + bool accountIsReady = false; + if (hasSelection) + { + QModelIndex selected = selection.first(); + MinecraftAccountPtr account = selected.data(AccountList::PointerRole).value(); + accountIsReady = !account->isActive(); + } + ui->actionRemove->setEnabled(accountIsReady); + ui->actionSetDefault->setEnabled(accountIsReady); + ui->actionUploadSkin->setEnabled(accountIsReady); + ui->actionDeleteSkin->setEnabled(accountIsReady); + ui->actionRefresh->setEnabled(accountIsReady); + + if(m_accounts->defaultAccount().get() == nullptr) { + ui->actionNoDefault->setEnabled(false); + ui->actionNoDefault->setChecked(true); + } + else { + ui->actionNoDefault->setEnabled(true); + ui->actionNoDefault->setChecked(false); + } +} + +void AccountListPage::on_actionUploadSkin_triggered() +{ + QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes(); + if (selection.size() > 0) + { + QModelIndex selected = selection.first(); + MinecraftAccountPtr account = selected.data(AccountList::PointerRole).value(); + SkinUploadDialog dialog(account, this); + dialog.exec(); + } +} + +void AccountListPage::on_actionDeleteSkin_triggered() +{ + QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes(); + if (selection.size() <= 0) + return; + + QModelIndex selected = selection.first(); + AuthSessionPtr session = std::make_shared(); + MinecraftAccountPtr account = selected.data(AccountList::PointerRole).value(); + auto login = account->refresh(session); + ProgressDialog prog(this); + if (prog.execWithTask((Task*)login.get()) != QDialog::Accepted) { + CustomMessageBox::selectable(this, tr("Skin Delete"), tr("Failed to login!"), QMessageBox::Warning)->exec(); + return; + } + auto deleteSkinTask = std::make_shared(this, session); + if (prog.execWithTask((Task*)deleteSkinTask.get()) != QDialog::Accepted) { + CustomMessageBox::selectable(this, tr("Skin Delete"), tr("Failed to delete current skin!"), QMessageBox::Warning)->exec(); + return; + } +} diff --git a/launcher/ui/pages/global/AccountListPage.h b/launcher/ui/pages/global/AccountListPage.h new file mode 100644 index 00000000..1c65e708 --- /dev/null +++ b/launcher/ui/pages/global/AccountListPage.h @@ -0,0 +1,85 @@ +/* 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 +#include + +#include "ui/pages/BasePage.h" + +#include "minecraft/auth/AccountList.h" +#include "Application.h" + +namespace Ui +{ +class AccountListPage; +} + +class AuthenticateTask; + +class AccountListPage : public QMainWindow, public BasePage +{ + Q_OBJECT +public: + explicit AccountListPage(QWidget *parent = 0); + ~AccountListPage(); + + QString displayName() const override + { + return tr("Accounts"); + } + QIcon icon() const override + { + auto icon = APPLICATION->getThemedIcon("accounts"); + if(icon.isNull()) + { + icon = APPLICATION->getThemedIcon("noaccount"); + } + return icon; + } + QString id() const override + { + return "accounts"; + } + QString helpPage() const override + { + return "Getting-Started#adding-an-account"; + } + +public slots: + void on_actionAddMojang_triggered(); + void on_actionAddMicrosoft_triggered(); + void on_actionRemove_triggered(); + void on_actionRefresh_triggered(); + void on_actionSetDefault_triggered(); + void on_actionNoDefault_triggered(); + void on_actionUploadSkin_triggered(); + void on_actionDeleteSkin_triggered(); + + void listChanged(); + + //! Updates the states of the dialog's buttons. + void updateButtonStates(); + +protected slots: + void ShowContextMenu(const QPoint &pos); + +private: + void changeEvent(QEvent * event) override; + QMenu * createPopupMenu() override; + shared_qobject_ptr m_accounts; + Ui::AccountListPage *ui; +}; diff --git a/launcher/ui/pages/global/AccountListPage.ui b/launcher/ui/pages/global/AccountListPage.ui new file mode 100644 index 00000000..29738c02 --- /dev/null +++ b/launcher/ui/pages/global/AccountListPage.ui @@ -0,0 +1,129 @@ + + + AccountListPage + + + + 0 + 0 + 800 + 600 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + false + + + false + + + true + + + false + + + + + + + + RightToolBarArea + + + false + + + + + + + + + + + + + + Add Mojang + + + + + Remove + + + + + Set Default + + + + + true + + + No Default + + + + + Upload Skin + + + + + Delete Skin + + + Delete the currently active skin and go back to the default one + + + + + Add Microsoft + + + + + Refresh + + + Refresh the account tokens + + + + + + VersionListView + QTreeView +
ui/widgets/VersionListView.h
+
+ + WideBar + QToolBar +
ui/widgets/WideBar.h
+
+
+ + +
diff --git a/launcher/ui/pages/global/CustomCommandsPage.cpp b/launcher/ui/pages/global/CustomCommandsPage.cpp new file mode 100644 index 00000000..8541e3c1 --- /dev/null +++ b/launcher/ui/pages/global/CustomCommandsPage.cpp @@ -0,0 +1,51 @@ +#include "CustomCommandsPage.h" +#include +#include +#include + +CustomCommandsPage::CustomCommandsPage(QWidget* parent): QWidget(parent) +{ + + auto verticalLayout = new QVBoxLayout(this); + verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + verticalLayout->setContentsMargins(0, 0, 0, 0); + + auto tabWidget = new QTabWidget(this); + tabWidget->setObjectName(QStringLiteral("tabWidget")); + commands = new CustomCommands(this); + commands->setContentsMargins(6, 6, 6, 6); + tabWidget->addTab(commands, "Foo"); + tabWidget->tabBar()->hide(); + verticalLayout->addWidget(tabWidget); + loadSettings(); +} + +CustomCommandsPage::~CustomCommandsPage() +{ +} + +bool CustomCommandsPage::apply() +{ + applySettings(); + return true; +} + +void CustomCommandsPage::applySettings() +{ + auto s = APPLICATION->settings(); + s->set("PreLaunchCommand", commands->prelaunchCommand()); + s->set("WrapperCommand", commands->wrapperCommand()); + s->set("PostExitCommand", commands->postexitCommand()); +} + +void CustomCommandsPage::loadSettings() +{ + auto s = APPLICATION->settings(); + commands->initialize( + false, + true, + s->get("PreLaunchCommand").toString(), + s->get("WrapperCommand").toString(), + s->get("PostExitCommand").toString() + ); +} diff --git a/launcher/ui/pages/global/CustomCommandsPage.h b/launcher/ui/pages/global/CustomCommandsPage.h new file mode 100644 index 00000000..a1155e0e --- /dev/null +++ b/launcher/ui/pages/global/CustomCommandsPage.h @@ -0,0 +1,55 @@ +/* Copyright 2018-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 +#include + +#include "ui/pages/BasePage.h" +#include +#include "ui/widgets/CustomCommands.h" + +class CustomCommandsPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit CustomCommandsPage(QWidget *parent = 0); + ~CustomCommandsPage(); + + QString displayName() const override + { + return tr("Custom Commands"); + } + QIcon icon() const override + { + return APPLICATION->getThemedIcon("custom-commands"); + } + QString id() const override + { + return "custom-commands"; + } + QString helpPage() const override + { + return "Custom-commands"; + } + bool apply() override; + +private: + void applySettings(); + void loadSettings(); + CustomCommands * commands; +}; diff --git a/launcher/ui/pages/global/ExternalToolsPage.cpp b/launcher/ui/pages/global/ExternalToolsPage.cpp new file mode 100644 index 00000000..41d900aa --- /dev/null +++ b/launcher/ui/pages/global/ExternalToolsPage.cpp @@ -0,0 +1,233 @@ +/* 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 "ExternalToolsPage.h" +#include "ui_ExternalToolsPage.h" + +#include +#include +#include +#include + +#include "settings/SettingsObject.h" +#include "tools/BaseProfiler.h" +#include +#include "Application.h" +#include + +ExternalToolsPage::ExternalToolsPage(QWidget *parent) : + QWidget(parent), + ui(new Ui::ExternalToolsPage) +{ + ui->setupUi(this); + ui->tabWidget->tabBar()->hide(); + + #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) + ui->jsonEditorTextBox->setClearButtonEnabled(true); + #endif + + ui->mceditLink->setOpenExternalLinks(true); + ui->jvisualvmLink->setOpenExternalLinks(true); + ui->jprofilerLink->setOpenExternalLinks(true); + loadSettings(); +} + +ExternalToolsPage::~ExternalToolsPage() +{ + delete ui; +} + +void ExternalToolsPage::loadSettings() +{ + auto s = APPLICATION->settings(); + ui->jprofilerPathEdit->setText(s->get("JProfilerPath").toString()); + ui->jvisualvmPathEdit->setText(s->get("JVisualVMPath").toString()); + ui->mceditPathEdit->setText(s->get("MCEditPath").toString()); + + // Editors + ui->jsonEditorTextBox->setText(s->get("JsonEditor").toString()); +} +void ExternalToolsPage::applySettings() +{ + auto s = APPLICATION->settings(); + + s->set("JProfilerPath", ui->jprofilerPathEdit->text()); + s->set("JVisualVMPath", ui->jvisualvmPathEdit->text()); + s->set("MCEditPath", ui->mceditPathEdit->text()); + + // Editors + QString jsonEditor = ui->jsonEditorTextBox->text(); + if (!jsonEditor.isEmpty() && + (!QFileInfo(jsonEditor).exists() || !QFileInfo(jsonEditor).isExecutable())) + { + QString found = QStandardPaths::findExecutable(jsonEditor); + if (!found.isEmpty()) + { + jsonEditor = found; + } + } + s->set("JsonEditor", jsonEditor); +} + +void ExternalToolsPage::on_jprofilerPathBtn_clicked() +{ + QString raw_dir = ui->jprofilerPathEdit->text(); + QString error; + do + { + raw_dir = QFileDialog::getExistingDirectory(this, tr("JProfiler Folder"), raw_dir); + if (raw_dir.isEmpty()) + { + break; + } + QString cooked_dir = FS::NormalizePath(raw_dir); + if (!APPLICATION->profilers()["jprofiler"]->check(cooked_dir, &error)) + { + QMessageBox::critical(this, tr("Error"), tr("Error while checking JProfiler install:\n%1").arg(error)); + continue; + } + else + { + ui->jprofilerPathEdit->setText(cooked_dir); + break; + } + } while (1); +} +void ExternalToolsPage::on_jprofilerCheckBtn_clicked() +{ + QString error; + if (!APPLICATION->profilers()["jprofiler"]->check(ui->jprofilerPathEdit->text(), &error)) + { + QMessageBox::critical(this, tr("Error"), tr("Error while checking JProfiler install:\n%1").arg(error)); + } + else + { + QMessageBox::information(this, tr("OK"), tr("JProfiler setup seems to be OK")); + } +} + +void ExternalToolsPage::on_jvisualvmPathBtn_clicked() +{ + QString raw_dir = ui->jvisualvmPathEdit->text(); + QString error; + do + { + raw_dir = QFileDialog::getOpenFileName(this, tr("JVisualVM Executable"), raw_dir); + if (raw_dir.isEmpty()) + { + break; + } + QString cooked_dir = FS::NormalizePath(raw_dir); + if (!APPLICATION->profilers()["jvisualvm"]->check(cooked_dir, &error)) + { + QMessageBox::critical(this, tr("Error"), tr("Error while checking JVisualVM install:\n%1").arg(error)); + continue; + } + else + { + ui->jvisualvmPathEdit->setText(cooked_dir); + break; + } + } while (1); +} +void ExternalToolsPage::on_jvisualvmCheckBtn_clicked() +{ + QString error; + if (!APPLICATION->profilers()["jvisualvm"]->check(ui->jvisualvmPathEdit->text(), &error)) + { + QMessageBox::critical(this, tr("Error"), tr("Error while checking JVisualVM install:\n%1").arg(error)); + } + else + { + QMessageBox::information(this, tr("OK"), tr("JVisualVM setup seems to be OK")); + } +} + +void ExternalToolsPage::on_mceditPathBtn_clicked() +{ + QString raw_dir = ui->mceditPathEdit->text(); + QString error; + do + { +#ifdef Q_OS_OSX + raw_dir = QFileDialog::getOpenFileName(this, tr("MCEdit Application"), raw_dir); +#else + raw_dir = QFileDialog::getExistingDirectory(this, tr("MCEdit Folder"), raw_dir); +#endif + if (raw_dir.isEmpty()) + { + break; + } + QString cooked_dir = FS::NormalizePath(raw_dir); + if (!APPLICATION->mcedit()->check(cooked_dir, error)) + { + QMessageBox::critical(this, tr("Error"), tr("Error while checking MCEdit install:\n%1").arg(error)); + continue; + } + else + { + ui->mceditPathEdit->setText(cooked_dir); + break; + } + } while (1); +} +void ExternalToolsPage::on_mceditCheckBtn_clicked() +{ + QString error; + if (!APPLICATION->mcedit()->check(ui->mceditPathEdit->text(), error)) + { + QMessageBox::critical(this, tr("Error"), tr("Error while checking MCEdit install:\n%1").arg(error)); + } + else + { + QMessageBox::information(this, tr("OK"), tr("MCEdit setup seems to be OK")); + } +} + +void ExternalToolsPage::on_jsonEditorBrowseBtn_clicked() +{ + QString raw_file = QFileDialog::getOpenFileName( + this, tr("JSON Editor"), + ui->jsonEditorTextBox->text().isEmpty() +#if defined(Q_OS_LINUX) + ? QString("/usr/bin") +#else + ? QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).first() +#endif + : ui->jsonEditorTextBox->text()); + + if (raw_file.isEmpty()) + { + return; + } + QString cooked_file = FS::NormalizePath(raw_file); + + // it has to exist and be an executable + if (QFileInfo(cooked_file).exists() && QFileInfo(cooked_file).isExecutable()) + { + ui->jsonEditorTextBox->setText(cooked_file); + } + else + { + QMessageBox::warning(this, tr("Invalid"), + tr("The file chosen does not seem to be an executable")); + } +} + +bool ExternalToolsPage::apply() +{ + applySettings(); + return true; +} diff --git a/launcher/ui/pages/global/ExternalToolsPage.h b/launcher/ui/pages/global/ExternalToolsPage.h new file mode 100644 index 00000000..5ae6148d --- /dev/null +++ b/launcher/ui/pages/global/ExternalToolsPage.h @@ -0,0 +1,74 @@ +/* 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 + +#include "ui/pages/BasePage.h" +#include + +namespace Ui { +class ExternalToolsPage; +} + +class ExternalToolsPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit ExternalToolsPage(QWidget *parent = 0); + ~ExternalToolsPage(); + + QString displayName() const override + { + return tr("External Tools"); + } + QIcon icon() const override + { + auto icon = APPLICATION->getThemedIcon("externaltools"); + if(icon.isNull()) + { + icon = APPLICATION->getThemedIcon("loadermods"); + } + return icon; + } + QString id() const override + { + return "external-tools"; + } + QString helpPage() const override + { + return "Tools"; + } + virtual bool apply() override; + +private: + void loadSettings(); + void applySettings(); + +private: + Ui::ExternalToolsPage *ui; + +private +slots: + void on_jprofilerPathBtn_clicked(); + void on_jprofilerCheckBtn_clicked(); + void on_jvisualvmPathBtn_clicked(); + void on_jvisualvmCheckBtn_clicked(); + void on_mceditPathBtn_clicked(); + void on_mceditCheckBtn_clicked(); + void on_jsonEditorBrowseBtn_clicked(); +}; diff --git a/launcher/ui/pages/global/ExternalToolsPage.ui b/launcher/ui/pages/global/ExternalToolsPage.ui new file mode 100644 index 00000000..e79e9388 --- /dev/null +++ b/launcher/ui/pages/global/ExternalToolsPage.ui @@ -0,0 +1,194 @@ + + + ExternalToolsPage + + + + 0 + 0 + 673 + 751 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + Tab 1 + + + + + + JProfiler + + + + + + + + + + + ... + + + + + + + + + Check + + + + + + + <html><head/><body><p><a href="https://www.ej-technologies.com/products/jprofiler/overview.html">https://www.ej-technologies.com/products/jprofiler/overview.html</a></p></body></html> + + + + + + + + + + JVisualVM + + + + + + + + + + + ... + + + + + + + + + Check + + + + + + + <html><head/><body><p><a href="https://visualvm.github.io/">https://visualvm.github.io/</a></p></body></html> + + + + + + + + + + MCEdit + + + + + + + + + + + ... + + + + + + + + + Check + + + + + + + <html><head/><body><p><a href="https://www.mcedit.net/">https://www.mcedit.net/</a></p></body></html> + + + + + + + + + + External Editors (leave empty for system default) + + + + + + + + + Text Editor: + + + + + + + ... + + + + + + + + + + Qt::Vertical + + + + 20 + 216 + + + + + + + + + + + + + diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp new file mode 100644 index 00000000..bd79f11a --- /dev/null +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -0,0 +1,153 @@ +/* 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 "JavaPage.h" +#include "JavaCommon.h" +#include "ui_JavaPage.h" + +#include +#include +#include +#include + +#include "ui/dialogs/VersionSelectDialog.h" + +#include "java/JavaUtils.h" +#include "java/JavaInstallList.h" + +#include "settings/SettingsObject.h" +#include +#include "Application.h" +#include + +JavaPage::JavaPage(QWidget *parent) : QWidget(parent), ui(new Ui::JavaPage) +{ + ui->setupUi(this); + ui->tabWidget->tabBar()->hide(); + + auto sysMiB = Sys::getSystemRam() / Sys::mebibyte; + ui->maxMemSpinBox->setMaximum(sysMiB); + loadSettings(); +} + +JavaPage::~JavaPage() +{ + delete ui; +} + +bool JavaPage::apply() +{ + applySettings(); + return true; +} + +void JavaPage::applySettings() +{ + auto s = APPLICATION->settings(); + + // Memory + int min = ui->minMemSpinBox->value(); + int max = ui->maxMemSpinBox->value(); + if(min < max) + { + s->set("MinMemAlloc", min); + s->set("MaxMemAlloc", max); + } + else + { + s->set("MinMemAlloc", max); + s->set("MaxMemAlloc", min); + } + s->set("PermGen", ui->permGenSpinBox->value()); + + // Java Settings + s->set("JavaPath", ui->javaPathTextBox->text()); + s->set("JvmArgs", ui->jvmArgsTextBox->text()); + JavaCommon::checkJVMArgs(s->get("JvmArgs").toString(), this->parentWidget()); +} +void JavaPage::loadSettings() +{ + auto s = APPLICATION->settings(); + // Memory + int min = s->get("MinMemAlloc").toInt(); + int max = s->get("MaxMemAlloc").toInt(); + if(min < max) + { + ui->minMemSpinBox->setValue(min); + ui->maxMemSpinBox->setValue(max); + } + else + { + ui->minMemSpinBox->setValue(max); + ui->maxMemSpinBox->setValue(min); + } + ui->permGenSpinBox->setValue(s->get("PermGen").toInt()); + + // Java Settings + ui->javaPathTextBox->setText(s->get("JavaPath").toString()); + ui->jvmArgsTextBox->setText(s->get("JvmArgs").toString()); +} + +void JavaPage::on_javaDetectBtn_clicked() +{ + JavaInstallPtr java; + + VersionSelectDialog vselect(APPLICATION->javalist().get(), tr("Select a Java version"), this, true); + vselect.setResizeOn(2); + vselect.exec(); + + if (vselect.result() == QDialog::Accepted && vselect.selectedVersion()) + { + java = std::dynamic_pointer_cast(vselect.selectedVersion()); + ui->javaPathTextBox->setText(java->path); + } +} + +void JavaPage::on_javaBrowseBtn_clicked() +{ + QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable")); + + // do not allow current dir - it's dirty. Do not allow dirs that don't exist + if(raw_path.isEmpty()) + { + return; + } + + QString cooked_path = FS::NormalizePath(raw_path); + QFileInfo javaInfo(cooked_path);; + if(!javaInfo.exists() || !javaInfo.isExecutable()) + { + return; + } + ui->javaPathTextBox->setText(cooked_path); +} + +void JavaPage::on_javaTestBtn_clicked() +{ + if(checker) + { + return; + } + checker.reset(new JavaCommon::TestCheck( + this, ui->javaPathTextBox->text(), ui->jvmArgsTextBox->text(), + ui->minMemSpinBox->value(), ui->maxMemSpinBox->value(), ui->permGenSpinBox->value())); + connect(checker.get(), SIGNAL(finished()), SLOT(checkerFinished())); + checker->run(); +} + +void JavaPage::checkerFinished() +{ + checker.reset(); +} diff --git a/launcher/ui/pages/global/JavaPage.h b/launcher/ui/pages/global/JavaPage.h new file mode 100644 index 00000000..8f9b3323 --- /dev/null +++ b/launcher/ui/pages/global/JavaPage.h @@ -0,0 +1,72 @@ +/* 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 +#include +#include "ui/pages/BasePage.h" +#include "JavaCommon.h" +#include +#include + +class SettingsObject; + +namespace Ui +{ +class JavaPage; +} + +class JavaPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit JavaPage(QWidget *parent = 0); + ~JavaPage(); + + QString displayName() const override + { + return tr("Java"); + } + QIcon icon() const override + { + return APPLICATION->getThemedIcon("java"); + } + QString id() const override + { + return "java-settings"; + } + QString helpPage() const override + { + return "Java-settings"; + } + bool apply() override; + +private: + void applySettings(); + void loadSettings(); + +private +slots: + void on_javaDetectBtn_clicked(); + void on_javaTestBtn_clicked(); + void on_javaBrowseBtn_clicked(); + void checkerFinished(); + +private: + Ui::JavaPage *ui; + unique_qobject_ptr checker; +}; diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui new file mode 100644 index 00000000..b67e9994 --- /dev/null +++ b/launcher/ui/pages/global/JavaPage.ui @@ -0,0 +1,260 @@ + + + JavaPage + + + + 0 + 0 + 545 + 580 + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + Tab 1 + + + + + + Memory + + + + + + The maximum amount of memory Minecraft is allowed to use. + + + MiB + + + 128 + + + 65536 + + + 128 + + + 1024 + + + + + + + Minimum memory allocation: + + + + + + + Maximum memory allocation: + + + + + + + The amount of memory Minecraft is started with. + + + MiB + + + 128 + + + 65536 + + + 128 + + + 256 + + + + + + + PermGen: + + + + + + + The amount of memory available to store loaded Java classes. + + + MiB + + + 64 + + + 999999999 + + + 8 + + + 64 + + + + + + + + + + Java Runtime + + + + + + + 0 + 0 + + + + Java path: + + + + + + + + + + + + + 0 + 0 + + + + + 28 + 16777215 + + + + ... + + + + + + + + + + + + + 0 + 0 + + + + JVM arguments: + + + + + + + + 0 + 0 + + + + Auto-detect... + + + + + + + + 0 + 0 + + + + Test + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + minMemSpinBox + maxMemSpinBox + permGenSpinBox + javaBrowseBtn + javaPathTextBox + jvmArgsTextBox + javaDetectBtn + javaTestBtn + tabWidget + + + + diff --git a/launcher/ui/pages/global/LanguagePage.cpp b/launcher/ui/pages/global/LanguagePage.cpp new file mode 100644 index 00000000..359fdeeb --- /dev/null +++ b/launcher/ui/pages/global/LanguagePage.cpp @@ -0,0 +1,51 @@ +#include "LanguagePage.h" + +#include "ui/widgets/LanguageSelectionWidget.h" +#include + +LanguagePage::LanguagePage(QWidget* parent) : + QWidget(parent) +{ + setObjectName(QStringLiteral("languagePage")); + auto layout = new QVBoxLayout(this); + mainWidget = new LanguageSelectionWidget(this); + layout->setContentsMargins(0,0,0,0); + layout->addWidget(mainWidget); + retranslate(); +} + +LanguagePage::~LanguagePage() +{ +} + +bool LanguagePage::apply() +{ + applySettings(); + return true; +} + +void LanguagePage::applySettings() +{ + auto settings = APPLICATION->settings(); + QString key = mainWidget->getSelectedLanguageKey(); + settings->set("Language", key); +} + +void LanguagePage::loadSettings() +{ + // NIL +} + +void LanguagePage::retranslate() +{ + mainWidget->retranslate(); +} + +void LanguagePage::changeEvent(QEvent* event) +{ + if (event->type() == QEvent::LanguageChange) + { + retranslate(); + } + QWidget::changeEvent(event); +} diff --git a/launcher/ui/pages/global/LanguagePage.h b/launcher/ui/pages/global/LanguagePage.h new file mode 100644 index 00000000..b1dd05ad --- /dev/null +++ b/launcher/ui/pages/global/LanguagePage.h @@ -0,0 +1,60 @@ +/* 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 +#include "ui/pages/BasePage.h" +#include +#include + +class LanguageSelectionWidget; + +class LanguagePage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit LanguagePage(QWidget *parent = 0); + virtual ~LanguagePage(); + + QString displayName() const override + { + return tr("Language"); + } + QIcon icon() const override + { + return APPLICATION->getThemedIcon("language"); + } + QString id() const override + { + return "language-settings"; + } + QString helpPage() const override + { + return "Language-settings"; + } + bool apply() override; + + void changeEvent(QEvent * ) override; + +private: + void applySettings(); + void loadSettings(); + void retranslate(); + +private: + LanguageSelectionWidget *mainWidget; +}; diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp new file mode 100644 index 00000000..2eb73e44 --- /dev/null +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -0,0 +1,466 @@ +/* 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 "LauncherPage.h" +#include "ui_LauncherPage.h" + +#include +#include +#include +#include + +#include "updater/UpdateChecker.h" + +#include "settings/SettingsObject.h" +#include +#include "Application.h" +#include "BuildConfig.h" +#include "ui/themes/ITheme.h" + +#include +#include + +// FIXME: possibly move elsewhere +enum InstSortMode +{ + // Sort alphabetically by name. + Sort_Name, + // Sort by which instance was launched most recently. + Sort_LastLaunch +}; + +LauncherPage::LauncherPage(QWidget *parent) : QWidget(parent), ui(new Ui::LauncherPage) +{ + ui->setupUi(this); + auto origForeground = ui->fontPreview->palette().color(ui->fontPreview->foregroundRole()); + auto origBackground = ui->fontPreview->palette().color(ui->fontPreview->backgroundRole()); + m_colors.reset(new LogColorCache(origForeground, origBackground)); + + ui->sortingModeGroup->setId(ui->sortByNameBtn, Sort_Name); + ui->sortingModeGroup->setId(ui->sortLastLaunchedBtn, Sort_LastLaunch); + + defaultFormat = new QTextCharFormat(ui->fontPreview->currentCharFormat()); + + m_languageModel = APPLICATION->translations(); + loadSettings(); + + if(BuildConfig.UPDATER_ENABLED) + { + QObject::connect(APPLICATION->updateChecker().get(), &UpdateChecker::channelListLoaded, this, &LauncherPage::refreshUpdateChannelList); + + if (APPLICATION->updateChecker()->hasChannels()) + { + refreshUpdateChannelList(); + } + else + { + APPLICATION->updateChecker()->updateChanList(false); + } + } + else + { + ui->updateSettingsBox->setHidden(true); + } + // Analytics + if(BuildConfig.ANALYTICS_ID.isEmpty()) + { + ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->analyticsTab)); + } + connect(ui->fontSizeBox, SIGNAL(valueChanged(int)), SLOT(refreshFontPreview())); + connect(ui->consoleFont, SIGNAL(currentFontChanged(QFont)), SLOT(refreshFontPreview())); + + //move mac data button + QFile file(QDir::current().absolutePath() + "/dontmovemacdata"); + if (!file.exists()) + { + ui->migrateDataFolderMacBtn->setVisible(false); + } +} + +LauncherPage::~LauncherPage() +{ + delete ui; + delete defaultFormat; +} + +bool LauncherPage::apply() +{ + applySettings(); + return true; +} + +void LauncherPage::on_instDirBrowseBtn_clicked() +{ + QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Instance Folder"), ui->instDirTextBox->text()); + + // do not allow current dir - it's dirty. Do not allow dirs that don't exist + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) + { + QString cooked_dir = FS::NormalizePath(raw_dir); + if (FS::checkProblemticPathJava(QDir(cooked_dir))) + { + QMessageBox warning; + warning.setText(tr("You're trying to specify an instance folder which\'s path " + "contains at least one \'!\'. " + "Java is known to cause problems if that is the case, your " + "instances (probably) won't start!")); + warning.setInformativeText( + tr("Do you really want to use this path? " + "Selecting \"No\" will close this and not alter your instance path.")); + warning.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + int result = warning.exec(); + if (result == QMessageBox::Yes) + { + ui->instDirTextBox->setText(cooked_dir); + } + } + else + { + ui->instDirTextBox->setText(cooked_dir); + } + } +} + +void LauncherPage::on_iconsDirBrowseBtn_clicked() +{ + QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Icons Folder"), ui->iconsDirTextBox->text()); + + // do not allow current dir - it's dirty. Do not allow dirs that don't exist + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) + { + QString cooked_dir = FS::NormalizePath(raw_dir); + ui->iconsDirTextBox->setText(cooked_dir); + } +} +void LauncherPage::on_modsDirBrowseBtn_clicked() +{ + QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Mods Folder"), ui->modsDirTextBox->text()); + + // do not allow current dir - it's dirty. Do not allow dirs that don't exist + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) + { + QString cooked_dir = FS::NormalizePath(raw_dir); + ui->modsDirTextBox->setText(cooked_dir); + } +} +void LauncherPage::on_migrateDataFolderMacBtn_clicked() +{ + QFile file(QDir::current().absolutePath() + "/dontmovemacdata"); + file.remove(); + QProcess::startDetached(qApp->arguments()[0]); + qApp->quit(); +} + +void LauncherPage::refreshUpdateChannelList() +{ + // Stop listening for selection changes. It's going to change a lot while we update it and + // we don't need to update the + // description label constantly. + QObject::disconnect(ui->updateChannelComboBox, SIGNAL(currentIndexChanged(int)), this, + SLOT(updateChannelSelectionChanged(int))); + + QList channelList = APPLICATION->updateChecker()->getChannelList(); + ui->updateChannelComboBox->clear(); + int selection = -1; + for (int i = 0; i < channelList.count(); i++) + { + UpdateChecker::ChannelListEntry entry = channelList.at(i); + + // When it comes to selection, we'll rely on the indexes of a channel entry being the + // same in the + // combo box as it is in the update checker's channel list. + // This probably isn't very safe, but the channel list doesn't change often enough (or + // at all) for + // this to be a big deal. Hope it doesn't break... + ui->updateChannelComboBox->addItem(entry.name); + + // If the update channel we just added was the selected one, set the current index in + // the combo box to it. + if (entry.id == m_currentUpdateChannel) + { + qDebug() << "Selected index" << i << "channel id" << m_currentUpdateChannel; + selection = i; + } + } + + ui->updateChannelComboBox->setCurrentIndex(selection); + + // Start listening for selection changes again and update the description label. + QObject::connect(ui->updateChannelComboBox, SIGNAL(currentIndexChanged(int)), this, + SLOT(updateChannelSelectionChanged(int))); + refreshUpdateChannelDesc(); + + // Now that we've updated the channel list, we can enable the combo box. + // It starts off disabled so that if the channel list hasn't been loaded, it will be + // disabled. + ui->updateChannelComboBox->setEnabled(true); +} + +void LauncherPage::updateChannelSelectionChanged(int index) +{ + refreshUpdateChannelDesc(); +} + +void LauncherPage::refreshUpdateChannelDesc() +{ + // Get the channel list. + QList channelList = APPLICATION->updateChecker()->getChannelList(); + int selectedIndex = ui->updateChannelComboBox->currentIndex(); + if (selectedIndex < 0) + { + return; + } + if (selectedIndex < channelList.count()) + { + // Find the channel list entry with the given index. + UpdateChecker::ChannelListEntry selected = channelList.at(selectedIndex); + + // Set the description text. + ui->updateChannelDescLabel->setText(selected.description); + + // Set the currently selected channel ID. + m_currentUpdateChannel = selected.id; + } +} + +void LauncherPage::applySettings() +{ + auto s = APPLICATION->settings(); + + if (ui->resetNotificationsBtn->isChecked()) + { + s->set("ShownNotifications", QString()); + } + + // Updates + s->set("AutoUpdate", ui->autoUpdateCheckBox->isChecked()); + s->set("UpdateChannel", m_currentUpdateChannel); + auto original = s->get("IconTheme").toString(); + //FIXME: make generic + switch (ui->themeComboBox->currentIndex()) + { + case 1: + s->set("IconTheme", "pe_dark"); + break; + case 2: + s->set("IconTheme", "pe_light"); + break; + case 3: + s->set("IconTheme", "pe_blue"); + break; + case 4: + s->set("IconTheme", "pe_colored"); + break; + case 5: + s->set("IconTheme", "OSX"); + break; + case 6: + s->set("IconTheme", "iOS"); + break; + case 7: + s->set("IconTheme", "flat"); + break; + case 8: + s->set("IconTheme", "custom"); + break; + case 0: + default: + s->set("IconTheme", "multimc"); + break; + } + + if(original != s->get("IconTheme")) + { + APPLICATION->setIconTheme(s->get("IconTheme").toString()); + } + + auto originalAppTheme = s->get("ApplicationTheme").toString(); + auto newAppTheme = ui->themeComboBoxColors->currentData().toString(); + if(originalAppTheme != newAppTheme) + { + s->set("ApplicationTheme", newAppTheme); + APPLICATION->setApplicationTheme(newAppTheme, false); + } + + // Console settings + s->set("ShowConsole", ui->showConsoleCheck->isChecked()); + s->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked()); + s->set("ShowConsoleOnError", ui->showConsoleErrorCheck->isChecked()); + QString consoleFontFamily = ui->consoleFont->currentFont().family(); + s->set("ConsoleFont", consoleFontFamily); + s->set("ConsoleFontSize", ui->fontSizeBox->value()); + s->set("ConsoleMaxLines", ui->lineLimitSpinBox->value()); + s->set("ConsoleOverflowStop", ui->checkStopLogging->checkState() != Qt::Unchecked); + + // Folders + // TODO: Offer to move instances to new instance folder. + s->set("InstanceDir", ui->instDirTextBox->text()); + s->set("CentralModsDir", ui->modsDirTextBox->text()); + s->set("IconsDir", ui->iconsDirTextBox->text()); + + auto sortMode = (InstSortMode)ui->sortingModeGroup->checkedId(); + switch (sortMode) + { + case Sort_LastLaunch: + s->set("InstSortMode", "LastLaunch"); + break; + case Sort_Name: + default: + s->set("InstSortMode", "Name"); + break; + } + + // Analytics + if(!BuildConfig.ANALYTICS_ID.isEmpty()) + { + s->set("Analytics", ui->analyticsCheck->isChecked()); + } +} +void LauncherPage::loadSettings() +{ + auto s = APPLICATION->settings(); + // Updates + ui->autoUpdateCheckBox->setChecked(s->get("AutoUpdate").toBool()); + m_currentUpdateChannel = s->get("UpdateChannel").toString(); + //FIXME: make generic + auto theme = s->get("IconTheme").toString(); + if (theme == "pe_dark") + { + ui->themeComboBox->setCurrentIndex(1); + } + else if (theme == "pe_light") + { + ui->themeComboBox->setCurrentIndex(2); + } + else if (theme == "pe_blue") + { + ui->themeComboBox->setCurrentIndex(3); + } + else if (theme == "pe_colored") + { + ui->themeComboBox->setCurrentIndex(4); + } + else if (theme == "OSX") + { + ui->themeComboBox->setCurrentIndex(5); + } + else if (theme == "iOS") + { + ui->themeComboBox->setCurrentIndex(6); + } + else if (theme == "flat") + { + ui->themeComboBox->setCurrentIndex(7); + } + else if (theme == "custom") + { + ui->themeComboBox->setCurrentIndex(8); + } + else + { + ui->themeComboBox->setCurrentIndex(0); + } + + { + auto currentTheme = s->get("ApplicationTheme").toString(); + auto themes = APPLICATION->getValidApplicationThemes(); + int idx = 0; + for(auto &theme: themes) + { + ui->themeComboBoxColors->addItem(theme->name(), theme->id()); + if(currentTheme == theme->id()) + { + ui->themeComboBoxColors->setCurrentIndex(idx); + } + idx++; + } + } + + // Console settings + ui->showConsoleCheck->setChecked(s->get("ShowConsole").toBool()); + ui->autoCloseConsoleCheck->setChecked(s->get("AutoCloseConsole").toBool()); + ui->showConsoleErrorCheck->setChecked(s->get("ShowConsoleOnError").toBool()); + QString fontFamily = APPLICATION->settings()->get("ConsoleFont").toString(); + QFont consoleFont(fontFamily); + ui->consoleFont->setCurrentFont(consoleFont); + + bool conversionOk = true; + int fontSize = APPLICATION->settings()->get("ConsoleFontSize").toInt(&conversionOk); + if(!conversionOk) + { + fontSize = 11; + } + ui->fontSizeBox->setValue(fontSize); + refreshFontPreview(); + ui->lineLimitSpinBox->setValue(s->get("ConsoleMaxLines").toInt()); + ui->checkStopLogging->setChecked(s->get("ConsoleOverflowStop").toBool()); + + // Folders + ui->instDirTextBox->setText(s->get("InstanceDir").toString()); + ui->modsDirTextBox->setText(s->get("CentralModsDir").toString()); + ui->iconsDirTextBox->setText(s->get("IconsDir").toString()); + + QString sortMode = s->get("InstSortMode").toString(); + + if (sortMode == "LastLaunch") + { + ui->sortLastLaunchedBtn->setChecked(true); + } + else + { + ui->sortByNameBtn->setChecked(true); + } + + // Analytics + if(!BuildConfig.ANALYTICS_ID.isEmpty()) + { + ui->analyticsCheck->setChecked(s->get("Analytics").toBool()); + } +} + +void LauncherPage::refreshFontPreview() +{ + int fontSize = ui->fontSizeBox->value(); + QString fontFamily = ui->consoleFont->currentFont().family(); + ui->fontPreview->clear(); + defaultFormat->setFont(QFont(fontFamily, fontSize)); + { + QTextCharFormat format(*defaultFormat); + format.setForeground(m_colors->getFront(MessageLevel::Error)); + // append a paragraph/line + auto workCursor = ui->fontPreview->textCursor(); + workCursor.movePosition(QTextCursor::End); + workCursor.insertText(tr("[Something/ERROR] A spooky error!"), format); + workCursor.insertBlock(); + } + { + QTextCharFormat format(*defaultFormat); + format.setForeground(m_colors->getFront(MessageLevel::Message)); + // append a paragraph/line + auto workCursor = ui->fontPreview->textCursor(); + workCursor.movePosition(QTextCursor::End); + workCursor.insertText(tr("[Test/INFO] A harmless message..."), format); + workCursor.insertBlock(); + } + { + QTextCharFormat format(*defaultFormat); + format.setForeground(m_colors->getFront(MessageLevel::Warning)); + // append a paragraph/line + auto workCursor = ui->fontPreview->textCursor(); + workCursor.movePosition(QTextCursor::End); + workCursor.insertText(tr("[Something/WARN] A not so spooky warning."), format); + workCursor.insertBlock(); + } +} diff --git a/launcher/ui/pages/global/LauncherPage.h b/launcher/ui/pages/global/LauncherPage.h new file mode 100644 index 00000000..4d0cf3c9 --- /dev/null +++ b/launcher/ui/pages/global/LauncherPage.h @@ -0,0 +1,103 @@ +/* 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 +#include + +#include "java/JavaChecker.h" +#include "ui/pages/BasePage.h" +#include +#include "ui/ColorCache.h" +#include + +class QTextCharFormat; +class SettingsObject; + +namespace Ui +{ +class LauncherPage; +} + +class LauncherPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit LauncherPage(QWidget *parent = 0); + ~LauncherPage(); + + QString displayName() const override + { + return "Launcher"; + } + QIcon icon() const override + { + return APPLICATION->getThemedIcon("launcher"); + } + QString id() const override + { + return "launcher-settings"; + } + QString helpPage() const override + { + return "Launcher-settings"; + } + bool apply() override; + +private: + void applySettings(); + void loadSettings(); + +private +slots: + void on_instDirBrowseBtn_clicked(); + void on_modsDirBrowseBtn_clicked(); + void on_iconsDirBrowseBtn_clicked(); + void on_migrateDataFolderMacBtn_clicked(); + + /*! + * Updates the list of update channels in the combo box. + */ + void refreshUpdateChannelList(); + + /*! + * Updates the channel description label. + */ + void refreshUpdateChannelDesc(); + + /*! + * Updates the font preview + */ + void refreshFontPreview(); + + void updateChannelSelectionChanged(int index); + +private: + Ui::LauncherPage *ui; + + /*! + * Stores the currently selected update channel. + */ + QString m_currentUpdateChannel; + + // default format for the font preview... + QTextCharFormat *defaultFormat; + + std::unique_ptr m_colors; + + std::shared_ptr m_languageModel; +}; diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui new file mode 100644 index 00000000..62a66d73 --- /dev/null +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -0,0 +1,584 @@ + + + LauncherPage + + + + 0 + 0 + 514 + 629 + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + QTabWidget::Rounded + + + 0 + + + + Features + + + + + + Update Settings + + + + + + Check for updates on start? + + + + + + + Up&date Channel: + + + updateChannelComboBox + + + + + + + false + + + + + + + No channel selected. + + + true + + + + + + + + + + Folders + + + + + + I&nstances: + + + instDirTextBox + + + + + + + + + + ... + + + + + + + &Mods: + + + modsDirTextBox + + + + + + + + + + ... + + + + + + + + + + &Icons: + + + iconsDirTextBox + + + + + + + ... + + + + + + + + + + Move the data to new location (will restart the launcher) + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + User Interface + + + + + + Launcher notifications + + + + + + Reset hidden notifications + + + true + + + + + + + + + + true + + + Instance view sorting mode + + + + + + By &last launched + + + sortingModeGroup + + + + + + + By &name + + + sortingModeGroup + + + + + + + + + + Theme + + + + + + &Icons + + + themeComboBox + + + + + + + + 0 + 0 + + + + Qt::StrongFocus + + + + Default + + + + + Simple (Dark Icons) + + + + + Simple (Light Icons) + + + + + Simple (Blue Icons) + + + + + Simple (Colored Icons) + + + + + OSX + + + + + iOS + + + + + Flat + + + + + Custom + + + + + + + + + 0 + 0 + + + + Qt::StrongFocus + + + + + + + Colors + + + themeComboBoxColors + + + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + Console + + + + + + Console Settings + + + + + + Show console while the game is running? + + + + + + + Automatically close console when the game quits? + + + + + + + Show console when the game crashes? + + + + + + + + + + History limit + + + + + + Stop logging when log overflows + + + + + + + + 0 + 0 + + + + lines + + + 10000 + + + 1000000 + + + 10000 + + + 100000 + + + + + + + + + + + 0 + 0 + + + + Console font + + + + + + + 0 + 0 + + + + Qt::ScrollBarAlwaysOff + + + false + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + 0 + 0 + + + + + + + + 5 + + + 16 + + + 11 + + + + + + + + + + + Analytics + + + + + + Analytics Settings + + + + + + Send anonymous usage statistics? + + + + + + + Qt::Horizontal + + + + + + + <html><head/> +<body> +<p>The launcher sends anonymous usage statistics on every start of the application.</p><p>The following data is collected:</p> +<ul> +<li>Launcher version.</li> +<li>Operating system name, version and architecture.</li> +<li>CPU architecture (kernel architecture on linux).</li> +<li>Size of system memory.</li> +<li>Java version, architecture and memory settings.</li> +</ul> +</body></html> + + + true + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + tabWidget + autoUpdateCheckBox + updateChannelComboBox + instDirTextBox + instDirBrowseBtn + modsDirTextBox + modsDirBrowseBtn + iconsDirTextBox + iconsDirBrowseBtn + resetNotificationsBtn + sortLastLaunchedBtn + sortByNameBtn + themeComboBox + themeComboBoxColors + showConsoleCheck + autoCloseConsoleCheck + showConsoleErrorCheck + lineLimitSpinBox + checkStopLogging + consoleFont + fontSizeBox + fontPreview + + + + + + + diff --git a/launcher/ui/pages/global/MinecraftPage.cpp b/launcher/ui/pages/global/MinecraftPage.cpp new file mode 100644 index 00000000..c763f8ac --- /dev/null +++ b/launcher/ui/pages/global/MinecraftPage.cpp @@ -0,0 +1,91 @@ +/* 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 "MinecraftPage.h" +#include "ui_MinecraftPage.h" + +#include +#include +#include + +#include "settings/SettingsObject.h" +#include "Application.h" + +MinecraftPage::MinecraftPage(QWidget *parent) : QWidget(parent), ui(new Ui::MinecraftPage) +{ + ui->setupUi(this); + ui->tabWidget->tabBar()->hide(); + loadSettings(); + updateCheckboxStuff(); +} + +MinecraftPage::~MinecraftPage() +{ + delete ui; +} + +bool MinecraftPage::apply() +{ + applySettings(); + return true; +} + +void MinecraftPage::updateCheckboxStuff() +{ + ui->windowWidthSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked()); + ui->windowHeightSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked()); +} + +void MinecraftPage::on_maximizedCheckBox_clicked(bool checked) +{ + Q_UNUSED(checked); + updateCheckboxStuff(); +} + +void MinecraftPage::applySettings() +{ + auto s = APPLICATION->settings(); + + // Window Size + s->set("LaunchMaximized", ui->maximizedCheckBox->isChecked()); + s->set("MinecraftWinWidth", ui->windowWidthSpinBox->value()); + s->set("MinecraftWinHeight", ui->windowHeightSpinBox->value()); + + // Native library workarounds + s->set("UseNativeOpenAL", ui->useNativeOpenALCheck->isChecked()); + s->set("UseNativeGLFW", ui->useNativeGLFWCheck->isChecked()); + + // Game time + s->set("ShowGameTime", ui->showGameTime->isChecked()); + s->set("ShowGlobalGameTime", ui->showGlobalGameTime->isChecked()); + s->set("RecordGameTime", ui->recordGameTime->isChecked()); +} + +void MinecraftPage::loadSettings() +{ + auto s = APPLICATION->settings(); + + // Window Size + ui->maximizedCheckBox->setChecked(s->get("LaunchMaximized").toBool()); + ui->windowWidthSpinBox->setValue(s->get("MinecraftWinWidth").toInt()); + ui->windowHeightSpinBox->setValue(s->get("MinecraftWinHeight").toInt()); + + ui->useNativeOpenALCheck->setChecked(s->get("UseNativeOpenAL").toBool()); + ui->useNativeGLFWCheck->setChecked(s->get("UseNativeGLFW").toBool()); + + ui->showGameTime->setChecked(s->get("ShowGameTime").toBool()); + ui->showGlobalGameTime->setChecked(s->get("ShowGlobalGameTime").toBool()); + ui->recordGameTime->setChecked(s->get("RecordGameTime").toBool()); +} diff --git a/launcher/ui/pages/global/MinecraftPage.h b/launcher/ui/pages/global/MinecraftPage.h new file mode 100644 index 00000000..42626d94 --- /dev/null +++ b/launcher/ui/pages/global/MinecraftPage.h @@ -0,0 +1,70 @@ +/* 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 +#include + +#include "java/JavaChecker.h" +#include "ui/pages/BasePage.h" +#include + +class SettingsObject; + +namespace Ui +{ +class MinecraftPage; +} + +class MinecraftPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit MinecraftPage(QWidget *parent = 0); + ~MinecraftPage(); + + QString displayName() const override + { + return tr("Minecraft"); + } + QIcon icon() const override + { + return APPLICATION->getThemedIcon("minecraft"); + } + QString id() const override + { + return "minecraft-settings"; + } + QString helpPage() const override + { + return "Minecraft-settings"; + } + bool apply() override; + +private: + void updateCheckboxStuff(); + void applySettings(); + void loadSettings(); + +private +slots: + void on_maximizedCheckBox_clicked(bool checked); + +private: + Ui::MinecraftPage *ui; + +}; diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui new file mode 100644 index 00000000..857b8cfb --- /dev/null +++ b/launcher/ui/pages/global/MinecraftPage.ui @@ -0,0 +1,196 @@ + + + MinecraftPage + + + + 0 + 0 + 936 + 1134 + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QTabWidget::Rounded + + + 0 + + + + Minecraft + + + + + + Window Size + + + + + + Start Minecraft maximized? + + + + + + + + + Window hei&ght: + + + windowHeightSpinBox + + + + + + + W&indow width: + + + windowWidthSpinBox + + + + + + + 1 + + + 65536 + + + 1 + + + 854 + + + + + + + 1 + + + 65536 + + + 480 + + + + + + + + + + + + Native library workarounds + + + + + + Use system installation of GLFW + + + + + + + Use system installation of OpenAL + + + + + + + + + + Game time + + + + + + Show time spent playing instances + + + + + + + Show time spent playing across all instances + + + + + + + Record time spent playing instances + + + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + + + + tabWidget + maximizedCheckBox + windowWidthSpinBox + windowHeightSpinBox + useNativeGLFWCheck + useNativeOpenALCheck + + + + diff --git a/launcher/ui/pages/global/PasteEEPage.cpp b/launcher/ui/pages/global/PasteEEPage.cpp new file mode 100644 index 00000000..4b375d9a --- /dev/null +++ b/launcher/ui/pages/global/PasteEEPage.cpp @@ -0,0 +1,81 @@ +/* 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 "PasteEEPage.h" +#include "ui_PasteEEPage.h" + +#include +#include +#include +#include + +#include "settings/SettingsObject.h" +#include "tools/BaseProfiler.h" +#include "Application.h" + +PasteEEPage::PasteEEPage(QWidget *parent) : + QWidget(parent), + ui(new Ui::PasteEEPage) +{ + ui->setupUi(this); + ui->tabWidget->tabBar()->hide();\ + connect(ui->customAPIkeyEdit, &QLineEdit::textEdited, this, &PasteEEPage::textEdited); + loadSettings(); +} + +PasteEEPage::~PasteEEPage() +{ + delete ui; +} + +void PasteEEPage::loadSettings() +{ + auto s = APPLICATION->settings(); + QString keyToUse = s->get("PasteEEAPIKey").toString(); + if(keyToUse == "multimc") + { + ui->multimcButton->setChecked(true); + } + else + { + ui->customButton->setChecked(true); + ui->customAPIkeyEdit->setText(keyToUse); + } +} + +void PasteEEPage::applySettings() +{ + auto s = APPLICATION->settings(); + + QString pasteKeyToUse; + if (ui->customButton->isChecked()) + pasteKeyToUse = ui->customAPIkeyEdit->text(); + else + { + pasteKeyToUse = "multimc"; + } + s->set("PasteEEAPIKey", pasteKeyToUse); +} + +bool PasteEEPage::apply() +{ + applySettings(); + return true; +} + +void PasteEEPage::textEdited(const QString& text) +{ + ui->customButton->setChecked(true); +} diff --git a/launcher/ui/pages/global/PasteEEPage.h b/launcher/ui/pages/global/PasteEEPage.h new file mode 100644 index 00000000..a1c7d434 --- /dev/null +++ b/launcher/ui/pages/global/PasteEEPage.h @@ -0,0 +1,62 @@ +/* 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 + +#include "ui/pages/BasePage.h" +#include + +namespace Ui { +class PasteEEPage; +} + +class PasteEEPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit PasteEEPage(QWidget *parent = 0); + ~PasteEEPage(); + + QString displayName() const override + { + return tr("Log Upload"); + } + QIcon icon() const override + { + return APPLICATION->getThemedIcon("log"); + } + QString id() const override + { + return "log-upload"; + } + QString helpPage() const override + { + return "Log-Upload"; + } + virtual bool apply() override; + +private: + void loadSettings(); + void applySettings(); + +private slots: + void textEdited(const QString &text); + +private: + Ui::PasteEEPage *ui; +}; diff --git a/launcher/ui/pages/global/PasteEEPage.ui b/launcher/ui/pages/global/PasteEEPage.ui new file mode 100644 index 00000000..10883781 --- /dev/null +++ b/launcher/ui/pages/global/PasteEEPage.ui @@ -0,0 +1,128 @@ + + + PasteEEPage + + + + 0 + 0 + 491 + 474 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + Tab 1 + + + + + + paste.ee API key + + + + + + MultiMC key - 12MB &upload limit + + + pasteButtonGroup + + + + + + + &Your own key - 12MB upload limit: + + + pasteButtonGroup + + + + + + + QLineEdit::Password + + + Paste your API key here! + + + + + + + Qt::Horizontal + + + + + + + <html><head/><body><p><a href="https://paste.ee">paste.ee</a> is used by MultiMC for log uploads. If you have a <a href="https://paste.ee">paste.ee</a> account, you can add your API key here and have your uploaded logs paired with your account.</p></body></html> + + + Qt::RichText + + + true + + + true + + + + + + + + + + Qt::Vertical + + + + 20 + 216 + + + + + + + + + + + + tabWidget + multimcButton + customButton + customAPIkeyEdit + + + + + + + diff --git a/launcher/ui/pages/global/ProxyPage.cpp b/launcher/ui/pages/global/ProxyPage.cpp new file mode 100644 index 00000000..5bc8199e --- /dev/null +++ b/launcher/ui/pages/global/ProxyPage.cpp @@ -0,0 +1,106 @@ +/* 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 "ProxyPage.h" +#include "ui_ProxyPage.h" + +#include + +#include "settings/SettingsObject.h" +#include "Application.h" +#include "Application.h" + +ProxyPage::ProxyPage(QWidget *parent) : QWidget(parent), ui(new Ui::ProxyPage) +{ + ui->setupUi(this); + ui->tabWidget->tabBar()->hide(); + loadSettings(); + updateCheckboxStuff(); + + connect(ui->proxyGroup, SIGNAL(buttonClicked(int)), SLOT(proxyChanged(int))); +} + +ProxyPage::~ProxyPage() +{ + delete ui; +} + +bool ProxyPage::apply() +{ + applySettings(); + return true; +} + +void ProxyPage::updateCheckboxStuff() +{ + ui->proxyAddrBox->setEnabled(!ui->proxyNoneBtn->isChecked() && + !ui->proxyDefaultBtn->isChecked()); + ui->proxyAuthBox->setEnabled(!ui->proxyNoneBtn->isChecked() && + !ui->proxyDefaultBtn->isChecked()); +} + +void ProxyPage::proxyChanged(int) +{ + updateCheckboxStuff(); +} + +void ProxyPage::applySettings() +{ + auto s = APPLICATION->settings(); + + // Proxy + QString proxyType = "None"; + if (ui->proxyDefaultBtn->isChecked()) + proxyType = "Default"; + else if (ui->proxyNoneBtn->isChecked()) + proxyType = "None"; + else if (ui->proxySOCKS5Btn->isChecked()) + proxyType = "SOCKS5"; + else if (ui->proxyHTTPBtn->isChecked()) + proxyType = "HTTP"; + + s->set("ProxyType", proxyType); + s->set("ProxyAddr", ui->proxyAddrEdit->text()); + s->set("ProxyPort", ui->proxyPortEdit->value()); + s->set("ProxyUser", ui->proxyUserEdit->text()); + s->set("ProxyPass", ui->proxyPassEdit->text()); + + APPLICATION->updateProxySettings( + proxyType, + ui->proxyAddrEdit->text(), + ui->proxyPortEdit->value(), + ui->proxyUserEdit->text(), + ui->proxyPassEdit->text() + ); +} +void ProxyPage::loadSettings() +{ + auto s = APPLICATION->settings(); + // Proxy + QString proxyType = s->get("ProxyType").toString(); + if (proxyType == "Default") + ui->proxyDefaultBtn->setChecked(true); + else if (proxyType == "None") + ui->proxyNoneBtn->setChecked(true); + else if (proxyType == "SOCKS5") + ui->proxySOCKS5Btn->setChecked(true); + else if (proxyType == "HTTP") + ui->proxyHTTPBtn->setChecked(true); + + ui->proxyAddrEdit->setText(s->get("ProxyAddr").toString()); + ui->proxyPortEdit->setValue(s->get("ProxyPort").value()); + ui->proxyUserEdit->setText(s->get("ProxyUser").toString()); + ui->proxyPassEdit->setText(s->get("ProxyPass").toString()); +} diff --git a/launcher/ui/pages/global/ProxyPage.h b/launcher/ui/pages/global/ProxyPage.h new file mode 100644 index 00000000..6698c349 --- /dev/null +++ b/launcher/ui/pages/global/ProxyPage.h @@ -0,0 +1,66 @@ +/* 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 +#include + +#include "ui/pages/BasePage.h" +#include + +namespace Ui +{ +class ProxyPage; +} + +class ProxyPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit ProxyPage(QWidget *parent = 0); + ~ProxyPage(); + + QString displayName() const override + { + return tr("Proxy"); + } + QIcon icon() const override + { + return APPLICATION->getThemedIcon("proxy"); + } + QString id() const override + { + return "proxy-settings"; + } + QString helpPage() const override + { + return "Proxy-settings"; + } + bool apply() override; + +private: + void updateCheckboxStuff(); + void applySettings(); + void loadSettings(); + +private +slots: + void proxyChanged(int); + +private: + Ui::ProxyPage *ui; +}; diff --git a/launcher/ui/pages/global/ProxyPage.ui b/launcher/ui/pages/global/ProxyPage.ui new file mode 100644 index 00000000..347fa86c --- /dev/null +++ b/launcher/ui/pages/global/ProxyPage.ui @@ -0,0 +1,203 @@ + + + ProxyPage + + + + 0 + 0 + 598 + 617 + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + This only applies to the launcher. Minecraft does not accept proxy settings. + + + Qt::AlignCenter + + + true + + + + + + + Type + + + + + + Uses your system's default proxy settings. + + + &Default + + + proxyGroup + + + + + + + &None + + + proxyGroup + + + + + + + SOC&KS5 + + + proxyGroup + + + + + + + H&TTP + + + proxyGroup + + + + + + + + + + Address and Port + + + + + + 127.0.0.1 + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + QAbstractSpinBox::PlusMinus + + + 65535 + + + 8080 + + + + + + + + + + Authentication + + + + + + + + + Username: + + + + + + + Password: + + + + + + + QLineEdit::Password + + + + + + + Note: Proxy username and password are stored in plain text inside the launcher's configuration file! + + + true + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + -- cgit