diff options
| -rw-r--r-- | CMakeLists.txt | 12 | ||||
| -rw-r--r-- | MultiMC.cpp | 24 | ||||
| -rw-r--r-- | MultiMC.h | 13 | ||||
| -rw-r--r-- | depends/launcher/org/multimc/EntryPoint.java | 36 | ||||
| -rw-r--r-- | gui/MainWindow.cpp | 118 | ||||
| -rw-r--r-- | gui/MainWindow.h | 9 | ||||
| -rw-r--r-- | gui/MainWindow.ui | 3 | ||||
| -rw-r--r-- | gui/dialogs/SettingsDialog.cpp | 230 | ||||
| -rw-r--r-- | gui/dialogs/SettingsDialog.h | 7 | ||||
| -rw-r--r-- | gui/dialogs/SettingsDialog.ui | 133 | ||||
| -rw-r--r-- | logic/LegacyInstance.cpp | 2 | ||||
| -rw-r--r-- | logic/MinecraftProcess.cpp | 16 | ||||
| -rw-r--r-- | logic/MinecraftProcess.h | 12 | ||||
| -rw-r--r-- | logic/OneSixInstance.cpp | 2 | ||||
| -rw-r--r-- | logic/tools/BaseExternalTool.cpp | 77 | ||||
| -rw-r--r-- | logic/tools/BaseExternalTool.h | 57 | ||||
| -rw-r--r-- | logic/tools/BaseProfiler.cpp | 35 | ||||
| -rw-r--r-- | logic/tools/BaseProfiler.h | 36 | ||||
| -rw-r--r-- | logic/tools/JProfiler.cpp | 78 | ||||
| -rw-r--r-- | logic/tools/JProfiler.h | 23 | ||||
| -rw-r--r-- | logic/tools/JVisualVM.cpp | 74 | ||||
| -rw-r--r-- | logic/tools/JVisualVM.h | 23 | ||||
| -rw-r--r-- | logic/tools/MCEditTool.cpp | 77 | ||||
| -rw-r--r-- | logic/tools/MCEditTool.h | 23 |
24 files changed, 1058 insertions, 62 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ea4c27a..0045a41b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -500,6 +500,18 @@ logic/assets/AssetsMigrateTask.h logic/assets/AssetsMigrateTask.cpp logic/assets/AssetsUtils.h logic/assets/AssetsUtils.cpp + +# Tools +logic/tools/BaseExternalTool.h +logic/tools/BaseExternalTool.cpp +logic/tools/MCEditTool.h +logic/tools/MCEditTool.cpp +logic/tools/BaseProfiler.h +logic/tools/BaseProfiler.cpp +logic/tools/JProfiler.h +logic/tools/JProfiler.cpp +logic/tools/JVisualVM.h +logic/tools/JVisualVM.cpp ) diff --git a/MultiMC.cpp b/MultiMC.cpp index 39a4443e..a0745a87 100644 --- a/MultiMC.cpp +++ b/MultiMC.cpp @@ -32,6 +32,10 @@ #include "logic/updater/UpdateChecker.h" #include "logic/updater/NotificationChecker.h" +#include "logic/tools/JProfiler.h" +#include "logic/tools/JVisualVM.h" +#include "logic/tools/MCEditTool.h" + #include "pathutils.h" #include "cmdutils.h" #include <inisettingsobject.h> @@ -42,8 +46,9 @@ using namespace Util::Commandline; MultiMC::MultiMC(int &argc, char **argv, bool root_override) - : QApplication(argc, argv), m_version{VERSION_MAJOR, VERSION_MINOR, VERSION_HOTFIX, - VERSION_BUILD, MultiMCVersion::VERSION_TYPE, VERSION_CHANNEL, BUILD_PLATFORM} + : QApplication(argc, argv), + m_version{VERSION_MAJOR, VERSION_MINOR, VERSION_HOTFIX, VERSION_BUILD, + MultiMCVersion::VERSION_TYPE, VERSION_CHANNEL, BUILD_PLATFORM} { setOrganizationName("MultiMC"); setApplicationName("MultiMC5"); @@ -212,6 +217,21 @@ MultiMC::MultiMC(int &argc, char **argv, bool root_override) // init proxy settings updateProxySettings(); + m_profilers.insert("jprofiler", + std::shared_ptr<BaseProfilerFactory>(new JProfilerFactory())); + m_profilers.insert("jvisualvm", + std::shared_ptr<BaseProfilerFactory>(new JVisualVMFactory())); + for (auto profiler : m_profilers.values()) + { + profiler->registerSettings(m_settings.get()); + } + m_tools.insert("mcedit", + std::shared_ptr<BaseDetachedToolFactory>(new MCEditFactory())); + for (auto tool : m_tools.values()) + { + tool->registerSettings(m_settings.get()); + } + // launch instance, if that's what should be done // WARNING: disabled until further notice /* @@ -23,6 +23,8 @@ class UpdateChecker; class NotificationChecker; class NewsChecker; class StatusChecker; +class BaseProfilerFactory; +class BaseDetachedToolFactory; #if defined(MMC) #undef MMC @@ -130,6 +132,15 @@ public: std::shared_ptr<JavaVersionList> javalist(); + QMap<QString, std::shared_ptr<BaseProfilerFactory>> profilers() + { + return m_profilers; + } + QMap<QString, std::shared_ptr<BaseDetachedToolFactory>> tools() + { + return m_tools; + } + void installUpdates(const QString updateFilesDir, UpdateFlags flags = None); /*! @@ -202,6 +213,8 @@ private: std::shared_ptr<LiteLoaderVersionList> m_liteloaderlist; std::shared_ptr<MinecraftVersionList> m_minecraftlist; std::shared_ptr<JavaVersionList> m_javalist; + QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers; + QMap<QString, std::shared_ptr<BaseDetachedToolFactory>> m_tools; QsLogging::DestinationPtr m_fileDestination; QsLogging::DestinationPtr m_debugDestination; diff --git a/depends/launcher/org/multimc/EntryPoint.java b/depends/launcher/org/multimc/EntryPoint.java index e2721ffa..f9fe68d6 100644 --- a/depends/launcher/org/multimc/EntryPoint.java +++ b/depends/launcher/org/multimc/EntryPoint.java @@ -29,7 +29,8 @@ public class EntryPoint private enum Action { Proceed, - Launch + Launch, + Abort } public static void main(String[] args) @@ -61,27 +62,40 @@ public class EntryPoint private Action parseLine(String inData) throws ParseException { String[] pair = inData.split(" ", 2); + + if(pair.length == 1) + { + String command = pair[0]; + if (pair[0].equals("launch")) + return Action.Launch; + + else if (pair[0].equals("abort")) + return Action.Abort; + + else throw new ParseException(); + } + if(pair.length != 2) throw new ParseException(); String command = pair[0]; String param = pair[1]; - if(command.equals("launch")) + if(command.equals("launcher")) { if(param.equals("legacy")) { m_launcher = new LegacyLauncher(); Utils.log("Using legacy launcher."); Utils.log(); - return Action.Launch; + return Action.Proceed; } if(param.equals("onesix")) { m_launcher = new OneSixLauncher(); Utils.log("Using onesix launcher."); Utils.log(); - return Action.Launch; + return Action.Proceed; } else throw new ParseException(); @@ -105,6 +119,7 @@ public class EntryPoint return 1; } boolean isListening = true; + boolean isAborted = false; // Main loop while (isListening) { @@ -115,7 +130,13 @@ public class EntryPoint inData = buffer.readLine(); if (inData != null) { - if(parseLine(inData) == Action.Launch) + Action a = parseLine(inData); + if(a == Action.Abort) + { + isListening = false; + isAborted = true; + } + if(a == Action.Launch) { isListening = false; } @@ -134,6 +155,11 @@ public class EntryPoint return 1; } } + if(isAborted) + { + System.err.println("Launch aborted by MultiMC."); + return 1; + } if(m_launcher != null) { return m_launcher.launch(m_params); diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index 29f7c8e8..ebbace52 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -33,6 +33,7 @@ #include <QLabel> #include <QToolButton> #include <QWidgetAction> +#include <QProgressDialog> #include "osutils.h" #include "userutils.h" @@ -97,6 +98,8 @@ #include <logic/updater/NotificationChecker.h> #include <logic/tasks/ThreadTask.h> +#include "logic/tools/BaseProfiler.h" + MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { MultiMCPlatform::fixWM_CLASS(this); @@ -357,6 +360,51 @@ void MainWindow::showInstanceContextMenu(const QPoint &pos) myMenu.exec(view->mapToGlobal(pos)); } +void MainWindow::updateToolsMenu() +{ + if (ui->actionLaunchInstance->menu()) + { + ui->actionLaunchInstance->menu()->deleteLater(); + } + QMenu *launchMenu = new QMenu(this); + QAction *normalLaunch = launchMenu->addAction(tr("Launch")); + connect(normalLaunch, &QAction::triggered, [this](){doLaunch();}); + launchMenu->addSeparator()->setText(tr("Profilers")); + for (auto profiler : MMC->profilers().values()) + { + QAction *profilerAction = launchMenu->addAction(profiler->name()); + QString error; + if (!profiler->check(&error)) + { + profilerAction->setDisabled(true); + profilerAction->setToolTip(tr("Profiler not setup correctly. Go into settings, \"External Tools\".")); + } + else + { + connect(profilerAction, &QAction::triggered, [this, profiler](){doLaunch(true, profiler.get());}); + } + } + launchMenu->addSeparator()->setText(tr("Tools")); + for (auto tool : MMC->tools().values()) + { + QAction *toolAction = launchMenu->addAction(tool->name()); + QString error; + if (!tool->check(&error)) + { + toolAction->setDisabled(true); + toolAction->setToolTip(tr("Tool not setup correctly. Go into settings, \"External Tools\".")); + } + else + { + connect(toolAction, &QAction::triggered, [this, tool]() + { + tool->createDetachedTool(m_selectedInstance, this)->run(); + }); + } + } + ui->actionLaunchInstance->setMenu(launchMenu); +} + void MainWindow::repopulateAccountsMenu() { accountMenu->clear(); @@ -930,6 +978,7 @@ void MainWindow::on_actionSettings_triggered() // FIXME: quick HACK to make this work. improve, optimize. proxymodel->invalidate(); proxymodel->sort(0); + updateToolsMenu(); } void MainWindow::on_actionManageAccounts_triggered() @@ -1078,7 +1127,7 @@ void MainWindow::on_actionLaunchInstanceOffline_triggered() } } -void MainWindow::doLaunch(bool online) +void MainWindow::doLaunch(bool online, BaseProfilerFactory *profiler) { if (!m_selectedInstance) return; @@ -1194,11 +1243,11 @@ void MainWindow::doLaunch(bool online) // update first if the server actually responded if (session->auth_server_online) { - updateInstance(m_selectedInstance, session); + updateInstance(m_selectedInstance, session, profiler); } else { - launchInstance(m_selectedInstance, session); + launchInstance(m_selectedInstance, session, profiler); } tryagain = false; } @@ -1206,22 +1255,22 @@ void MainWindow::doLaunch(bool online) } } -void MainWindow::updateInstance(BaseInstance *instance, AuthSessionPtr session) +void MainWindow::updateInstance(BaseInstance *instance, AuthSessionPtr session, BaseProfilerFactory *profiler) { auto updateTask = instance->doUpdate(); if (!updateTask) { - launchInstance(instance, session); + launchInstance(instance, session, profiler); return; } ProgressDialog tDialog(this); - connect(updateTask.get(), &Task::succeeded, [this, instance, session] - { launchInstance(instance, session); }); + connect(updateTask.get(), &Task::succeeded, [this, instance, session, profiler] + { launchInstance(instance, session, profiler); }); connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString))); tDialog.exec(updateTask.get()); } -void MainWindow::launchInstance(BaseInstance *instance, AuthSessionPtr session) +void MainWindow::launchInstance(BaseInstance *instance, AuthSessionPtr session, BaseProfilerFactory *profiler) { Q_ASSERT_X(instance != NULL, "launchInstance", "instance is NULL"); Q_ASSERT_X(session.get() != nullptr, "launchInstance", "session is NULL"); @@ -1236,7 +1285,56 @@ void MainWindow::launchInstance(BaseInstance *instance, AuthSessionPtr session) connect(console, SIGNAL(isClosing()), this, SLOT(instanceEnded())); proc->setLogin(session); - proc->launch(); + proc->arm(); + + if (profiler) + { + QString error; + if (!profiler->check(&error)) + { + QMessageBox::critical(this, tr("Error"), tr("Couldn't start profiler: %1").arg(error)); + proc->abort(); + return; + } + BaseProfiler *profilerInstance = profiler->createProfiler(instance, this); + QProgressDialog dialog; + dialog.setMinimum(0); + dialog.setMaximum(0); + dialog.setValue(0); + dialog.setLabelText(tr("Waiting for profiler...")); + connect(&dialog, &QProgressDialog::canceled, profilerInstance, &BaseProfiler::abortProfiling); + dialog.show(); + connect(profilerInstance, &BaseProfiler::readyToLaunch, [&dialog, this](const QString &message) + { + dialog.accept(); + QMessageBox msg; + msg.setText(tr("The launch of Minecraft itself is delayed until you press the " + "button. This is the right time to setup the profiler, as the " + "profiler server is running now.\n\n%1").arg(message)); + msg.setWindowTitle(tr("Waiting")); + msg.setIcon(QMessageBox::Information); + msg.addButton(tr("Launch"), QMessageBox::AcceptRole); + msg.exec(); + proc->launch(); + }); + connect(profilerInstance, &BaseProfiler::abortLaunch, [&dialog, this](const QString &message) + { + dialog.accept(); + QMessageBox msg; + msg.setText(tr("Couldn't start the profiler: %1").arg(message)); + msg.setWindowTitle(tr("Error")); + msg.setIcon(QMessageBox::Critical); + msg.addButton(QMessageBox::Ok); + msg.exec(); + proc->abort(); + }); + profilerInstance->beginProfiling(proc); + dialog.exec(); + } + else + { + proc->launch(); + } } void MainWindow::onGameUpdateError(QString error) @@ -1377,6 +1475,8 @@ void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex & m_statusLeft->setText(m_selectedInstance->getStatusbarDescription()); updateInstanceToolIcon(m_selectedInstance->iconKey()); + updateToolsMenu(); + MMC->settings()->set("SelectedInstance", m_selectedInstance->id()); } else diff --git a/gui/MainWindow.h b/gui/MainWindow.h index 4d9e165d..7a29977d 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -29,6 +29,7 @@ class LabeledToolButton; class QLabel; class MinecraftProcess; class ConsoleWindow; +class BaseProfilerFactory; namespace Ui { @@ -111,18 +112,18 @@ slots: * Launches the currently selected instance with the default account. * If no default account is selected, prompts the user to pick an account. */ - void doLaunch(bool online = true); + void doLaunch(bool online = true, BaseProfilerFactory *profiler = 0); /*! * Launches the given instance with the given account. * This function assumes that the given account has a valid, usable access token. */ - void launchInstance(BaseInstance *instance, AuthSessionPtr session); + void launchInstance(BaseInstance *instance, AuthSessionPtr session, BaseProfilerFactory *profiler = 0); /*! * Prepares the given instance for launch with the given account. */ - void updateInstance(BaseInstance *instance, AuthSessionPtr account); + void updateInstance(BaseInstance *instance, AuthSessionPtr account, BaseProfilerFactory *profiler = 0); void onGameUpdateError(QString error); @@ -140,6 +141,8 @@ slots: void showInstanceContextMenu(const QPoint&); + void updateToolsMenu(); + public slots: void instanceActivated(QModelIndex); diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui index 8cf26d18..90c86075 100644 --- a/gui/MainWindow.ui +++ b/gui/MainWindow.ui @@ -531,9 +531,8 @@ </widget> <layoutdefault spacing="6" margin="11"/> <resources> - <include location="../resources/instances/instances.qrc"/> <include location="../resources/multimc/multimc.qrc"/> - <include location="../resources/backgrounds/backgrounds.qrc"/> + <include location="../resources/instances/instances.qrc"/> </resources> <connections/> </ui> diff --git a/gui/dialogs/SettingsDialog.cpp b/gui/dialogs/SettingsDialog.cpp index ef363f02..d79bb558 100644 --- a/gui/dialogs/SettingsDialog.cpp +++ b/gui/dialogs/SettingsDialog.cpp @@ -29,6 +29,8 @@ #include "logic/updater/UpdateChecker.h" +#include "logic/tools/BaseProfiler.h" + #include <settingsobject.h> #include <pathutils.h> #include <QFileDialog> @@ -46,12 +48,14 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Se ui->jsonEditorTextBox->setClearButtonEnabled(true); #endif - restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("SettingsGeometry").toByteArray())); + restoreGeometry( + QByteArray::fromBase64(MMC->settings()->get("SettingsGeometry").toByteArray())); loadSettings(MMC->settings().get()); updateCheckboxStuff(); - QObject::connect(MMC->updateChecker().get(), &UpdateChecker::channelListLoaded, this, &SettingsDialog::refreshUpdateChannelList); + QObject::connect(MMC->updateChecker().get(), &UpdateChecker::channelListLoaded, this, + &SettingsDialog::refreshUpdateChannelList); if (MMC->updateChecker()->hasChannels()) { @@ -62,6 +66,9 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Se MMC->updateChecker()->updateChanList(); } connect(ui->proxyGroup, SIGNAL(buttonClicked(int)), SLOT(proxyChanged(int))); + ui->mceditLink->setOpenExternalLinks(true); + ui->jvisualvmLink->setOpenExternalLinks(true); + ui->jprofilerLink->setOpenExternalLinks(true); } SettingsDialog::~SettingsDialog() @@ -84,8 +91,10 @@ void SettingsDialog::updateCheckboxStuff() { ui->windowWidthSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked()); ui->windowHeightSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked()); - ui->proxyAddrBox->setEnabled(!ui->proxyNoneBtn->isChecked() && !ui->proxyDefaultBtn->isChecked()); - ui->proxyAuthBox->setEnabled(!ui->proxyNoneBtn->isChecked() && !ui->proxyDefaultBtn->isChecked()); + ui->proxyAddrBox->setEnabled(!ui->proxyNoneBtn->isChecked() && + !ui->proxyDefaultBtn->isChecked()); + ui->proxyAuthBox->setEnabled(!ui->proxyNoneBtn->isChecked() && + !ui->proxyDefaultBtn->isChecked()); } void SettingsDialog::on_ftbLauncherBrowseBtn_clicked() @@ -103,8 +112,8 @@ void SettingsDialog::on_ftbLauncherBrowseBtn_clicked() void SettingsDialog::on_ftbBrowseBtn_clicked() { - QString raw_dir = QFileDialog::getExistingDirectory(this, tr("FTB Directory"), - ui->ftbBox->text()); + QString raw_dir = + QFileDialog::getExistingDirectory(this, tr("FTB Directory"), ui->ftbBox->text()); QString cooked_dir = NormalizePath(raw_dir); // do not allow current dir - it's dirty. Do not allow dirs that don't exist @@ -170,11 +179,11 @@ void SettingsDialog::on_jsonEditorBrowseBtn_clicked() QString raw_file = QFileDialog::getOpenFileName( this, tr("JSON Editor"), ui->jsonEditorTextBox->text().isEmpty() - #if defined(Q_OS_LINUX) +#if defined(Q_OS_LINUX) ? QString("/usr/bin") - #else +#else ? QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).first() - #endif +#endif : ui->jsonEditorTextBox->text()); QString cooked_file = NormalizePath(raw_file); @@ -184,14 +193,14 @@ void SettingsDialog::on_jsonEditorBrowseBtn_clicked() } // it has to exist and be an executable - if (QFileInfo(cooked_file).exists() && - QFileInfo(cooked_file).isExecutable()) + 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")); + QMessageBox::warning(this, tr("Invalid"), + tr("The file chosen does not seem to be an executable")); } } @@ -223,9 +232,11 @@ void SettingsDialog::proxyChanged(int) void SettingsDialog::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 + // 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))); + QObject::disconnect(ui->updateChannelComboBox, SIGNAL(currentIndexChanged(int)), this, + SLOT(updateChannelSelectionChanged(int))); QList<UpdateChecker::ChannelListEntry> channelList = MMC->updateChecker()->getChannelList(); ui->updateChannelComboBox->clear(); @@ -233,29 +244,34 @@ void SettingsDialog::refreshUpdateChannelList() 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 + + // 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 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 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) { QLOG_DEBUG() << "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))); + 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. + // It starts off disabled so that if the channel list hasn't been loaded, it will be + // disabled. ui->updateChannelComboBox->setEnabled(true); } @@ -269,7 +285,7 @@ void SettingsDialog::refreshUpdateChannelDesc() // Get the channel list. QList<UpdateChecker::ChannelListEntry> channelList = MMC->updateChecker()->getChannelList(); int selectedIndex = ui->updateChannelComboBox->currentIndex(); - if(selectedIndex < 0) + if (selectedIndex < 0) { return; } @@ -289,7 +305,8 @@ void SettingsDialog::refreshUpdateChannelDesc() void SettingsDialog::applySettings(SettingsObject *s) { // Language - s->set("Language", ui->languageBox->itemData(ui->languageBox->currentIndex()).toLocale().bcp47Name()); + s->set("Language", + ui->languageBox->itemData(ui->languageBox->currentIndex()).toLocale().bcp47Name()); // Updates s->set("AutoUpdate", ui->autoUpdateCheckBox->isChecked()); @@ -309,7 +326,8 @@ void SettingsDialog::applySettings(SettingsObject *s) // Editors QString jsonEditor = ui->jsonEditorTextBox->text(); - if (!jsonEditor.isEmpty() && (!QFileInfo(jsonEditor).exists() || !QFileInfo(jsonEditor).isExecutable())) + if (!jsonEditor.isEmpty() && + (!QFileInfo(jsonEditor).exists() || !QFileInfo(jsonEditor).isExecutable())) { QString found = QStandardPaths::findExecutable(jsonEditor); if (!found.isEmpty()) @@ -330,10 +348,14 @@ void SettingsDialog::applySettings(SettingsObject *s) // 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"; + 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()); @@ -368,6 +390,11 @@ void SettingsDialog::applySettings(SettingsObject *s) } s->set("PostExitCommand", ui->postExitCmdTextBox->text()); + + // Profilers + s->set("JProfilerPath", ui->jprofilerPathEdit->text()); + s->set("JVisualVMPath", ui->jvisualvmPathEdit->text()); + s->set("MCEditPath", ui->mceditPathEdit->text()); } void SettingsDialog::loadSettings(SettingsObject *s) @@ -379,11 +406,10 @@ void SettingsDialog::loadSettings(SettingsObject *s) QDir(MMC->root() + "/translations").entryList(QStringList() << "*.qm", QDir::Files)) { QLocale locale(lang.section(QRegExp("[_\.]"), 1)); - ui->languageBox->addItem( - QLocale::languageToString(locale.language()), - locale); + ui->languageBox->addItem(QLocale::languageToString(locale.language()), locale); } - ui->languageBox->setCurrentIndex(ui->languageBox->findData(QLocale(s->get("Language").toString()))); + ui->languageBox->setCurrentIndex( + ui->languageBox->findData(QLocale(s->get("Language").toString()))); // Updates ui->autoUpdateCheckBox->setChecked(s->get("AutoUpdate").toBool()); @@ -430,10 +456,14 @@ void SettingsDialog::loadSettings(SettingsObject *s) // 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); + 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<qint16>()); @@ -447,6 +477,11 @@ void SettingsDialog::loadSettings(SettingsObject *s) // Custom Commands ui->preLaunchCmdTextBox->setText(s->get("PreLaunchCommand").toString()); ui->postExitCmdTextBox->setText(s->get("PostExitCommand").toString()); + + // Profilers + ui->jprofilerPathEdit->setText(s->get("JProfilerPath").toString()); + ui->jvisualvmPathEdit->setText(s->get("JVisualVMPath").toString()); + ui->mceditPathEdit->setText(s->get("MCEditPath").toString()); } void SettingsDialog::on_javaDetectBtn_clicked() @@ -503,3 +538,126 @@ void SettingsDialog::checkFinished(JavaCheckResult result) "or set the path to the java executable.")); } } + +void SettingsDialog::on_jprofilerPathBtn_clicked() +{ + QString raw_dir = ui->jprofilerPathEdit->text(); + QString error; + do + { + raw_dir = QFileDialog::getExistingDirectory(this, tr("JProfiler Directory"), raw_dir); + if (raw_dir.isEmpty()) + { + break; + } + QString cooked_dir = NormalizePath(raw_dir); + if (!MMC->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 SettingsDialog::on_jprofilerCheckBtn_clicked() +{ + QString error; + if (!MMC->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 SettingsDialog::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 = NormalizePath(raw_dir); + if (!MMC->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 SettingsDialog::on_jvisualvmCheckBtn_clicked() +{ + QString error; + if (!MMC->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 SettingsDialog::on_mceditPathBtn_clicked() +{ + QString raw_dir = ui->mceditPathEdit->text(); + QString error; + do + { +#ifdef Q_OS_OSX +#warning stuff + raw_dir = QFileDialog::getOpenFileName(this, tr("MCEdit Application"), raw_dir); +#else + raw_dir = QFileDialog::getExistingDirectory(this, tr("MCEdit Directory"), raw_dir); +#endif + if (raw_dir.isEmpty()) + { + break; + } + QString cooked_dir = NormalizePath(raw_dir); + if (!MMC->tools()["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 SettingsDialog::on_mceditCheckBtn_clicked() +{ + QString error; + if (!MMC->tools()["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")); + } +} diff --git a/gui/dialogs/SettingsDialog.h b/gui/dialogs/SettingsDialog.h index d7bbbeb3..d8495fdd 100644 --- a/gui/dialogs/SettingsDialog.h +++ b/gui/dialogs/SettingsDialog.h @@ -75,6 +75,13 @@ slots: void checkFinished(JavaCheckResult result); + void on_jprofilerPathBtn_clicked(); + void on_jprofilerCheckBtn_clicked(); + void on_jvisualvmPathBtn_clicked(); + void on_jvisualvmCheckBtn_clicked(); + void on_mceditPathBtn_clicked(); + void on_mceditCheckBtn_clicked(); + /*! * Updates the list of update channels in the combo box. */ diff --git a/gui/dialogs/SettingsDialog.ui b/gui/dialogs/SettingsDialog.ui index 54e7db7a..e8da8582 100644 --- a/gui/dialogs/SettingsDialog.ui +++ b/gui/dialogs/SettingsDialog.ui @@ -863,6 +863,137 @@ </item> </layout> </widget> + <widget class="QWidget" name="externalToolsTab"> + <attribute name= |
