Merge branch 'feature_profiling' into integration_json_and_tools
This commit is contained in:
commit
f7c97efcf3
@ -500,6 +500,18 @@ logic/assets/AssetsMigrateTask.h
|
|||||||
logic/assets/AssetsMigrateTask.cpp
|
logic/assets/AssetsMigrateTask.cpp
|
||||||
logic/assets/AssetsUtils.h
|
logic/assets/AssetsUtils.h
|
||||||
logic/assets/AssetsUtils.cpp
|
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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
24
MultiMC.cpp
24
MultiMC.cpp
@ -32,6 +32,10 @@
|
|||||||
#include "logic/updater/UpdateChecker.h"
|
#include "logic/updater/UpdateChecker.h"
|
||||||
#include "logic/updater/NotificationChecker.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 "pathutils.h"
|
||||||
#include "cmdutils.h"
|
#include "cmdutils.h"
|
||||||
#include <inisettingsobject.h>
|
#include <inisettingsobject.h>
|
||||||
@ -42,8 +46,9 @@
|
|||||||
using namespace Util::Commandline;
|
using namespace Util::Commandline;
|
||||||
|
|
||||||
MultiMC::MultiMC(int &argc, char **argv, bool root_override)
|
MultiMC::MultiMC(int &argc, char **argv, bool root_override)
|
||||||
: QApplication(argc, argv), m_version{VERSION_MAJOR, VERSION_MINOR, VERSION_HOTFIX,
|
: QApplication(argc, argv),
|
||||||
VERSION_BUILD, MultiMCVersion::VERSION_TYPE, VERSION_CHANNEL, BUILD_PLATFORM}
|
m_version{VERSION_MAJOR, VERSION_MINOR, VERSION_HOTFIX, VERSION_BUILD,
|
||||||
|
MultiMCVersion::VERSION_TYPE, VERSION_CHANNEL, BUILD_PLATFORM}
|
||||||
{
|
{
|
||||||
setOrganizationName("MultiMC");
|
setOrganizationName("MultiMC");
|
||||||
setApplicationName("MultiMC5");
|
setApplicationName("MultiMC5");
|
||||||
@ -212,6 +217,21 @@ MultiMC::MultiMC(int &argc, char **argv, bool root_override)
|
|||||||
// init proxy settings
|
// init proxy settings
|
||||||
updateProxySettings();
|
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
|
// launch instance, if that's what should be done
|
||||||
// WARNING: disabled until further notice
|
// WARNING: disabled until further notice
|
||||||
/*
|
/*
|
||||||
|
13
MultiMC.h
13
MultiMC.h
@ -23,6 +23,8 @@ class UpdateChecker;
|
|||||||
class NotificationChecker;
|
class NotificationChecker;
|
||||||
class NewsChecker;
|
class NewsChecker;
|
||||||
class StatusChecker;
|
class StatusChecker;
|
||||||
|
class BaseProfilerFactory;
|
||||||
|
class BaseDetachedToolFactory;
|
||||||
|
|
||||||
#if defined(MMC)
|
#if defined(MMC)
|
||||||
#undef MMC
|
#undef MMC
|
||||||
@ -130,6 +132,15 @@ public:
|
|||||||
|
|
||||||
std::shared_ptr<JavaVersionList> javalist();
|
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);
|
void installUpdates(const QString updateFilesDir, UpdateFlags flags = None);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -202,6 +213,8 @@ private:
|
|||||||
std::shared_ptr<LiteLoaderVersionList> m_liteloaderlist;
|
std::shared_ptr<LiteLoaderVersionList> m_liteloaderlist;
|
||||||
std::shared_ptr<MinecraftVersionList> m_minecraftlist;
|
std::shared_ptr<MinecraftVersionList> m_minecraftlist;
|
||||||
std::shared_ptr<JavaVersionList> m_javalist;
|
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_fileDestination;
|
||||||
QsLogging::DestinationPtr m_debugDestination;
|
QsLogging::DestinationPtr m_debugDestination;
|
||||||
|
|
||||||
|
@ -29,7 +29,8 @@ public class EntryPoint
|
|||||||
private enum Action
|
private enum Action
|
||||||
{
|
{
|
||||||
Proceed,
|
Proceed,
|
||||||
Launch
|
Launch,
|
||||||
|
Abort
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
@ -61,27 +62,40 @@ public class EntryPoint
|
|||||||
private Action parseLine(String inData) throws ParseException
|
private Action parseLine(String inData) throws ParseException
|
||||||
{
|
{
|
||||||
String[] pair = inData.split(" ", 2);
|
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)
|
if(pair.length != 2)
|
||||||
throw new ParseException();
|
throw new ParseException();
|
||||||
|
|
||||||
String command = pair[0];
|
String command = pair[0];
|
||||||
String param = pair[1];
|
String param = pair[1];
|
||||||
|
|
||||||
if(command.equals("launch"))
|
if(command.equals("launcher"))
|
||||||
{
|
{
|
||||||
if(param.equals("legacy"))
|
if(param.equals("legacy"))
|
||||||
{
|
{
|
||||||
m_launcher = new LegacyLauncher();
|
m_launcher = new LegacyLauncher();
|
||||||
Utils.log("Using legacy launcher.");
|
Utils.log("Using legacy launcher.");
|
||||||
Utils.log();
|
Utils.log();
|
||||||
return Action.Launch;
|
return Action.Proceed;
|
||||||
}
|
}
|
||||||
if(param.equals("onesix"))
|
if(param.equals("onesix"))
|
||||||
{
|
{
|
||||||
m_launcher = new OneSixLauncher();
|
m_launcher = new OneSixLauncher();
|
||||||
Utils.log("Using onesix launcher.");
|
Utils.log("Using onesix launcher.");
|
||||||
Utils.log();
|
Utils.log();
|
||||||
return Action.Launch;
|
return Action.Proceed;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw new ParseException();
|
throw new ParseException();
|
||||||
@ -105,6 +119,7 @@ public class EntryPoint
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
boolean isListening = true;
|
boolean isListening = true;
|
||||||
|
boolean isAborted = false;
|
||||||
// Main loop
|
// Main loop
|
||||||
while (isListening)
|
while (isListening)
|
||||||
{
|
{
|
||||||
@ -115,7 +130,13 @@ public class EntryPoint
|
|||||||
inData = buffer.readLine();
|
inData = buffer.readLine();
|
||||||
if (inData != null)
|
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;
|
isListening = false;
|
||||||
}
|
}
|
||||||
@ -134,6 +155,11 @@ public class EntryPoint
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(isAborted)
|
||||||
|
{
|
||||||
|
System.err.println("Launch aborted by MultiMC.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if(m_launcher != null)
|
if(m_launcher != null)
|
||||||
{
|
{
|
||||||
return m_launcher.launch(m_params);
|
return m_launcher.launch(m_params);
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
#include <QWidgetAction>
|
#include <QWidgetAction>
|
||||||
|
#include <QProgressDialog>
|
||||||
|
|
||||||
#include "osutils.h"
|
#include "osutils.h"
|
||||||
#include "userutils.h"
|
#include "userutils.h"
|
||||||
@ -97,6 +98,8 @@
|
|||||||
#include <logic/updater/NotificationChecker.h>
|
#include <logic/updater/NotificationChecker.h>
|
||||||
#include <logic/tasks/ThreadTask.h>
|
#include <logic/tasks/ThreadTask.h>
|
||||||
|
|
||||||
|
#include "logic/tools/BaseProfiler.h"
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
|
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
|
||||||
{
|
{
|
||||||
MultiMCPlatform::fixWM_CLASS(this);
|
MultiMCPlatform::fixWM_CLASS(this);
|
||||||
@ -357,6 +360,51 @@ void MainWindow::showInstanceContextMenu(const QPoint &pos)
|
|||||||
myMenu.exec(view->mapToGlobal(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()
|
void MainWindow::repopulateAccountsMenu()
|
||||||
{
|
{
|
||||||
accountMenu->clear();
|
accountMenu->clear();
|
||||||
@ -930,6 +978,7 @@ void MainWindow::on_actionSettings_triggered()
|
|||||||
// FIXME: quick HACK to make this work. improve, optimize.
|
// FIXME: quick HACK to make this work. improve, optimize.
|
||||||
proxymodel->invalidate();
|
proxymodel->invalidate();
|
||||||
proxymodel->sort(0);
|
proxymodel->sort(0);
|
||||||
|
updateToolsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionManageAccounts_triggered()
|
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)
|
if (!m_selectedInstance)
|
||||||
return;
|
return;
|
||||||
@ -1194,11 +1243,11 @@ void MainWindow::doLaunch(bool online)
|
|||||||
// update first if the server actually responded
|
// update first if the server actually responded
|
||||||
if (session->auth_server_online)
|
if (session->auth_server_online)
|
||||||
{
|
{
|
||||||
updateInstance(m_selectedInstance, session);
|
updateInstance(m_selectedInstance, session, profiler);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
launchInstance(m_selectedInstance, session);
|
launchInstance(m_selectedInstance, session, profiler);
|
||||||
}
|
}
|
||||||
tryagain = false;
|
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();
|
auto updateTask = instance->doUpdate();
|
||||||
if (!updateTask)
|
if (!updateTask)
|
||||||
{
|
{
|
||||||
launchInstance(instance, session);
|
launchInstance(instance, session, profiler);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ProgressDialog tDialog(this);
|
ProgressDialog tDialog(this);
|
||||||
connect(updateTask.get(), &Task::succeeded, [this, instance, session]
|
connect(updateTask.get(), &Task::succeeded, [this, instance, session, profiler]
|
||||||
{ launchInstance(instance, session); });
|
{ launchInstance(instance, session, profiler); });
|
||||||
connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString)));
|
connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString)));
|
||||||
tDialog.exec(updateTask.get());
|
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(instance != NULL, "launchInstance", "instance is NULL");
|
||||||
Q_ASSERT_X(session.get() != nullptr, "launchInstance", "session 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()));
|
connect(console, SIGNAL(isClosing()), this, SLOT(instanceEnded()));
|
||||||
|
|
||||||
proc->setLogin(session);
|
proc->setLogin(session);
|
||||||
|
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();
|
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)
|
void MainWindow::onGameUpdateError(QString error)
|
||||||
@ -1377,6 +1475,8 @@ void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex &
|
|||||||
m_statusLeft->setText(m_selectedInstance->getStatusbarDescription());
|
m_statusLeft->setText(m_selectedInstance->getStatusbarDescription());
|
||||||
updateInstanceToolIcon(m_selectedInstance->iconKey());
|
updateInstanceToolIcon(m_selectedInstance->iconKey());
|
||||||
|
|
||||||
|
updateToolsMenu();
|
||||||
|
|
||||||
MMC->settings()->set("SelectedInstance", m_selectedInstance->id());
|
MMC->settings()->set("SelectedInstance", m_selectedInstance->id());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -29,6 +29,7 @@ class LabeledToolButton;
|
|||||||
class QLabel;
|
class QLabel;
|
||||||
class MinecraftProcess;
|
class MinecraftProcess;
|
||||||
class ConsoleWindow;
|
class ConsoleWindow;
|
||||||
|
class BaseProfilerFactory;
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
@ -111,18 +112,18 @@ slots:
|
|||||||
* Launches the currently selected instance with the default account.
|
* Launches the currently selected instance with the default account.
|
||||||
* If no default account is selected, prompts the user to pick an 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.
|
* Launches the given instance with the given account.
|
||||||
* This function assumes that the given account has a valid, usable access token.
|
* 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.
|
* 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);
|
void onGameUpdateError(QString error);
|
||||||
|
|
||||||
@ -140,6 +141,8 @@ slots:
|
|||||||
|
|
||||||
void showInstanceContextMenu(const QPoint&);
|
void showInstanceContextMenu(const QPoint&);
|
||||||
|
|
||||||
|
void updateToolsMenu();
|
||||||
|
|
||||||
public
|
public
|
||||||
slots:
|
slots:
|
||||||
void instanceActivated(QModelIndex);
|
void instanceActivated(QModelIndex);
|
||||||
|
@ -531,9 +531,8 @@
|
|||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../resources/instances/instances.qrc"/>
|
|
||||||
<include location="../resources/multimc/multimc.qrc"/>
|
<include location="../resources/multimc/multimc.qrc"/>
|
||||||
<include location="../resources/backgrounds/backgrounds.qrc"/>
|
<include location="../resources/instances/instances.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
#include "logic/updater/UpdateChecker.h"
|
#include "logic/updater/UpdateChecker.h"
|
||||||
|
|
||||||
|
#include "logic/tools/BaseProfiler.h"
|
||||||
|
|
||||||
#include <settingsobject.h>
|
#include <settingsobject.h>
|
||||||
#include <pathutils.h>
|
#include <pathutils.h>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
@ -46,12 +48,14 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Se
|
|||||||
ui->jsonEditorTextBox->setClearButtonEnabled(true);
|
ui->jsonEditorTextBox->setClearButtonEnabled(true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("SettingsGeometry").toByteArray()));
|
restoreGeometry(
|
||||||
|
QByteArray::fromBase64(MMC->settings()->get("SettingsGeometry").toByteArray()));
|
||||||
|
|
||||||
loadSettings(MMC->settings().get());
|
loadSettings(MMC->settings().get());
|
||||||
updateCheckboxStuff();
|
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())
|
if (MMC->updateChecker()->hasChannels())
|
||||||
{
|
{
|
||||||
@ -62,6 +66,9 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Se
|
|||||||
MMC->updateChecker()->updateChanList();
|
MMC->updateChecker()->updateChanList();
|
||||||
}
|
}
|
||||||
connect(ui->proxyGroup, SIGNAL(buttonClicked(int)), SLOT(proxyChanged(int)));
|
connect(ui->proxyGroup, SIGNAL(buttonClicked(int)), SLOT(proxyChanged(int)));
|
||||||
|
ui->mceditLink->setOpenExternalLinks(true);
|
||||||
|
ui->jvisualvmLink->setOpenExternalLinks(true);
|
||||||
|
ui->jprofilerLink->setOpenExternalLinks(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsDialog::~SettingsDialog()
|
SettingsDialog::~SettingsDialog()
|
||||||
@ -84,8 +91,10 @@ void SettingsDialog::updateCheckboxStuff()
|
|||||||
{
|
{
|
||||||
ui->windowWidthSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
|
ui->windowWidthSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
|
||||||
ui->windowHeightSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
|
ui->windowHeightSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
|
||||||
ui->proxyAddrBox->setEnabled(!ui->proxyNoneBtn->isChecked() && !ui->proxyDefaultBtn->isChecked());
|
ui->proxyAddrBox->setEnabled(!ui->proxyNoneBtn->isChecked() &&
|
||||||
ui->proxyAuthBox->setEnabled(!ui->proxyNoneBtn->isChecked() && !ui->proxyDefaultBtn->isChecked());
|
!ui->proxyDefaultBtn->isChecked());
|
||||||
|
ui->proxyAuthBox->setEnabled(!ui->proxyNoneBtn->isChecked() &&
|
||||||
|
!ui->proxyDefaultBtn->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsDialog::on_ftbLauncherBrowseBtn_clicked()
|
void SettingsDialog::on_ftbLauncherBrowseBtn_clicked()
|
||||||
@ -103,8 +112,8 @@ void SettingsDialog::on_ftbLauncherBrowseBtn_clicked()
|
|||||||
|
|
||||||
void SettingsDialog::on_ftbBrowseBtn_clicked()
|
void SettingsDialog::on_ftbBrowseBtn_clicked()
|
||||||
{
|
{
|
||||||
QString raw_dir = QFileDialog::getExistingDirectory(this, tr("FTB Directory"),
|
QString raw_dir =
|
||||||
ui->ftbBox->text());
|
QFileDialog::getExistingDirectory(this, tr("FTB Directory"), ui->ftbBox->text());
|
||||||
QString cooked_dir = NormalizePath(raw_dir);
|
QString cooked_dir = NormalizePath(raw_dir);
|
||||||
|
|
||||||
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
|
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
|
||||||
@ -184,14 +193,14 @@ void SettingsDialog::on_jsonEditorBrowseBtn_clicked()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// it has to exist and be an executable
|
// it has to exist and be an executable
|
||||||
if (QFileInfo(cooked_file).exists() &&
|
if (QFileInfo(cooked_file).exists() && QFileInfo(cooked_file).isExecutable())
|
||||||
QFileInfo(cooked_file).isExecutable())
|
|
||||||
{
|
{
|
||||||
ui->jsonEditorTextBox->setText(cooked_file);
|
ui->jsonEditorTextBox->setText(cooked_file);
|
||||||
}
|
}
|
||||||
else
|
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()
|
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.
|
// 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();
|
QList<UpdateChecker::ChannelListEntry> channelList = MMC->updateChecker()->getChannelList();
|
||||||
ui->updateChannelComboBox->clear();
|
ui->updateChannelComboBox->clear();
|
||||||
@ -234,13 +245,16 @@ void SettingsDialog::refreshUpdateChannelList()
|
|||||||
{
|
{
|
||||||
UpdateChecker::ChannelListEntry entry = channelList.at(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.
|
// 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...
|
// this to be a big deal. Hope it doesn't break...
|
||||||
ui->updateChannelComboBox->addItem(entry.name);
|
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)
|
if (entry.id == m_currentUpdateChannel)
|
||||||
{
|
{
|
||||||
QLOG_DEBUG() << "Selected index" << i << "channel id" << m_currentUpdateChannel;
|
QLOG_DEBUG() << "Selected index" << i << "channel id" << m_currentUpdateChannel;
|
||||||
@ -251,11 +265,13 @@ void SettingsDialog::refreshUpdateChannelList()
|
|||||||
ui->updateChannelComboBox->setCurrentIndex(selection);
|
ui->updateChannelComboBox->setCurrentIndex(selection);
|
||||||
|
|
||||||
// Start listening for selection changes again and update the description label.
|
// 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();
|
refreshUpdateChannelDesc();
|
||||||
|
|
||||||
// Now that we've updated the channel list, we can enable the combo box.
|
// 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);
|
ui->updateChannelComboBox->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,7 +305,8 @@ void SettingsDialog::refreshUpdateChannelDesc()
|
|||||||
void SettingsDialog::applySettings(SettingsObject *s)
|
void SettingsDialog::applySettings(SettingsObject *s)
|
||||||
{
|
{
|
||||||
// Language
|
// Language
|
||||||
s->set("Language", ui->languageBox->itemData(ui->languageBox->currentIndex()).toLocale().bcp47Name());
|
s->set("Language",
|
||||||
|
ui->languageBox->itemData(ui->languageBox->currentIndex()).toLocale().bcp47Name());
|
||||||
|
|
||||||
// Updates
|
// Updates
|
||||||
s->set("AutoUpdate", ui->autoUpdateCheckBox->isChecked());
|
s->set("AutoUpdate", ui->autoUpdateCheckBox->isChecked());
|
||||||
@ -309,7 +326,8 @@ void SettingsDialog::applySettings(SettingsObject *s)
|
|||||||
|
|
||||||
// Editors
|
// Editors
|
||||||
QString jsonEditor = ui->jsonEditorTextBox->text();
|
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);
|
QString found = QStandardPaths::findExecutable(jsonEditor);
|
||||||
if (!found.isEmpty())
|
if (!found.isEmpty())
|
||||||
@ -330,10 +348,14 @@ void SettingsDialog::applySettings(SettingsObject *s)
|
|||||||
|
|
||||||
// Proxy
|
// Proxy
|
||||||
QString proxyType = "None";
|
QString proxyType = "None";
|
||||||
if (ui->proxyDefaultBtn->isChecked()) proxyType = "Default";
|
if (ui->proxyDefaultBtn->isChecked())
|
||||||
else if (ui->proxyNoneBtn->isChecked()) proxyType = "None";
|
proxyType = "Default";
|
||||||
else if (ui->proxySOCKS5Btn->isChecked()) proxyType = "SOCKS5";
|
else if (ui->proxyNoneBtn->isChecked())
|
||||||
else if (ui->proxyHTTPBtn->isChecked()) proxyType = "HTTP";
|
proxyType = "None";
|
||||||
|
else if (ui->proxySOCKS5Btn->isChecked())
|
||||||
|
proxyType = "SOCKS5";
|
||||||
|
else if (ui->proxyHTTPBtn->isChecked())
|
||||||
|
proxyType = "HTTP";
|
||||||
|
|
||||||
s->set("ProxyType", proxyType);
|
s->set("ProxyType", proxyType);
|
||||||
s->set("ProxyAddr", ui->proxyAddrEdit->text());
|
s->set("ProxyAddr", ui->proxyAddrEdit->text());
|
||||||
@ -368,6 +390,11 @@ void SettingsDialog::applySettings(SettingsObject *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
s->set("PostExitCommand", ui->postExitCmdTextBox->text());
|
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)
|
void SettingsDialog::loadSettings(SettingsObject *s)
|
||||||
@ -379,11 +406,10 @@ void SettingsDialog::loadSettings(SettingsObject *s)
|
|||||||
QDir(MMC->root() + "/translations").entryList(QStringList() << "*.qm", QDir::Files))
|
QDir(MMC->root() + "/translations").entryList(QStringList() << "*.qm", QDir::Files))
|
||||||
{
|
{
|
||||||
QLocale locale(lang.section(QRegExp("[_\.]"), 1));
|
QLocale locale(lang.section(QRegExp("[_\.]"), 1));
|
||||||
ui->languageBox->addItem(
|
ui->languageBox->addItem(QLocale::languageToString(locale.language()), locale);
|
||||||
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
|
// Updates
|
||||||
ui->autoUpdateCheckBox->setChecked(s->get("AutoUpdate").toBool());
|
ui->autoUpdateCheckBox->setChecked(s->get("AutoUpdate").toBool());
|
||||||
@ -430,10 +456,14 @@ void SettingsDialog::loadSettings(SettingsObject *s)
|
|||||||
|
|
||||||
// Proxy
|
// Proxy
|
||||||
QString proxyType = s->get("ProxyType").toString();
|
QString proxyType = s->get("ProxyType").toString();
|
||||||
if (proxyType == "Default") ui->proxyDefaultBtn->setChecked(true);
|
if (proxyType == "Default")
|
||||||
else if (proxyType == "None") ui->proxyNoneBtn->setChecked(true);
|
ui->proxyDefaultBtn->setChecked(true);
|
||||||
else if (proxyType == "SOCKS5") ui->proxySOCKS5Btn->setChecked(true);
|
else if (proxyType == "None")
|
||||||
else if (proxyType == "HTTP") ui->proxyHTTPBtn->setChecked(true);
|
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->proxyAddrEdit->setText(s->get("ProxyAddr").toString());
|
||||||
ui->proxyPortEdit->setValue(s->get("ProxyPort").value<qint16>());
|
ui->proxyPortEdit->setValue(s->get("ProxyPort").value<qint16>());
|
||||||
@ -447,6 +477,11 @@ void SettingsDialog::loadSettings(SettingsObject *s)
|
|||||||
// Custom Commands
|
// Custom Commands
|
||||||
ui->preLaunchCmdTextBox->setText(s->get("PreLaunchCommand").toString());
|
ui->preLaunchCmdTextBox->setText(s->get("PreLaunchCommand").toString());
|
||||||
ui->postExitCmdTextBox->setText(s->get("PostExitCommand").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()
|
void SettingsDialog::on_javaDetectBtn_clicked()
|
||||||
@ -503,3 +538,126 @@ void SettingsDialog::checkFinished(JavaCheckResult result)
|
|||||||
"or set the path to the java executable."));
|
"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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -75,6 +75,13 @@ slots:
|
|||||||
|
|
||||||
void checkFinished(JavaCheckResult result);
|
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.
|
* Updates the list of update channels in the combo box.
|
||||||
*/
|
*/
|
||||||
|
@ -863,6 +863,137 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="externalToolsTab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>External Tools</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string>JProfiler</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="jprofilerPathEdit"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="jprofilerPathBtn">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="jprofilerCheckBtn">
|
||||||
|
<property name="text">
|
||||||
|
<string>Check</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="jprofilerLink">
|
||||||
|
<property name="text">
|
||||||
|
<string><html><head/><body><p><a href="http://www.ej-technologies.com/products/jprofiler/overview.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.ej-technologies.com/products/jprofiler/overview.html</span></a></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_3">
|
||||||
|
<property name="title">
|
||||||
|
<string>JVisualVM</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="jvisualvmPathEdit"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="jvisualvmPathBtn">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="jvisualvmCheckBtn">
|
||||||
|
<property name="text">
|
||||||
|
<string>Check</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="jvisualvmLink">
|
||||||
|
<property name="text">
|
||||||
|
<string><html><head/><body><p><a href="http://visualvm.java.net/"><span style=" text-decoration: underline; color:#0000ff;">http://visualvm.java.net/</span></a></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_4">
|
||||||
|
<property name="title">
|
||||||
|
<string>MCEdit</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="mceditPathEdit"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="mceditPathBtn">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="mceditCheckBtn">
|
||||||
|
<property name="text">
|
||||||
|
<string>Check</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="mceditLink">
|
||||||
|
<property name="text">
|
||||||
|
<string><html><head/><body><p><a href="http://www.mcedit.net/"><span style=" text-decoration: underline; color:#0000ff;">http://www.mcedit.net/</span></a></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -938,7 +1069,7 @@
|
|||||||
</connection>
|
</connection>
|
||||||
</connections>
|
</connections>
|
||||||
<buttongroups>
|
<buttongroups>
|
||||||
<buttongroup name="proxyGroup"/>
|
|
||||||
<buttongroup name="sortingModeGroup"/>
|
<buttongroup name="sortingModeGroup"/>
|
||||||
|
<buttongroup name="proxyGroup"/>
|
||||||
</buttongroups>
|
</buttongroups>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -77,7 +77,7 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(AuthSessionPtr account)
|
|||||||
launchScript += "windowTitle " + windowTitle() + "\n";
|
launchScript += "windowTitle " + windowTitle() + "\n";
|
||||||
launchScript += "windowParams " + windowParams + "\n";
|
launchScript += "windowParams " + windowParams + "\n";
|
||||||
launchScript += "lwjgl " + lwjgl + "\n";
|
launchScript += "lwjgl " + lwjgl + "\n";
|
||||||
launchScript += "launch legacy\n";
|
launchScript += "launcher legacy\n";
|
||||||
}
|
}
|
||||||
proc->setLaunchScript(launchScript);
|
proc->setLaunchScript(launchScript);
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ void MinecraftProcess::killMinecraft()
|
|||||||
kill();
|
kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinecraftProcess::launch()
|
void MinecraftProcess::arm()
|
||||||
{
|
{
|
||||||
emit log("MultiMC version: " + MMC->version().toString() + "\n\n");
|
emit log("MultiMC version: " + MMC->version().toString() + "\n\n");
|
||||||
emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n");
|
emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n");
|
||||||
@ -374,3 +374,17 @@ void MinecraftProcess::launch()
|
|||||||
QByteArray bytes = launchScript.toUtf8();
|
QByteArray bytes = launchScript.toUtf8();
|
||||||
writeData(bytes.constData(), bytes.length());
|
writeData(bytes.constData(), bytes.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MinecraftProcess::launch()
|
||||||
|
{
|
||||||
|
QString launchString("launch\n");
|
||||||
|
QByteArray bytes = launchString.toUtf8();
|
||||||
|
writeData(bytes.constData(), bytes.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinecraftProcess::abort()
|
||||||
|
{
|
||||||
|
QString launchString("abort\n");
|
||||||
|
QByteArray bytes = launchString.toUtf8();
|
||||||
|
writeData(bytes.constData(), bytes.length());
|
||||||
|
}
|
||||||
|
@ -55,10 +55,20 @@ public:
|
|||||||
MinecraftProcess(BaseInstance *inst);
|
MinecraftProcess(BaseInstance *inst);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief launch minecraft
|
* @brief start the launcher part with the provided launch script
|
||||||
|
*/
|
||||||
|
void arm();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief launch the armed instance!
|
||||||
*/
|
*/
|
||||||
void launch();
|
void launch();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief abort launch!
|
||||||
|
*/
|
||||||
|
void abort();
|
||||||
|
|
||||||
BaseInstance *instance()
|
BaseInstance *instance()
|
||||||
{
|
{
|
||||||
return m_instance;
|
return m_instance;
|
||||||
|
@ -230,7 +230,7 @@ MinecraftProcess *OneSixInstance::prepareForLaunch(AuthSessionPtr session)
|
|||||||
launchScript += "ext " + finfo.absoluteFilePath() + "\n";
|
launchScript += "ext " + finfo.absoluteFilePath() + "\n";
|
||||||
}
|
}
|
||||||
launchScript += "natives " + natives_dir.absolutePath() + "\n";
|
launchScript += "natives " + natives_dir.absolutePath() + "\n";
|
||||||
launchScript += "launch onesix\n";
|
launchScript += "launcher onesix\n";
|
||||||
|
|
||||||
// create the process and set its parameters
|
// create the process and set its parameters
|
||||||
MinecraftProcess *proc = new MinecraftProcess(this);
|
MinecraftProcess *proc = new MinecraftProcess(this);
|
||||||
|
77
logic/tools/BaseExternalTool.cpp
Normal file
77
logic/tools/BaseExternalTool.cpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#include "BaseExternalTool.h"
|
||||||
|
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QInputDialog>
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "logic/BaseInstance.h"
|
||||||
|
#include "MultiMC.h"
|
||||||
|
|
||||||
|
BaseExternalTool::BaseExternalTool(BaseInstance *instance, QObject *parent)
|
||||||
|
: QObject(parent), m_instance(instance)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseExternalTool::~BaseExternalTool()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 BaseExternalTool::pid(QProcess *process)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
struct _PROCESS_INFORMATION *procinfo = process->pid();
|
||||||
|
return procinfo->dwProcessId;
|
||||||
|
#else
|
||||||
|
return process->pid();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BaseExternalTool::getSave() const
|
||||||
|
{
|
||||||
|
QDir saves(m_instance->minecraftRoot() + "/saves");
|
||||||
|
QStringList worlds = saves.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
|
QMutableListIterator<QString> it(worlds);
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
it.next();
|
||||||
|
if (!QDir(saves.absoluteFilePath(it.value())).exists("level.dat"))
|
||||||
|
{
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool ok = true;
|
||||||
|
const QString save = QInputDialog::getItem(
|
||||||
|
MMC->activeWindow(), tr("MCEdit"), tr("Choose which world to open:"),
|
||||||
|
worlds, 0, false, &ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
return saves.absoluteFilePath(save);
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BaseDetachedTool::BaseDetachedTool(BaseInstance *instance, QObject *parent)
|
||||||
|
: BaseExternalTool(instance, parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseDetachedTool::run()
|
||||||
|
{
|
||||||
|
runImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BaseExternalToolFactory::~BaseExternalToolFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseDetachedTool *BaseDetachedToolFactory::createDetachedTool(BaseInstance *instance, QObject *parent)
|
||||||
|
{
|
||||||
|
return qobject_cast<BaseDetachedTool *>(createTool(instance, parent));
|
||||||
|
}
|
57
logic/tools/BaseExternalTool.h
Normal file
57
logic/tools/BaseExternalTool.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class BaseInstance;
|
||||||
|
class SettingsObject;
|
||||||
|
class MinecraftProcess;
|
||||||
|
class QProcess;
|
||||||
|
|
||||||
|
class BaseExternalTool : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit BaseExternalTool(BaseInstance *instance, QObject *parent = 0);
|
||||||
|
virtual ~BaseExternalTool();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BaseInstance *m_instance;
|
||||||
|
|
||||||
|
qint64 pid(QProcess *process);
|
||||||
|
QString getSave() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BaseDetachedTool : public BaseExternalTool
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit BaseDetachedTool(BaseInstance *instance, QObject *parent = 0);
|
||||||
|
|
||||||
|
public
|
||||||
|
slots:
|
||||||
|
void run();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void runImpl() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BaseExternalToolFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~BaseExternalToolFactory();
|
||||||
|
|
||||||
|
virtual QString name() const = 0;
|
||||||
|
|
||||||
|
virtual void registerSettings(SettingsObject *settings) = 0;
|
||||||
|
|
||||||
|
virtual BaseExternalTool *createTool(BaseInstance *instance, QObject *parent = 0) = 0;
|
||||||
|
|
||||||
|
virtual bool check(QString *error) = 0;
|
||||||
|
virtual bool check(const QString &path, QString *error) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BaseDetachedToolFactory : public BaseExternalToolFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual BaseDetachedTool *createDetachedTool(BaseInstance *instance, QObject *parent = 0);
|
||||||
|
};
|
35
logic/tools/BaseProfiler.cpp
Normal file
35
logic/tools/BaseProfiler.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
BaseProfiler::BaseProfiler(BaseInstance *instance, QObject *parent)
|
||||||
|
: BaseExternalTool(instance, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseProfiler::beginProfiling(MinecraftProcess *process)
|
||||||
|
{
|
||||||
|
beginProfilingImpl(process);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseProfiler::abortProfiling()
|
||||||
|
{
|
||||||
|
abortProfilingImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseProfiler::abortProfilingImpl()
|
||||||
|
{
|
||||||
|
if (!m_profilerProcess)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_profilerProcess->terminate();
|
||||||
|
m_profilerProcess->deleteLater();
|
||||||
|
m_profilerProcess = 0;
|
||||||
|
emit abortLaunch(tr("Profiler aborted"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseProfiler *BaseProfilerFactory::createProfiler(BaseInstance *instance, QObject *parent)
|
||||||
|
{
|
||||||
|
return qobject_cast<BaseProfiler *>(createTool(instance, parent));
|
||||||
|
}
|
36
logic/tools/BaseProfiler.h
Normal file
36
logic/tools/BaseProfiler.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BaseExternalTool.h"
|
||||||
|
|
||||||
|
class BaseInstance;
|
||||||
|
class SettingsObject;
|
||||||
|
class MinecraftProcess;
|
||||||
|
class QProcess;
|
||||||
|
|
||||||
|
class BaseProfiler : public BaseExternalTool
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit BaseProfiler(BaseInstance *instance, QObject *parent = 0);
|
||||||
|
|
||||||
|
public
|
||||||
|
slots:
|
||||||
|
void beginProfiling(MinecraftProcess *process);
|
||||||
|
void abortProfiling();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QProcess *m_profilerProcess;
|
||||||
|
|
||||||
|
virtual void beginProfilingImpl(MinecraftProcess *process) = 0;
|
||||||
|
virtual void abortProfilingImpl();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void readyToLaunch(const QString &message);
|
||||||
|
void abortLaunch(const QString &message);
|
||||||
|
};
|
||||||
|
|
||||||
|
class BaseProfilerFactory : public BaseExternalToolFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual BaseProfiler *createProfiler(BaseInstance *instance, QObject *parent = 0);
|
||||||
|
};
|
78
logic/tools/JProfiler.cpp
Normal file
78
logic/tools/JProfiler.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include "JProfiler.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include "settingsobject.h"
|
||||||
|
#include "logic/MinecraftProcess.h"
|
||||||
|
#include "logic/BaseInstance.h"
|
||||||
|
#include "MultiMC.h"
|
||||||
|
|
||||||
|
JProfiler::JProfiler(BaseInstance *instance, QObject *parent) : BaseProfiler(instance, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void JProfiler::beginProfilingImpl(MinecraftProcess *process)
|
||||||
|
{
|
||||||
|
int port = MMC->settings()->get("JProfilerPort").toInt();
|
||||||
|
QProcess *profiler = new QProcess(this);
|
||||||
|
profiler->setArguments(QStringList() << "-d" << QString::number(pid(process)) << "--gui"
|
||||||
|
<< "-p" << QString::number(port));
|
||||||
|
profiler->setProgram(QDir(MMC->settings()->get("JProfilerPath").toString())
|
||||||
|
.absoluteFilePath("bin/jpenable"));
|
||||||
|
connect(profiler, &QProcess::started, [this, port]()
|
||||||
|
{ emit readyToLaunch(tr("Listening on port: %1").arg(port)); });
|
||||||
|
connect(profiler,
|
||||||
|
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||||
|
[this](int exit, QProcess::ExitStatus status)
|
||||||
|
{
|
||||||
|
if (status == QProcess::CrashExit)
|
||||||
|
{
|
||||||
|
emit abortLaunch(tr("Profiler aborted"));
|
||||||
|
}
|
||||||
|
if (m_profilerProcess)
|
||||||
|
{
|
||||||
|
m_profilerProcess->deleteLater();
|
||||||
|
m_profilerProcess = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
profiler->start();
|
||||||
|
m_profilerProcess = profiler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JProfilerFactory::registerSettings(SettingsObject *settings)
|
||||||
|
{
|
||||||
|
settings->registerSetting("JProfilerPath");
|
||||||
|
settings->registerSetting("JProfilerPort", 42042);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseExternalTool *JProfilerFactory::createTool(BaseInstance *instance, QObject *parent)
|
||||||
|
{
|
||||||
|
return new JProfiler(instance, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JProfilerFactory::check(QString *error)
|
||||||
|
{
|
||||||
|
return check(MMC->settings()->get("JProfilerPath").toString(), error);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JProfilerFactory::check(const QString &path, QString *error)
|
||||||
|
{
|
||||||
|
if (path.isEmpty())
|
||||||
|
{
|
||||||
|
*error = QObject::tr("Empty path");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QDir dir(path);
|
||||||
|
if (!dir.exists())
|
||||||
|
{
|
||||||
|
*error = QObject::tr("Path does not exist");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!dir.exists("bin") || !dir.exists("bin/jprofiler") || !dir.exists("bin/agent.jar"))
|
||||||
|
{
|
||||||
|
*error = QObject::tr("Invalid JProfiler install");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
23
logic/tools/JProfiler.h
Normal file
23
logic/tools/JProfiler.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
|
class JProfiler : public BaseProfiler
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
JProfiler(BaseInstance *instance, QObject *parent = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void beginProfilingImpl(MinecraftProcess *process);
|
||||||
|
};
|
||||||
|
|
||||||
|
class JProfilerFactory : public BaseProfilerFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString name() const override { return "JProfiler"; }
|
||||||
|
void registerSettings(SettingsObject *settings) override;
|
||||||
|
BaseExternalTool *createTool(BaseInstance *instance, QObject *parent = 0) override;
|
||||||
|
bool check(QString *error) override;
|
||||||
|
bool check(const QString &path, QString *error) override;
|
||||||
|
};
|
74
logic/tools/JVisualVM.cpp
Normal file
74
logic/tools/JVisualVM.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include "JVisualVM.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
#include "settingsobject.h"
|
||||||
|
#include "logic/MinecraftProcess.h"
|
||||||
|
#include "logic/BaseInstance.h"
|
||||||
|
#include "MultiMC.h"
|
||||||
|
|
||||||
|
JVisualVM::JVisualVM(BaseInstance *instance, QObject *parent) : BaseProfiler(instance, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void JVisualVM::beginProfilingImpl(MinecraftProcess *process)
|
||||||
|
{
|
||||||
|
QProcess *profiler = new QProcess(this);
|
||||||
|
profiler->setArguments(QStringList() << "--openpid" << QString::number(pid(process)));
|
||||||
|
profiler->setProgram(MMC->settings()->get("JVisualVMPath").toString());
|
||||||
|
connect(profiler, &QProcess::started, [this]()
|
||||||
|
{ emit readyToLaunch(tr("JVisualVM started")); });
|
||||||
|
connect(profiler,
|
||||||
|
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||||
|
[this](int exit, QProcess::ExitStatus status)
|
||||||
|
{
|
||||||
|
if (exit != 0 || status == QProcess::CrashExit)
|
||||||
|
{
|
||||||
|
emit abortLaunch(tr("Profiler aborted"));
|
||||||
|
}
|
||||||
|
if (m_profilerProcess)
|
||||||
|
{
|
||||||
|
m_profilerProcess->deleteLater();
|
||||||
|
m_profilerProcess = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
profiler->start();
|
||||||
|
m_profilerProcess = profiler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JVisualVMFactory::registerSettings(SettingsObject *settings)
|
||||||
|
{
|
||||||
|
QString defaultValue = QStandardPaths::findExecutable("jvisualvm");
|
||||||
|
if (defaultValue.isNull())
|
||||||
|
{
|
||||||
|
defaultValue = QStandardPaths::findExecutable("visualvm");
|
||||||
|
}
|
||||||
|
settings->registerSetting("JVisualVMPath", defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseExternalTool *JVisualVMFactory::createTool(BaseInstance *instance, QObject *parent)
|
||||||
|
{
|
||||||
|
return new JVisualVM(instance, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JVisualVMFactory::check(QString *error)
|
||||||
|
{
|
||||||
|
return check(MMC->settings()->get("JVisualVMPath").toString(), error);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JVisualVMFactory::check(const QString &path, QString *error)
|
||||||
|
{
|
||||||
|
if (path.isEmpty())
|
||||||
|
{
|
||||||
|
*error = QObject::tr("Empty path");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QString resolved = QStandardPaths::findExecutable(path);
|
||||||
|
if (resolved.isEmpty() && !QDir::isAbsolutePath(path))
|
||||||
|
{
|
||||||
|
*error = QObject::tr("Invalid path to JVisualVM");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
23
logic/tools/JVisualVM.h
Normal file
23
logic/tools/JVisualVM.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
|
class JVisualVM : public BaseProfiler
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
JVisualVM(BaseInstance *instance, QObject *parent = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void beginProfilingImpl(MinecraftProcess *process);
|
||||||
|
};
|
||||||
|
|
||||||
|
class JVisualVMFactory : public BaseProfilerFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString name() const override { return "JVisualVM"; }
|
||||||
|
void registerSettings(SettingsObject *settings) override;
|
||||||
|
BaseExternalTool *createTool(BaseInstance *instance, QObject *parent = 0) override;
|
||||||
|
bool check(QString *error) override;
|
||||||
|
bool check(const QString &path, QString *error) override;
|
||||||
|
};
|
77
logic/tools/MCEditTool.cpp
Normal file
77
logic/tools/MCEditTool.cpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#include "MCEditTool.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "settingsobject.h"
|
||||||
|
#include "logic/BaseInstance.h"
|
||||||
|
#include "MultiMC.h"
|
||||||
|
|
||||||
|
MCEditTool::MCEditTool(BaseInstance *instance, QObject *parent)
|
||||||
|
: BaseDetachedTool(instance, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MCEditTool::runImpl()
|
||||||
|
{
|
||||||
|
const QString mceditPath = MMC->settings()->get("MCEditPath").toString();
|
||||||
|
const QString save = getSave();
|
||||||
|
if (save.isNull())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef Q_OS_OSX
|
||||||
|
QProcess *process = new QProcess();
|
||||||
|
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), process, SLOT(deleteLater()));
|
||||||
|
process->setProgram(mceditPath);
|
||||||
|
process->setArguments(QStringList() << save);
|
||||||
|
process->start();
|
||||||
|
#else
|
||||||
|
QDir mceditDir(mceditPath);
|
||||||
|
QString program;
|
||||||
|
if (mceditDir.exists("mcedit.py"))
|
||||||
|
{
|
||||||
|
program = mceditDir.absoluteFilePath("mcedit.py");
|
||||||
|
}
|
||||||
|
else if (mceditDir.exists("mcedit.exe"))
|
||||||
|
{
|
||||||
|
program = mceditDir.absoluteFilePath("mcedit.exe");
|
||||||
|
}
|
||||||
|
QProcess::startDetached(program, QStringList() << save, mceditPath);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void MCEditFactory::registerSettings(SettingsObject *settings)
|
||||||
|
{
|
||||||
|
settings->registerSetting("MCEditPath");
|
||||||
|
}
|
||||||
|
BaseExternalTool *MCEditFactory::createTool(BaseInstance *instance, QObject *parent)
|
||||||
|
{
|
||||||
|
return new MCEditTool(instance, parent);
|
||||||
|
}
|
||||||
|
bool MCEditFactory::check(QString *error)
|
||||||
|
{
|
||||||
|
return check(MMC->settings()->get("MCEditPath").toString(), error);
|
||||||
|
}
|
||||||
|
bool MCEditFactory::check(const QString &path, QString *error)
|
||||||
|
{
|
||||||
|
if (path.isEmpty())
|
||||||
|
{
|
||||||
|
*error = QObject::tr("Path is empty");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const QDir dir(path);
|
||||||
|
if (!dir.exists())
|
||||||
|
{
|
||||||
|
*error = QObject::tr("Path does not exist");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!dir.exists("mcedit.py") && !dir.exists("mcedit.exe") && !dir.exists("Contents"))
|
||||||
|
{
|
||||||
|
*error = QObject::tr("Path does not seem to be a MCEdit path");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
23
logic/tools/MCEditTool.h
Normal file
23
logic/tools/MCEditTool.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BaseExternalTool.h"
|
||||||
|
|
||||||
|
class MCEditTool : public BaseDetachedTool
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit MCEditTool(BaseInstance *instance, QObject *parent = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void runImpl() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MCEditFactory : public BaseDetachedToolFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString name() const override { return "MCEdit"; }
|
||||||
|
void registerSettings(SettingsObject *settings) override;
|
||||||
|
BaseExternalTool *createTool(BaseInstance *instance, QObject *parent = 0) override;
|
||||||
|
bool check(QString *error) override;
|
||||||
|
bool check(const QString &path, QString *error) override;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user