aboutsummaryrefslogtreecommitdiff
path: root/launcher/ui/pages/global
diff options
context:
space:
mode:
Diffstat (limited to 'launcher/ui/pages/global')
-rw-r--r--launcher/ui/pages/global/AccountListPage.cpp260
-rw-r--r--launcher/ui/pages/global/AccountListPage.h85
-rw-r--r--launcher/ui/pages/global/AccountListPage.ui129
-rw-r--r--launcher/ui/pages/global/CustomCommandsPage.cpp51
-rw-r--r--launcher/ui/pages/global/CustomCommandsPage.h55
-rw-r--r--launcher/ui/pages/global/ExternalToolsPage.cpp233
-rw-r--r--launcher/ui/pages/global/ExternalToolsPage.h74
-rw-r--r--launcher/ui/pages/global/ExternalToolsPage.ui194
-rw-r--r--launcher/ui/pages/global/JavaPage.cpp153
-rw-r--r--launcher/ui/pages/global/JavaPage.h72
-rw-r--r--launcher/ui/pages/global/JavaPage.ui260
-rw-r--r--launcher/ui/pages/global/LanguagePage.cpp51
-rw-r--r--launcher/ui/pages/global/LanguagePage.h60
-rw-r--r--launcher/ui/pages/global/LauncherPage.cpp466
-rw-r--r--launcher/ui/pages/global/LauncherPage.h103
-rw-r--r--launcher/ui/pages/global/LauncherPage.ui584
-rw-r--r--launcher/ui/pages/global/MinecraftPage.cpp91
-rw-r--r--launcher/ui/pages/global/MinecraftPage.h70
-rw-r--r--launcher/ui/pages/global/MinecraftPage.ui196
-rw-r--r--launcher/ui/pages/global/PasteEEPage.cpp81
-rw-r--r--launcher/ui/pages/global/PasteEEPage.h62
-rw-r--r--launcher/ui/pages/global/PasteEEPage.ui128
-rw-r--r--launcher/ui/pages/global/ProxyPage.cpp106
-rw-r--r--launcher/ui/pages/global/ProxyPage.h66
-rw-r--r--launcher/ui/pages/global/ProxyPage.ui203
25 files changed, 3833 insertions, 0 deletions
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 <QItemSelectionModel>
+#include <QMenu>
+
+#include <QDebug>
+
+#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<MinecraftAccountPtr>();
+ AuthSessionPtr session = std::make_shared<AuthSession>();
+ 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<MinecraftAccountPtr>();
+ 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<MinecraftAccountPtr>();
+ 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<MinecraftAccountPtr>();
+ 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<AuthSession>();
+ MinecraftAccountPtr account = selected.data(AccountList::PointerRole).value<MinecraftAccountPtr>();
+ 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<SkinDelete>(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 <QMainWindow>
+#include <memory>
+
+#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<AccountList> 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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AccountListPage</class>
+ <widget class="QMainWindow" name="AccountListPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>600</height>
+ </rect>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="VersionListView" name="listView">
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
+ <property name="itemsExpandable">
+ <bool>false</bool>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <attribute name="headerStretchLastSection">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="WideBar" name="toolBar">
+ <attribute name="toolBarArea">
+ <enum>RightToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>false</bool>
+ </attribute>
+ <addaction name="actionAddMicrosoft"/>
+ <addaction name="actionAddMojang"/>
+ <addaction name="actionRefresh"/>
+ <addaction name="actionRemove"/>
+ <addaction name="actionSetDefault"/>
+ <addaction name="actionNoDefault"/>
+ <addaction name="separator"/>
+ <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>Remove</string>
+ </property>
+ </action>
+ <action name="actionSetDefault">
+ <property name="text">
+ <string>Set Default</string>
+ </property>
+ </action>
+ <action name="actionNoDefault">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>No Default</string>
+ </property>
+ </action>
+ <action name="actionUploadSkin">
+ <property name="text">
+ <string>Upload Skin</string>
+ </property>
+ </action>
+ <action name="actionDeleteSkin">
+ <property name="text">
+ <string>Delete Skin</string>
+ </property>
+ <property name="toolTip">
+ <string>Delete the currently active skin and go back to the default one</string>
+ </property>
+ </action>
+ <action name="actionAddMicrosoft">
+ <property name="text">
+ <string>Add Microsoft</string>
+ </property>
+ </action>
+ <action name="actionRefresh">
+ <property name="text">
+ <string>Refresh</string>
+ </property>
+ <property name="toolTip">
+ <string>Refresh the account tokens</string>
+ </property>
+ </action>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>VersionListView</class>
+ <extends>QTreeView</extends>
+ <header>ui/widgets/VersionListView.h</header>
+ </customwidget>
+ <customwidget>
+ <class>WideBar</class>
+ <extends>QToolBar</extends>
+ <header>ui/widgets/WideBar.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
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 <QVBoxLayout>
+#include <QTabWidget>
+#include <QTabBar>
+
+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 <memory>
+#include <QDialog>
+
+#include "ui/pages/BasePage.h"
+#include <Application.h>
+#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 <QMessageBox>
+#include <QFileDialog>
+#include <QStandardPaths>
+#include <QTabBar>
+
+#include "settings/SettingsObject.h"
+#include "tools/BaseProfiler.h"
+#include <FileSystem.h>
+#include "Application.h"
+#include <tools/MCEditTool.h>
+
+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/