aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt52
-rw-r--r--MultiMC.cpp3
-rw-r--r--changelog.md3
-rw-r--r--gui/ColumnResizer.cpp202
-rw-r--r--gui/ColumnResizer.h38
-rw-r--r--gui/MainWindow.cpp42
-rw-r--r--gui/MainWindow.h3
-rw-r--r--gui/dialogs/AboutDialog.ui39
-rw-r--r--gui/dialogs/AccountListDialog.ui96
-rw-r--r--gui/dialogs/IconPickerDialog.h3
-rw-r--r--gui/dialogs/ProgressDialog.h3
-rw-r--r--gui/dialogs/SettingsDialog.cpp704
-rw-r--r--gui/dialogs/SettingsDialog.ui1122
-rw-r--r--gui/pages/BasePageProvider.h41
-rw-r--r--gui/pages/LegacyJarModPage.cpp2
-rw-r--r--gui/pages/LegacyJarModPage.ui200
-rw-r--r--gui/pages/LogPage.cpp1
-rw-r--r--gui/pages/LogPage.ui222
-rw-r--r--gui/pages/ModFolderPage.cpp1
-rw-r--r--gui/pages/ModFolderPage.ui106
-rw-r--r--gui/pages/NotesPage.cpp1
-rw-r--r--gui/pages/NotesPage.ui38
-rw-r--r--gui/pages/OtherLogsPage.cpp1
-rw-r--r--gui/pages/OtherLogsPage.ui142
-rw-r--r--gui/pages/ScreenshotsPage.cpp1
-rw-r--r--gui/pages/ScreenshotsPage.ui104
-rw-r--r--gui/pages/VersionPage.cpp2
-rw-r--r--gui/pages/VersionPage.ui311
-rw-r--r--gui/pages/global/AccountListPage.cpp (renamed from gui/dialogs/AccountListDialog.cpp)48
-rw-r--r--gui/pages/global/AccountListPage.h (renamed from gui/dialogs/AccountListDialog.h)33
-rw-r--r--gui/pages/global/AccountListPage.ui115
-rw-r--r--gui/pages/global/ExternalToolsPage.cpp238
-rw-r--r--gui/pages/global/ExternalToolsPage.h68
-rw-r--r--gui/pages/global/ExternalToolsPage.ui197
-rw-r--r--gui/pages/global/JavaPage.cpp146
-rw-r--r--gui/pages/global/JavaPage.h72
-rw-r--r--gui/pages/global/JavaPage.ui303
-rw-r--r--gui/pages/global/MinecraftPage.cpp104
-rw-r--r--gui/pages/global/MinecraftPage.h69
-rw-r--r--gui/pages/global/MinecraftPage.ui184
-rw-r--r--gui/pages/global/MultiMCPage.cpp340
-rw-r--r--gui/pages/global/MultiMCPage.h (renamed from gui/dialogs/SettingsDialog.h)70
-rw-r--r--gui/pages/global/MultiMCPage.ui399
-rw-r--r--gui/pages/global/ProxyPage.cpp95
-rw-r--r--gui/pages/global/ProxyPage.h66
-rw-r--r--gui/pages/global/ProxyPage.ui197
-rw-r--r--gui/widgets/PageContainer.cpp3
-rw-r--r--logic/BaseVersionList.h3
-rw-r--r--logic/DefaultVariable.h35
-rw-r--r--logic/InstanceList.cpp24
-rw-r--r--logic/LwjglVersionList.cpp13
-rw-r--r--logic/VersionFilterData.cpp4
-rw-r--r--logic/VersionFilterData.h2
-rw-r--r--logic/forge/ForgeInstaller.cpp35
-rw-r--r--logic/forge/ForgeVersion.h7
-rw-r--r--logic/forge/ForgeVersionList.cpp6
-rw-r--r--logic/liteloader/LiteLoaderVersionList.cpp2
-rw-r--r--logic/minecraft/GradleSpecifier.h129
-rw-r--r--logic/minecraft/MinecraftVersion.cpp14
-rw-r--r--logic/minecraft/MinecraftVersion.h10
-rw-r--r--logic/minecraft/MinecraftVersionList.cpp24
-rw-r--r--logic/minecraft/OneSixLibrary.cpp54
-rw-r--r--logic/minecraft/RawLibrary.cpp47
-rw-r--r--logic/minecraft/RawLibrary.h12
-rw-r--r--logic/minecraft/VersionFile.cpp29
-rw-r--r--resources/multimc/16x16/minecraft.pngbin0 -> 782 bytes
-rw-r--r--resources/multimc/24x24/minecraft.pngbin0 -> 1500 bytes
-rw-r--r--resources/multimc/256x256/minecraft.pngbin0 -> 49869 bytes
-rw-r--r--resources/multimc/32x32/minecraft.pngbin0 -> 2495 bytes
-rw-r--r--resources/multimc/48x48/minecraft.pngbin0 -> 5077 bytes
-rw-r--r--resources/multimc/index.theme3
-rw-r--r--resources/multimc/multimc.qrc13
-rw-r--r--resources/multimc/scalable/java.svg773
-rw-r--r--resources/multimc/scalable/proxy.svg260
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/tst_gradlespecifier.cpp77
76 files changed, 5119 insertions, 2688 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c8f84b28..bcb09f83 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -283,6 +283,8 @@ SET(MULTIMC_SOURCES
# GUI - general utilities
gui/GuiUtil.h
gui/GuiUtil.cpp
+ gui/ColumnResizer.h
+ gui/ColumnResizer.cpp
# GUI - windows
gui/MainWindow.h
@@ -313,11 +315,23 @@ SET(MULTIMC_SOURCES
gui/pages/OtherLogsPage.cpp
gui/pages/OtherLogsPage.h
+ # GUI - global settings pages
+ gui/pages/global/AccountListPage.cpp
+ gui/pages/global/AccountListPage.h
+ gui/pages/global/ExternalToolsPage.cpp
+ gui/pages/global/ExternalToolsPage.h
+ gui/pages/global/JavaPage.cpp
+ gui/pages/global/JavaPage.h
+ gui/pages/global/MinecraftPage.cpp
+ gui/pages/global/MinecraftPage.h
+ gui/pages/global/MultiMCPage.cpp
+ gui/pages/global/MultiMCPage.h
+ gui/pages/global/ProxyPage.cpp
+ gui/pages/global/ProxyPage.h
+
# GUI - dialogs
gui/dialogs/AboutDialog.cpp
gui/dialogs/AboutDialog.h
- gui/dialogs/AccountListDialog.cpp
- gui/dialogs/AccountListDialog.h
gui/dialogs/AccountSelectDialog.cpp
gui/dialogs/AccountSelectDialog.h
gui/dialogs/CopyInstanceDialog.cpp
@@ -342,8 +356,6 @@ SET(MULTIMC_SOURCES
gui/pagedialog/PageDialog.h
gui/dialogs/ProgressDialog.cpp
gui/dialogs/ProgressDialog.h
- gui/dialogs/SettingsDialog.cpp
- gui/dialogs/SettingsDialog.h
gui/dialogs/UpdateDialog.cpp
gui/dialogs/UpdateDialog.h
gui/dialogs/VersionSelectDialog.cpp
@@ -427,6 +439,9 @@ SET(MULTIMC_SOURCES
# RW lock protected map
logic/RWStorage.h
+ # A variable that has an implicit default value and keeps track of changes
+ logic/DefaultVariable.h
+
# network stuffs
logic/net/NetAction.h
logic/net/MD5EtagDownload.h
@@ -493,6 +508,7 @@ SET(MULTIMC_SOURCES
logic/OneSixInstance_p.h
# OneSix version json infrastructure
+ logic/minecraft/GradleSpecifier.h
logic/minecraft/InstanceVersion.cpp
logic/minecraft/InstanceVersion.h
logic/minecraft/JarMod.cpp
@@ -641,8 +657,15 @@ SET(MULTIMC_UIS
gui/pages/ScreenshotsPage.ui
gui/pages/OtherLogsPage.ui
+ # Global settings pages
+ gui/pages/global/AccountListPage.ui
+ gui/pages/global/ExternalToolsPage.ui
+ gui/pages/global/JavaPage.ui
+ gui/pages/global/MinecraftPage.ui
+ gui/pages/global/MultiMCPage.ui
+ gui/pages/global/ProxyPage.ui
+
# Dialogs
- gui/dialogs/SettingsDialog.ui
gui/dialogs/CopyInstanceDialog.ui
gui/dialogs/NewInstanceDialog.ui
gui/dialogs/AboutDialog.ui
@@ -650,7 +673,6 @@ SET(MULTIMC_UIS
gui/dialogs/LwjglSelectDialog.ui
gui/dialogs/ProgressDialog.ui
gui/dialogs/IconPickerDialog.ui
- gui/dialogs/AccountListDialog.ui
gui/dialogs/AccountSelectDialog.ui
gui/dialogs/EditAccountDialog.ui
gui/dialogs/LoginDialog.ui
@@ -760,7 +782,13 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInf
COMPONENT Runtime
REGEX "tga|tiff|mng" EXCLUDE
)
-
+ # Icon engines
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "fontawesome" EXCLUDE
+ )
# Platform plugins
install(
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
@@ -778,7 +806,15 @@ else()
REGEX "d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE
)
-
+ # Icon engines
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "fontawesome" EXCLUDE
+ REGEX "d\\." EXCLUDE
+ REGEX "_debug\\." EXCLUDE
+ )
# Platform plugins
install(
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
diff --git a/MultiMC.cpp b/MultiMC.cpp
index 7e7c6c88..acf05c89 100644
--- a/MultiMC.cpp
+++ b/MultiMC.cpp
@@ -357,6 +357,9 @@ void MultiMC::initGlobalSettings()
m_settings->registerSetting("AutoUpdate", true);
m_settings->registerSetting("IconTheme", QString("multimc"));
+ // Minecraft Sneaky Updates
+ m_settings->registerSetting("AutoUpdateMinecraftVersions", true);
+
// Notifications
m_settings->registerSetting("ShownNotifications", QString());
diff --git a/changelog.md b/changelog.md
index 03bd90aa..8bbade3e 100644
--- a/changelog.md
+++ b/changelog.md
@@ -3,6 +3,9 @@
##0.5.0
- In development...
+##0.4.1
+- Fix LWJGL version list (SourceForge has changed the download API)
+
##0.4.0
- Jar support in 1.6+
- Deprecated legacy instances
diff --git a/gui/ColumnResizer.cpp b/gui/ColumnResizer.cpp
new file mode 100644
index 00000000..1c5597aa
--- /dev/null
+++ b/gui/ColumnResizer.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2011 Aurélien Gâteau <agateau@kde.org>
+ * License: LGPL v2.1 or later (see COPYING)
+ */
+#include "ColumnResizer.h"
+
+#include <QDebug>
+#include <QEvent>
+#include <QFormLayout>
+#include <QGridLayout>
+#include <QTimer>
+#include <QWidget>
+
+class FormLayoutWidgetItem : public QWidgetItem
+{
+public:
+ FormLayoutWidgetItem(QWidget* widget, QFormLayout* formLayout, QFormLayout::ItemRole itemRole)
+ : QWidgetItem(widget)
+ , m_width(-1)
+ , m_formLayout(formLayout)
+ , m_itemRole(itemRole)
+ {}
+
+ QSize sizeHint() const
+ {
+ QSize size = QWidgetItem::sizeHint();
+ if (m_width != -1) {
+ size.setWidth(m_width);
+ }
+ return size;
+ }
+
+ QSize minimumSize() const
+ {
+ QSize size = QWidgetItem::minimumSize();
+ if (m_width != -1) {
+ size.setWidth(m_width);
+ }
+ return size;
+ }
+
+ QSize maximumSize() const
+ {
+ QSize size = QWidgetItem::maximumSize();
+ if (m_width != -1) {
+ size.setWidth(m_width);
+ }
+ return size;
+ }
+
+ void setWidth(int width)
+ {
+ if (width != m_width) {
+ m_width = width;
+ invalidate();
+ }
+ }
+
+ void setGeometry(const QRect& _rect)
+ {
+ QRect rect = _rect;
+ int width = widget()->sizeHint().width();
+ if (m_itemRole == QFormLayout::LabelRole && m_formLayout->labelAlignment() & Qt::AlignRight) {
+ rect.setLeft(rect.right() - width);
+ }
+ QWidgetItem::setGeometry(rect);
+ }
+
+ QFormLayout* formLayout() const
+ {
+ return m_formLayout;
+ }
+
+private:
+ int m_width;
+ QFormLayout* m_formLayout;
+ QFormLayout::ItemRole m_itemRole;
+};
+
+typedef QPair<QGridLayout*, int> GridColumnInfo;
+
+class ColumnResizerPrivate
+{
+public:
+ ColumnResizerPrivate(ColumnResizer* q_ptr)
+ : q(q_ptr)
+ , m_updateTimer(new QTimer(q))
+ {
+ m_updateTimer->setSingleShot(true);
+ m_updateTimer->setInterval(0);
+ QObject::connect(m_updateTimer, SIGNAL(timeout()), q, SLOT(updateWidth()));
+ }
+
+ void scheduleWidthUpdate()
+ {
+ m_updateTimer->start();
+ }
+
+ ColumnResizer* q;
+ QTimer* m_updateTimer;
+ QList<QWidget*> m_widgets;
+ QList<FormLayoutWidgetItem*> m_wrWidgetItemList;
+ QList<GridColumnInfo> m_gridColumnInfoList;
+};
+
+ColumnResizer::ColumnResizer(QObject* parent)
+: QObject(parent)
+, d(new ColumnResizerPrivate(this))
+{}
+
+ColumnResizer::~ColumnResizer()
+{
+ delete d;
+}
+
+void ColumnResizer::addWidget(QWidget* widget)
+{
+ d->m_widgets.append(widget);
+ widget->installEventFilter(this);
+ d->scheduleWidthUpdate();
+}
+
+void ColumnResizer::updateWidth()
+{
+ int width = 0;
+ Q_FOREACH(QWidget* widget, d->m_widgets) {
+ width = qMax(widget->sizeHint().width(), width);
+ }
+ Q_FOREACH(FormLayoutWidgetItem* item, d->m_wrWidgetItemList) {
+ item->setWidth(width);
+ item->formLayout()->update();
+ }
+ Q_FOREACH(GridColumnInfo info, d->m_gridColumnInfoList) {
+ info.first->setColumnMinimumWidth(info.second, width);
+ }
+}
+
+bool ColumnResizer::eventFilter(QObject*, QEvent* event)
+{
+ if (event->type() == QEvent::Resize) {
+ d->scheduleWidthUpdate();
+ }
+ return false;
+}
+
+void ColumnResizer::addWidgetsFromLayout(QLayout* layout, int column)
+{
+ Q_ASSERT(column >= 0);
+ QGridLayout* gridLayout = qobject_cast<QGridLayout*>(layout);
+ QFormLayout* formLayout = qobject_cast<QFormLayout*>(layout);
+ if (gridLayout) {
+ addWidgetsFromGridLayout(gridLayout, column);
+ } else if (formLayout) {
+ if (column > QFormLayout::SpanningRole) {
+ qCritical() << "column should not be more than" << QFormLayout::SpanningRole << "for QFormLayout";
+ return;
+ }
+ QFormLayout::ItemRole role = static_cast<QFormLayout::ItemRole>(column);
+ addWidgetsFromFormLayout(formLayout, role);
+ } else {
+ qCritical() << "Don't know how to handle layout" << layout;
+ }
+}
+
+void ColumnResizer::addWidgetsFromGridLayout(QGridLayout* layout, int column)
+{
+ for (int row = 0; row < layout->rowCount(); ++row) {
+ QLayoutItem* item = layout->itemAtPosition(row, column);
+ if (!item) {
+ continue;
+ }
+ QWidget* widget = item->widget();
+ if (!widget) {
+ continue;
+ }
+ addWidget(widget);
+ }
+ d->m_gridColumnInfoList << GridColumnInfo(layout, column);
+}
+
+void ColumnResizer::addWidgetsFromFormLayout(QFormLayout* layout, QFormLayout::ItemRole role)
+{
+ for (int row = 0; row < layout->rowCount(); ++row) {
+ QLayoutItem* item = layout->itemAt(row, role);
+ if (!item) {
+ continue;
+ }
+ QWidget* widget = item->widget();
+ if (!widget) {
+ continue;
+ }
+ layout->removeItem(item);
+ delete item;
+ FormLayoutWidgetItem* newItem = new FormLayoutWidgetItem(widget, layout, role);
+ layout->setItem(row, role, newItem);
+ addWidget(widget);
+ d->m_wrWidgetItemList << newItem;
+ }
+}
+
+#include <ColumnResizer.moc>
+// vi: ts=4 sw=4 et
diff --git a/gui/ColumnResizer.h b/gui/ColumnResizer.h
new file mode 100644
index 00000000..4bbac383
--- /dev/null
+++ b/gui/ColumnResizer.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011 Aurélien Gâteau <agateau@kde.org>
+ * License: LGPL v2.1 or later (see COPYING)
+ */
+#pragma once
+
+#include <QFormLayout>
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+
+class QEvent;
+class QGridLayout;
+class QLayout;
+class QWidget;
+
+class ColumnResizerPrivate;
+class ColumnResizer : public QObject
+{
+ Q_OBJECT
+public:
+ ColumnResizer(QObject* parent = 0);
+ ~ColumnResizer();
+
+ void addWidget(QWidget* widget);
+ void addWidgetsFromLayout(QLayout*, int column);
+ void addWidgetsFromGridLayout(QGridLayout*, int column);
+ void addWidgetsFromFormLayout(QFormLayout*, QFormLayout::ItemRole role);
+
+private Q_SLOTS:
+ void updateWidth();
+
+protected:
+ bool eventFilter(QObject*, QEvent* event);
+
+private:
+ ColumnResizerPrivate* const d;
+};
diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp
index 1a92139c..ce03d7b9 100644
--- a/gui/MainWindow.cpp
+++ b/gui/MainWindow.cpp
@@ -49,7 +49,6 @@
#include "gui/widgets/LabeledToolButton.h"
#include "widgets/ServerStatus.h"
-#include "gui/dialogs/SettingsDialog.h"
#include "gui/dialogs/NewInstanceDialog.h"
#include "gui/dialogs/ProgressDialog.h"
#include "gui/dialogs/AboutDialog.h"
@@ -58,12 +57,18 @@
#include "gui/dialogs/LwjglSelectDialog.h"
#include "gui/dialogs/IconPickerDialog.h"
#include "gui/dialogs/CopyInstanceDialog.h"
-#include "gui/dialogs/AccountListDialog.h"
#include "gui/dialogs/AccountSelectDialog.h"
#include "gui/dialogs/UpdateDialog.h"
#include "gui/dialogs/EditAccountDialog.h"
#include "gui/dialogs/NotificationDialog.h"
+#include "gui/pages/global/MultiMCPage.h"
+#include "gui/pages/global/ExternalToolsPage.h"
+#include "gui/pages/global/AccountListPage.h"
+#include "pages/global/ProxyPage.h"
+#include "pages/global/JavaPage.h"
+#include "pages/global/MinecraftPage.h"
+
#include "gui/ConsoleWindow.h"
#include "pagedialog/PageDialog.h"
@@ -245,6 +250,17 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
ui->mainToolBar->addAction(accountMenuButtonAction);
+ // set up global pages dialog
+ {
+ m_globalSettingsProvider = std::make_shared<GenericPageProvider>(tr("Settings"));
+ m_globalSettingsProvider->addPage<MultiMCPage>();
+ m_globalSettingsProvider->addPage<MinecraftPage>();
+ m_globalSettingsProvider->addPage<JavaPage>();
+ m_globalSettingsProvider->addPage<ProxyPage>();
+ m_globalSettingsProvider->addPage<ExternalToolsPage>();
+ m_globalSettingsProvider->addPage<AccountListPage>();
+ }
+
// Update the menu when the active account changes.
// Shouldn't have to use lambdas here like this, but if I don't, the compiler throws a fit.
// Template hell sucks...
@@ -937,16 +953,6 @@ void MainWindow::on_actionCheckUpdate_triggered()
updater->checkForUpdate(true);
}
-void MainWindow::on_actionSettings_triggered()
-{
- SettingsDialog dialog(this);
- dialog.exec();
- // FIXME: quick HACK to make this work. improve, optimize.
- proxymodel->invalidate();
- proxymodel->sort(0);
- updateToolsMenu();
-}
-
template <typename T>
void ShowPageDialog(T raw_provider, QWidget * parent, QString open_page = QString())
{
@@ -957,6 +963,15 @@ void ShowPageDialog(T raw_provider, QWidget * parent, QString open_page = QStrin
dlg.exec();
}
+void MainWindow::on_actionSettings_triggered()
+{
+ ShowPageDialog(m_globalSettingsProvider, this, "global-settings");
+ // FIXME: quick HACK to make this work. improve, optimize.
+ proxymodel->invalidate();
+ proxymodel->sort(0);
+ updateToolsMenu();
+}
+
void MainWindow::on_actionInstanceSettings_triggered()
{
ShowPageDialog(m_selectedInstance, this, "settings");
@@ -980,8 +995,7 @@ void MainWindow::on_actionScreenshots_triggered()
void MainWindow::on_actionManageAccounts_triggered()
{
- AccountListDialog dialog(this);
- dialog.exec();
+ ShowPageDialog(m_globalSettingsProvider, this, "accounts");
}
void MainWindow::on_actionReportBug_triggered()
diff --git a/gui/MainWindow.h b/gui/MainWindow.h
index 36ef883b..32ad4daf 100644
--- a/gui/MainWindow.h
+++ b/gui/MainWindow.h
@@ -30,6 +30,7 @@ class QLabel;
class MinecraftProcess;
class ConsoleWindow;
class BaseProfilerFactory;
+class GenericPageProvider;
namespace Ui
{
@@ -189,6 +190,8 @@ private:
QToolButton *changeIconButton;
QToolButton *newsLabel;
+ std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
+
InstancePtr m_selectedInstance;
QString m_currentInstIcon;
diff --git a/gui/dialogs/AboutDialog.ui b/gui/dialogs/AboutDialog.ui
index 04983299..93fa8963 100644
--- a/gui/dialogs/AboutDialog.ui
+++ b/gui/dialogs/AboutDialog.ui
@@ -96,7 +96,7 @@
<item>
<widget class="QToolBox" name="toolBox">
<property name="currentIndex">
- <number>1</number>
+ <number>0</number>
</property>
<widget class="QWidget" name="aboutPage">
<property name="geometry">
@@ -104,7 +104,7 @@
<x>0</x>
<y>0</y>
<width>689</width>
- <height>331</height>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -229,7 +229,7 @@
<x>0</x>
<y>0</y>
<width>689</width>
- <height>331</height>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -245,8 +245,8 @@
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
@@ -271,7 +271,7 @@ p, li { white-space: pre-wrap; }
<x>0</x>
<y>0</y>
<width>689</width>
- <height>331</height>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -298,7 +298,7 @@ p, li { white-space: pre-wrap; }
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans Mono'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans Mono'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Copyright 2012-2014 MultiMC Contributors&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;);&lt;/span&gt;&lt;/p&gt;
@@ -422,7 +422,7 @@ p, li { white-space: pre-wrap; }
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; */&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;&quot;&gt;Java IconLoader class&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Copyright (c) 2011, Chris Molini&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;All rights reserved.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
@@ -447,8 +447,13 @@ p, li { white-space: pre-wrap; }
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;/span&gt;&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;&quot;&gt;ColumnResizer&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;/*&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Copyright 2011 Aurélien Gâteau &amp;lt;agateau@kde.org&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * License: LGPL v2.1 or later (see COPYING)&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; */&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
@@ -459,8 +464,8 @@ p, li { white-space: pre-wrap; }
<rect>
<x>0</x>
<y>0</y>
- <width>689</width>
- <height>331</height>
+ <width>98</width>
+ <height>88</height>
</rect>
</property>
<attribute name="label">
@@ -473,12 +478,12 @@ p, li { white-space: pre-wrap; }
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;Part of the reason for using the Apache license is we don't want people using the &amp;quot;MultiMC&amp;quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &amp;quot;MultiMC&amp;quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork &lt;/span&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:600;&quot;&gt;without&lt;/span&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt; implying that you have our blessing.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Part of the reason for using the Apache license is we don't want people using the &amp;quot;MultiMC&amp;quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &amp;quot;MultiMC&amp;quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork &lt;span style=&quot; font-weight:600;&quot;&gt;without&lt;/span&gt; implying that you have our blessing.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
diff --git a/gui/dialogs/AccountListDialog.ui b/gui/dialogs/AccountListDialog.ui
deleted file mode 100644
index 72682163..00000000
--- a/gui/dialogs/AccountListDialog.ui
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>AccountListDialog</class>
- <widget class="QDialog" name="AccountListDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>400</width>
- <height>300</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Manage Accounts</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QLabel" name="welcomeLabel">
- <property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Welcome! If you're new here, you can click the &amp;quot;Add&amp;quot; button to add your Mojang or Minecraft account.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QTreeView" name="listView"/>
- </item>
- <item>
- <layout class="QVBoxLayout" name="manageAcctsBtnBox">
- <item>
- <widget class="QPushButton" name="addAccountBtn">
- <property name="text">
- <string>&amp;Add</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="rmAccountBtn">
- <property name="text">
- <string>&amp;Remove</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="buttonSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="setDefaultBtn">
- <property name="toolTip">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set the currently selected account as the active account. The active account is the account that is used to log in (unless it is overridden in an instance-specific setting).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- <property name="text">
- <string>&amp;Set Default</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="noDefaultBtn">
- <property name="toolTip">
- <string>Set no default account. This will cause MultiMC to prompt you to select an account every time you launch an instance that doesn't have its own default set.</string>
- </property>
- <property name="text">
- <string>&amp;No Default</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QDialogButtonBox" name="closeBtnBox">
- <property name="standardButtons">
- <set>QDialogButtonBox::Close</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/gui/dialogs/IconPickerDialog.h b/gui/dialogs/IconPickerDialog.h
index 70951da6..f00c2388 100644
--- a/gui/dialogs/IconPickerDialog.h
+++ b/gui/dialogs/IconPickerDialog.h
@@ -29,10 +29,7 @@ class IconPickerDialog : public QDialog
public:
explicit IconPickerDialog(QWidget *parent = 0);
~IconPickerDialog();
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Woverloaded-virtual"
int exec(QString selection);
- #pragma clang diagnostic pop
QString selectedIconKey;
protected:
diff --git a/gui/dialogs/ProgressDialog.h b/gui/dialogs/ProgressDialog.h
index 45a6238a..3276fd7a 100644
--- a/gui/dialogs/ProgressDialog.h
+++ b/gui/dialogs/ProgressDialog.h
@@ -34,10 +34,7 @@ public:
void updateSize();
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Woverloaded-virtual"
int exec(ProgressProvider *task);
- #pragma clang diagnostic pop
void setSkipButton(bool present, QString label = QString());
diff --git a/gui/dialogs/SettingsDialog.cpp b/gui/dialogs/SettingsDialog.cpp
deleted file mode 100644
index 46368bc1..00000000
--- a/gui/dialogs/SettingsDialog.cpp
+++ /dev/null
@@ -1,704 +0,0 @@
-/* Copyright 2013 MultiMC Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "MultiMC.h"
-
-#include "gui/dialogs/SettingsDialog.h"
-#include "ui_SettingsDialog.h"
-
-#include "gui/Platform.h"
-#include "gui/dialogs/VersionSelectDialog.h"
-#include "gui/dialogs/CustomMessageBox.h"
-
-#include "logic/NagUtils.h"
-
-#include "logic/java/JavaUtils.h"
-#include "logic/java/JavaVersionList.h"
-#include "logic/java/JavaChecker.h"
-
-#include "logic/updater/UpdateChecker.h"
-
-#include "logic/tools/BaseProfiler.h"
-
-#include "logic/settings/SettingsObject.h"
-#include <pathutils.h>
-#include <QFileDialog>
-#include <QMessageBox>
-#include <QDir>
-
-// FIXME: possibly move elsewhere
-enum InstSortMode
-{
- // Sort alphabetically by name.
- Sort_Name,
- // Sort by which instance was launched most recently.
- Sort_LastLaunch
-};
-
-SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::SettingsDialog)
-{
- MultiMCPlatform::fixWM_CLASS(this);
- ui->setupUi(this);
- ui->sortingModeGroup->setId(ui->sortByNameBtn, Sort_Name);
- ui->sortingModeGroup->setId(ui->sortLastLaunchedBtn, Sort_LastLaunch);
-
-#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
- ui->jsonEditorTextBox->setClearButtonEnabled(true);
-#endif
-
- restoreGeometry(
- QByteArray::fromBase64(MMC->settings()->get("SettingsGeometry").toByteArray()));
-
- loadSettings(MMC->settings().get());
- updateCheckboxStuff();
-
- QObject::connect(MMC->updateChecker().get(), &UpdateChecker::channelListLoaded, this,
- &SettingsDialog::refreshUpdateChannelList);
-
- if (MMC->updateChecker()->hasChannels())
- {
- refreshUpdateChannelList();
- }
- else
- {
- MMC->updateChecker()->updateChanList(false);
- }
- connect(ui->proxyGroup, SIGNAL(buttonClicked(int)), SLOT(proxyChanged(int)));
- ui->mceditLink->setOpenExternalLinks(true);
- ui->jvisualvmLink->setOpenExternalLinks(true);
- ui->jprofilerLink->setOpenExternalLinks(true);
-}
-
-SettingsDialog::~SettingsDialog()
-{
- delete ui;
-}
-void SettingsDialog::showEvent(QShowEvent *ev)
-{
- QDialog::showEvent(ev);
-}
-
-void SettingsDialog::closeEvent(QCloseEvent *ev)
-{
- MMC->settings()->set("SettingsGeometry", saveGeometry().toBase64());
-
- QDialog::closeEvent(ev);
-}
-
-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());
-}
-
-void SettingsDialog::on_ftbLauncherBrowseBtn_clicked()
-{
- QString raw_dir = QFileDialog::getExistingDirectory(this, tr("FTB Launcher Directory"),
- ui->ftbLauncherBox->text());
- QString cooked_dir = NormalizePath(raw_dir);
-
- // do not allow current dir - it's dirty. Do not allow dirs that don't exist
- if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
- {
- ui->ftbLauncherBox->setText(cooked_dir);
- }
-}
-
-void SettingsDialog::on_ftbBrowseBtn_clicked()
-{
- 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
- if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
- {
- ui->ftbBox->setText(cooked_dir);
- }
-}
-
-void SettingsDialog::on_instDirBrowseBtn_clicked()
-{
- QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Instance Directory"),
- ui->instDirTextBox->text());
- QString cooked_dir = NormalizePath(raw_dir);
-
- // do not allow current dir - it's dirty. Do not allow dirs that don't exist
- if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
- {
- ui->instDirTextBox->setText(cooked_dir);
- }
-}
-void SettingsDialog::on_iconsDirBrowseBtn_clicked()
-{
- QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Icons Directory"),
- ui->iconsDirTextBox->text());
- QString cooked_dir = NormalizePath(raw_dir);
-
- // do not allow current dir - it's dirty. Do not allow dirs that don't exist
- if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
- {
- ui->iconsDirTextBox->setText(cooked_dir);
- }
-}
-
-void SettingsDialog::on_modsDirBrowseBtn_clicked()
-{
- QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Mods Directory"),
- ui->modsDirTextBox->text());
- QString cooked_dir = NormalizePath(raw_dir);
-
- // do not allow current dir - it's dirty. Do not allow dirs that don't exist
- if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
- {
- ui->modsDirTextBox->setText(cooked_dir);
- }
-}
-
-void SettingsDialog::on_lwjglDirBrowseBtn_clicked()
-{
- QString raw_dir = QFileDialog::getExistingDirectory(this, tr("LWJGL Directory"),
- ui->lwjglDirTextBox->text());
- QString cooked_dir = NormalizePath(raw_dir);
-
- // do not allow current dir - it's dirty. Do not allow dirs that don't exist
- if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
- {
- ui->lwjglDirTextBox->setText(cooked_dir);
- }
-}
-
-void SettingsDialog::on_jsonEditorBrowseBtn_clicked()
-{
- QString raw_file = QFileDialog::getOpenFileName(
- this, tr("JSON Editor"),
- ui->jsonEditorTextBox->text().isEmpty()
-#if defined(Q_OS_LINUX)
- ? QString("/usr/bin")
-#else
- ? QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).first()
-#endif
- : ui->jsonEditorTextBox->text());
- QString cooked_file = NormalizePath(raw_file);
-
- if (cooked_file.isEmpty())
- {
- return;
- }
-
- // it has to exist and be an executable
- if (QFileInfo(cooked_file).exists() && QFileInfo(cooked_file).isExecutable())
- {
- ui->jsonEditorTextBox->setText(cooked_file);
- }
- else
- {
- QMessageBox::warning(this, tr("Invalid"),
- tr("The file chosen does not seem to be an executable"));
- }
-}
-
-void SettingsDialog::on_maximizedCheckBox_clicked(bool checked)
-{
- Q_UNUSED(checked);
- updateCheckboxStuff();
-}
-
-void SettingsDialog::on_buttonBox_accepted()
-{
- applySettings(MMC->settings().get());
-
- // Apply proxy settings
- MMC->updateProxySettings();
-
- MMC->settings()->set("SettingsGeometry", saveGeometry().toBase64());
-}
-
-void SettingsDialog::on_buttonBox_rejected()
-{
- MMC->settings()->set("SettingsGeometry", saveGeometry().toBase64());
-}
-
-void SettingsDialog::proxyChanged(int)
-{
- updateCheckboxStuff();
-}
-
-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
- // description label constantly.
- QObject::disconnect(ui->updateChannelComboBox, SIGNAL(currentIndexChanged(int)), this,
- SLOT(updateChannelSelectionChanged(int)));
-
- QList<UpdateChecker::ChannelListEntry> channelList = MMC->updateChecker()->getChannelList();
- ui->updateChannelComboBox->clear();
- int selection = -1;
- for (int i = 0; i < channelList.count(); i++)
- {
- UpdateChecker::ChannelListEntry entry = channelList.at(i);
-
- // When it comes to selection, we'll rely on the indexes of a channel entry being the
- // same in the
- // combo box as it is in the update checker's channel list.
- // This probably isn't very safe, but the channel list doesn't change often enough (or
- // at all) for
- // this to be a big deal. Hope it doesn't break...
- ui->updateChannelComboBox->addItem(entry.name);
-
- // If the update channel we just added was the selected one, set the current index in
- // the combo box to it.
- if (entry.id == m_currentUpdateChannel)
- {
- 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)));
- refreshUpdateChannelDesc();
-
- // Now that we've updated the channel list, we can enable the combo box.
- // It starts off disabled so that if the channel list hasn't been loaded, it will be
- // disabled.
- ui->updateChannelComboBox->setEnabled(true);
-}
-
-void SettingsDialog::updateChannelSelectionChanged(int index)
-{
- refreshUpdateChannelDesc();
-}
-
-void SettingsDialog::refreshUpdateChannelDesc()
-{
- // Get the channel list.
- QList<UpdateChecker::ChannelListEntry> channelList = MMC->updateChecker()->getChannelList();
- int selectedIndex = ui->updateChannelComboBox->currentIndex();
- if (selectedIndex < 0)
- {
- return;
- }
- if (selectedIndex < channelList.count())
- {
- // Find the channel list entry with the given index.
- UpdateChecker::ChannelListEntry selected = channelList.at(selectedIndex);
-
- // Set the description text.
- ui->updateChannelDescLabel->setText(selected.description);
-
- // Set the currently selected channel ID.
- m_currentUpdateChannel = selected.id;
- }
-}
-
-void SettingsDialog::applySettings(SettingsObject *s)
-{
- // Language
- s->set("Language",
- ui->languageBox->itemData(ui->languageBox->currentIndex()).toLocale().bcp47Name());
-
- if (ui->resetNotificationsBtn->isChecked())
- {
- s->set("ShownNotifications", QString());
- }
-
- // Updates
- s->set("AutoUpdate", ui->autoUpdateCheckBox->isChecked());
- s->set("UpdateChannel", m_currentUpdateChannel);
- //FIXME: make generic
- switch (ui->themeComboBox->currentIndex())
- {
- case 1:
- s->set("IconTheme", "pe_dark");
- break;
- case 2:
- s->set("IconTheme", "pe_light");
- break;
- case 0:
- default:
- s->set("IconTheme", "multimc");
- break;
- }
- // FTB
- s->set("TrackFTBInstances", ui->trackFtbBox->isChecked());
- s->set("FTBLauncherRoot", ui->ftbLauncherBox->text());
- s->set("FTBRoot", ui->ftbBox->text());
-
- // Folders
- // TODO: Offer to move instances to new instance folder.
- s->set("InstanceDir", ui->instDirTextBox->text());
- s->set("CentralModsDir", ui->modsDirTextBox->text());
- s->set("LWJGLDir", ui->lwjglDirTextBox->text());
- s->set("IconsDir", ui->iconsDirTextBox->text());
-
- // Editors
- QString jsonEditor = ui->jsonEditorTextBox->text();
- if (!jsonEditor.isEmpty() &&
- (!QFileInfo(jsonEditor).exists() || !QFileInfo(jsonEditor).isExecutable()))
- {
- QString found = QStandardPaths::findExecutable(jsonEditor);
- if (!found.isEmpty())
- {
- jsonEditor = found;
- }
- }
- s->set("JsonEditor", jsonEditor);
-
- // Console
- s->set("ShowConsole", ui->showConsoleCheck->isChecked());
- s->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked());
-
- // Window Size
- s->set("LaunchMaximized", ui->maximizedCheckBox->isChecked());
- s->set("MinecraftWinWidth", ui->windowWidthSpinBox->value());
- s->set("MinecraftWinHeight", ui->windowHeightSpinBox->value());
-
- // Proxy
- QString proxyType = "None";
- if (ui->proxyDefaultBtn->isChecked())
- proxyType = "Default";
- else if (ui->proxyNoneBtn->isChecked())
- proxyType = "None";
- else if (ui->proxySOCKS5Btn->isChecked())
- proxyType = "SOCKS5";
- else if (ui->proxyHTTPBtn->isChecked())
- proxyType = "HTTP";
-
- s->set("ProxyType", proxyType);
- s->set("ProxyAddr", ui->proxyAddrEdit->text());
- s->set("ProxyPort", ui->proxyPortEdit->value());
- s->set("ProxyUser", ui->proxyUserEdit->text());
- s->set("ProxyPass", ui->proxyPassEdit->text());
-
- // Memory
- s->set("MinMemAlloc", ui->minMemSpinBox->value());
- s->set("MaxMemAlloc", ui->maxMemSpinBox->value());
- s->set("PermGen", ui->permGenSpinBox->value());
-
- // Java Settings
- s->set("JavaPath", ui->javaPathTextBox->text());
- s->set("JvmArgs", ui->jvmArgsTextBox->text());
- NagUtils::checkJVMArgs(s->get("JvmArgs").toString(), this->parentWidget());
-
- // Custom Commands
- s->set("PreLaunchCommand", ui->preLaunchCmdTextBox->text());
- s->set("PostExitCommand", ui->postExitCmdTextBox->text());
-
- auto sortMode = (InstSortMode)ui->sortingModeGroup->checkedId();
- switch (sortMode)
- {
- case Sort_LastLaunch:
- s->set("InstSortMode", "LastLaunch");
- break;
- case Sort_Name:
- default:
- s->set("InstSortMode", "Name");
- break;
- }
-
- 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)
-{
- // Language
- ui->languageBox->clear();
- ui->languageBox->addItem(tr("English"), QLocale(QLocale::English));
- foreach(const QString & lang, QDir(MMC->staticData() + "/translations")
- .entryList(QStringList() << "*.qm", QDir::Files))
- {
- QLocale locale(lang.section(QRegExp("[_\\.]"), 1));
- ui->languageBox->addItem(QLocale::languageToString(locale.language()), locale);
- }
- ui->languageBox->setCurrentIndex(
- ui->languageBox->findData(QLocale(s->get("Language").toString())));
-
- // Updates
- ui->autoUpdateCheckBox->setChecked(s->get("AutoUpdate").toBool());
- m_currentUpdateChannel = s->get("UpdateChannel").toString();
- //FIXME: make generic
- auto theme = s->get("IconTheme").toString();
- if (theme == "pe_dark")
- {
- ui->themeComboBox->setCurrentIndex(1);
- }
- else if (theme == "pe_light")
- {
- ui->themeComboBox->setCurrentIndex(2);
- }
- else
- {
- ui->themeComboBox->setCurrentIndex(0);
- }
- // FTB
- ui->trackFtbBox->setChecked(s->get("TrackFTBInstances").toBool());
- ui->ftbLauncherBox->setText(s->get("FTBLauncherRoot").toString());
- ui->ftbBox->setText(s->get("FTBRoot").toString());
-
- // Folders
- ui->instDirTextBox->setText(s->get("InstanceDir").toString());
- ui->modsDirTextBox->setText(s->get("CentralModsDir").toString());
- ui->lwjglDirTextBox->setText(s->get("LWJGLDir").toString());
- ui->iconsDirTextBox->setText(s->get("IconsDir").toString());
-
- // Editors
- ui->jsonEditorTextBox->setText(s->get("JsonEditor").toString());
-
- // Console
- ui->showConsoleCheck->setChecked(s->get("ShowConsole").toBool());
- ui->autoCloseConsoleCheck->setChecked(s->get("AutoCloseConsole").toBool());
-
- // Window Size
- ui->maximizedCheckBox->setChecked(s->get("LaunchMaximized").toBool());
- ui->windowWidthSpinBox->setValue(s->get("MinecraftWinWidth").toInt());
- ui->windowHeightSpinBox->setValue(s->get("MinecraftWinHeight").toInt());
-
- // Memory
- ui->minMemSpinBox->setValue(s->get("MinMemAlloc").toInt());
- ui->maxMemSpinBox->setValue(s->get("MaxMemAlloc").toInt());
- ui->permGenSpinBox->setValue(s->get("PermGen").toInt());
-
- QString sortMode = s->get("InstSortMode").toString();
-
- if (sortMode == "LastLaunch")
- {
- ui->sortLastLaunchedBtn->setChecked(true);
- }
- else
- {
- ui->sortByNameBtn->setChecked(true);
- }
-
- // Proxy
- QString proxyType = s->get("ProxyType").toString();
- if (proxyType == "Default")
- ui->proxyDefaultBtn->setChecked(true);
- else if (proxyType == "None")
- ui->proxyNoneBtn->setChecked(true);
- else if (proxyType == "SOCKS5")
- ui->proxySOCKS5Btn->setChecked(true);
- else if (proxyType == "HTTP")
- ui->proxyHTTPBtn->setChecked(true);
-
- ui->proxyAddrEdit->setText(s->get("ProxyAddr").toString());
- ui->proxyPortEdit->setValue(s->get("ProxyPort").value<qint16>());
- ui->proxyUserEdit->setText(s->get("ProxyUser").toString());
- ui->proxyPassEdit->setText(s->get("ProxyPass").toString());
-
- // Java Settings
- ui->javaPathTextBox->setText(s->get("JavaPath").toString());
- ui->jvmArgsTextBox->setText(s->get("JvmArgs").toString());
-
- // 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()
-{
- JavaVersionPtr java;
-
- VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true);
- vselect.setResizeOn(2);
- vselect.exec();
-
- if (vselect.result() == QDialog::Accepted && vselect.selectedVersion())
- {
- java = std::dynamic_pointer_cast<JavaVersion>(vselect.selectedVersion());
- ui->javaPathTextBox->setText(java->path);
- }
-}
-
-void SettingsDialog::on_javaBrowseBtn_clicked()
-{
- QString dir = QFileDialog::getOpenFileName(this, tr("Find Java executable"));
- if (!dir.isNull())
- {
- ui->javaPathTextBox->setText(dir);
- }
-}
-
-void SettingsDialog::on_javaTestBtn_clicked()
-{
- checker.reset(new JavaChecker());
- connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
- SLOT(checkFinished(JavaCheckResult)));
- checker->path = ui->javaPathTextBox->text();
- checker->performCheck();
-}
-
-void SettingsDialog::checkFinished(JavaCheckResult result)
-{
- if (result.valid)
- {
- QString text;
- text += "Java test succeeded!\n";
- if (result.is_64bit)
- text += "Using 64bit java.\n";
- text += "\n";
- text += "Platform reported: " + result.realPlatform + "\n";
- text += "Java version reported: " + result.javaVersion;
- QMessageBox::information(this, tr("Java test success"), text);
- }
- else
- {
- QMessageBox::warning(
- this, tr("Java test failure"),
- tr("The specified java binary didn't work. You should use the auto-detect feature, "
- "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.ui b/gui/dialogs/SettingsDialog.ui
deleted file mode 100644
index d4e90302..00000000
--- a/gui/dialogs/SettingsDialog.ui
+++ /dev/null
@@ -1,1122 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>SettingsDialog</class>
- <widget class="QDialog" name="SettingsDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>545</width>
- <height>609</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowTitle">
- <string>Settings</string>
- </property>
- <property name="windowIcon">
- <iconset>
- <normaloff>:/icons/toolbar/settings</normaloff>:/icons/toolbar/settings</iconset>
- </property>
- <property name="modal">
- <bool>true</bool>
- </property>
- <layout class="QVBoxLayout" name="mainLayout">
- <item>
- <widget class="QTabWidget" name="settingsTabs">
- <property name="tabShape">
- <enum>QTabWidget::Rounded</enum>
- </property>
- <property name="currentIndex">
- <number>0</number>
- </property>
- <widget class="QWidget" name="featuresTab">
- <attribute name="title">
- <string>Features</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_9">
- <item>
- <widget class="QGroupBox" name="updateSettingsBox">
- <property name="title">
- <string>Update Settings</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_7">
- <item>
- <widget class="QCheckBox" name="autoUpdateCheckBox">
- <property name="text">
- <string>Check for updates when MultiMC starts?</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="updateChannelLabel">
- <property name="text">
- <string>Update Channel:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="updateChannelComboBox">
- <property name="enabled">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="updateChannelDescLabel">
- <property name="text">
- <string>No channel selected.</string>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox">
- <property name="title">
- <string>FTB</string>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="2" column="2">
- <widget class="QPushButton" name="ftbLauncherBrowseBtn">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="maximumSize">
- <size>
- <width>28</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="focusPolicy">
- <enum>Qt::TabFocus</enum>
- </property>
- <property name="text">
- <string>...</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Launcher:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="ftbLauncherBox">
- <property name="enabled">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="0" column="0" colspan="2">
- <widget class="QCheckBox" name="trackFtbBox">
- <property name="text">
- <string>Track FTB instances</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLineEdit" name="ftbBox"/>
- </item>
- <item row="3" column="2">
- <widget class="QPushButton" name="ftbBrowseBtn">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="maximumSize">
- <size>
- <width>28</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>...</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Files:</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="foldersBox">
- <property name="title">
- <string>Folders</string>
- </property>
- <layout class="QGridLayout" name="foldersBoxLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="labelInstDir">
- <property name="text">
- <string>Instances:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="instDirTextBox"/>
- </item>
- <item row="0" column="2">
- <widget class="QToolButton" name="instDirBrowseBtn">
- <property name="text">
- <string>...</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="labelModsDir">
- <property name="text">
- <string>Mods:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="modsDirTextBox"/>
- </item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="lwjglDirTextBox"/>
- </item>
- <item row="1" column="2">
- <widget class="QToolButton" name="modsDirBrowseBtn">
- <property name="text">
- <string>...</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="labelLWJGLDir">
- <property name="text">
- <string>LWJGL:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QToolButton" name="lwjglDirBrowseBtn">
- <property name="text">
- <string>...</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLineEdit" name="iconsDirTextBox"/>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="labelIconsDir">
- <property name="text">
- <string>Icons:</string>
- </property>
- </widget>
- </item>
- <item row="3" column="2">
- <widget class="QToolButton" name="iconsDirBrowseBtn">
- <property name="text">
- <string>...</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_2">
- <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 class="QWidget" name="generalTab">
- <attribute name="title">
- <string>User Interface</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QGridLayout" name="_2">
- <item row="0" column="0">
- <widget class="QLabel" name="label_3">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Language (needs restart):</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QComboBox" name="languageBox"/>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QPushButton" name="resetNotificationsBtn">
- <property name="text">
- <string>Reset hidden notifications</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="sortingModeBox">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="title">
- <string>Sorting Mode</string>
- </property>
- <layout class="QHBoxLayout" name="sortingModeBoxLayout">
- <item>
- <widget class="QRadioButton" name="sortLastLaunchedBtn">
- <property name="text">
- <string>By last launched</string>
- </property>
- <attribute name="buttonGroup">
- <string notr="true">sortingModeGroup</string>
- </attribute>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="sortByNameBtn">
- <property name="text">
- <string>By name</string>
- </property>
- <attribute name="buttonGroup">
- <string notr="true">sortingModeGroup</string>
- </attribute>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="themeBox">
- <property name="title">
- <string>Icon Theme</string>
- </property>
- <layout class="QHBoxLayout" name="themeBoxLayout">
- <item>
- <widget class="QComboBox" name="themeComboBox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="focusPolicy">
- <enum>Qt::StrongFocus</enum>
- </property>
- <item>
- <property name="text">
- <string>Default</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Simple</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Simple (Light Icons)</string>
- </property>
- </item>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="editorsBox">
- <property name="title">
- <string>External Editors (leave empty for system default)</string>
- </property>
- <layout class="QGridLayout" name="foldersBoxLayout_2">
- <item row="0" column="1">
- <widget class="QLineEdit" name="jsonEditorTextBox"/>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="labelJsonEditor">
- <property name="text">
- <string>JSON Editor:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QToolButton" name="jsonEditorBrowseBtn">
- <property name="text">
- <string>...</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <spacer name="generalTabSpacer">
- <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 class="QWidget" name="minecraftTab">
- <attribute name="title">
- <string>Minecraft</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <widget class="QGroupBox" name="windowSizeGroupBox">
- <property name="title">
- <string>Window Size</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_4">
- <item>
- <widget class="QCheckBox" name="maximizedCheckBox">
- <property name="text">
- <string>Start Minecraft maximized?</string>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QGridLayout" name="gridLayoutWindowSize">
- <item row="1" column="0">
- <widget class="QLabel" name="labelWindowHeight">
- <property name="text">
- <string>Window height:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="labelWindowWidth">
- <property name="text">
- <string>Window width:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QSpinBox" name="windowWidthSpinBox">
- <property name="minimum">
- <number>854</number>
- </property>
- <property name="maximum">
- <number>65536</number>
- </property>
- <property name="singleStep">
- <number>1</number>
- </property>
- <property name="value">
- <number>854</number>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QSpinBox" name="windowHeightSpinBox">
- <property name="minimum">
- <number>480</number>
- </property>
- <property name="maximum">
- <number>65536</number>
- </property>
- <property name="value">
- <number>480</number>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="consoleSettingsBox">
- <property name="title">
- <string>Console Settings</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QCheckBox" name="showConsoleCheck">
- <property name="text">
- <string>Show console while the game is running?</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="autoCloseConsoleCheck">
- <property name="text">
- <string>Automatically close console when the game quits?</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacerMinecraft">
- <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 class="QWidget" name="javaTab">
- <attribute name="title">
- <string>Java</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_5">
- <item>
- <widget class="QGroupBox" name="memoryGroupBox">
- <property name="title">
- <string>Memory</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="1" column="1">
- <widget class="QSpinBox" name="maxMemSpinBox">
- <property name="toolTip">
- <string>The maximum amount of memory Minecraft is allowed to use.</string>
- </property>
- <property name="suffix">
- <string> MB</string>
- </property>
- <property name="minimum">
- <number>512</number>
- </property>
- <property name="maximum">
- <number>65536</number>
- </property>
- <property name="singleStep">
- <number>128</number>
- </property>
- <property name="value">
- <number>1024</number>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="labelMinMem">
- <property name="text">
- <string>Minimum memory allocation:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="labelMaxMem">
- <property name="text">
- <string>Maximum memory allocation:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QSpinBox" name="minMemSpinBox">
- <property name="toolTip">
- <string>The amount of memory Minecraft is started with.</string>
- </property>
- <property name="suffix">
- <string> MB</string>
- </property>
- <property name="minimum">
- <number>256</number>
- </property>
- <property name="maximum">
- <number>65536</number>
- </property>
- <property name="singleStep">
- <number>128</number>
- </property>
- <property name="value">
- <number>256</number>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="labelPermGen">
- <property name="text">
- <string>PermGen:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QSpinBox" name="permGenSpinBox">
- <property name="toolTip">
- <string>The amount of memory available to store loaded Java classes.</string>
- </property>
- <property name="suffix">
- <string> MB</string>
- </property>
- <property name="minimum">
- <number>64</number>
- </property>
- <property name="maximum">
- <number>999999999</number>
- </property>
- <property name="singleStep">
- <number>8</number>
- </property>
- <property name="value">
- <number>64</number>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="javaSettingsGroupBox">
- <property name="title">
- <string>Java Settings</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="0" column="0">
- <widget class="QLabel" name="labelJavaPath">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Java path:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QPushButton" name="javaDetectBtn">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Auto-detect...</string>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QPushButton" name="javaTestBtn">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Test</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="labelJVMArgs">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>JVM arguments:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1" colspan="2">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QLineEdit" name="javaPathTextBox"/>
- </item>
- <item>
- <widget class="QPushButton" name="javaBrowseBtn">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="maximumSize">
- <size>
- <width>28</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>...</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="2" column="1" colspan="2">
- <widget class="QLineEdit" name="jvmArgsTextBox"/>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="customCommandsGroupBox">
- <property name="title">
- <string>Custom Commands</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="1" column="0">
- <widget class="QLabel" name="labelPostExitCmd">
- <property name="text">
- <string>Post-exit command:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="labelPreLaunchCmd">
- <property name="text">
- <string>Pre-launch command:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="preLaunchCmdTextBox"/>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="postExitCmdTextBox"/>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="labelCustomCmdsDescription">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Pre-launch command runs before the instance launches and post-exit command runs after it exits. Both will be run in MultiMC's working directory with INST_ID, INST_DIR, and INST_NAME as environment variables.</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="networkTab">
- <property name="toolTip">
- <string>Network settings.</string>
- </property>
- <attribute name="title">
- <string>Network</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_6">
- <item>
- <widget class="QGroupBox" name="proxySettingsBox">
- <property name="title">
- <string>Proxy</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_8">
- <item>
- <widget class="QGroupBox" name="proxyTypeBox">
- <property name="title">
- <string>Type</string>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <widget class="QRadioButton" name="proxyDefaultBtn">
- <property name="toolTip">
- <string>Uses your system's default proxy settings.</string>
- </property>
- <property name="text">
- <string>Default</string>
- </property>
- <attribute name="buttonGroup">
- <string notr="true">proxyGroup</string>
- </attribute>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="proxyNoneBtn">
- <property name="text">
- <string>None</string>
- </property>
- <attribute name="buttonGroup">
- <string notr="true">proxyGroup</string>
- </attribute>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="proxySOCKS5Btn">
- <property name="text">
- <string>SOCKS5</string>
- </property>
- <attribute name="buttonGroup">
- <string notr="true">proxyGroup</string>
- </attribute>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="proxyHTTPBtn">
- <property name="text">
- <string>HTTP</string>
- </property>
- <attribute name="buttonGroup">
- <string notr="true">proxyGroup</string>
- </attribute>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="proxyAddrBox">
- <property name="title">
- <string>Address and Port</string>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QLineEdit" name="proxyAddrEdit">
- <property name="placeholderText">
- <string>127.0.0.1</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSpinBox" name="proxyPortEdit">
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::PlusMinus</enum>
- </property>
- <property name="maximum">
- <number>65535</number>
- </property>
- <property name="value">
- <number>8080</number>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="proxyAuthBox">
- <property name="title">
- <string>Authentication</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_5">
- <item row="0" column="1">
- <widget class="QLineEdit" name="proxyUserEdit"/>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="proxyUsernameLabel">
- <property name="text">
- <string>Username:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="proxyPasswordLabel">
- <property name="text">
- <string>Password:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="proxyPassEdit">
- <property name="echoMode">
- <enum>QLineEdit::Password</enum>
- </property>
- </widget>
- </item>
- <item row="2" column="0" colspan="2">
- <widget class="QLabel" name="proxyPlainTextWarningLabel">
- <property name="text">
- <string>Note: Proxy username and password are stored in plain text inside MultiMC's configuration file!</string>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <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 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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://www.ej-technologies.com/products/jprofiler/overview.html&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.ej-technologies.com/products/jprofiler/overview.html&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://visualvm.java.net/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://visualvm.java.net/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://www.mcedit.net/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.mcedit.net/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>
- </item>
- <item>
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <tabstops>
- <tabstop>buttonBox</tabstop>
- <tabstop>sortLastLaunchedBtn</tabstop>
- <tabstop>sortByNameBtn</tabstop>
- <tabstop>jsonEditorTextBox</tabstop>
- <tabstop>jsonEditorBrowseBtn</tabstop>
- <tabstop>maximizedCheckBox</tabstop>
- <tabstop>windowWidthSpinBox</tabstop>
- <tabstop>windowHeightSpinBox</tabstop>
- <tabstop>showConsoleCheck</tabstop>
- <tabstop>autoCloseConsoleCheck</tabstop>
- <tabstop>minMemSpinBox</tabstop>
- <tabstop>maxMemSpinBox</tabstop>
- <tabstop>permGenSpinBox</tabstop>
- <tabstop>javaPathTextBox</tabstop>
- <tabstop>javaBrowseBtn</tabstop>
- <tabstop>javaDetectBtn</tabstop>
- <tabstop>javaTestBtn</tabstop>
- <tabstop>jvmArgsTextBox</tabstop>
- <tabstop>preLaunchCmdTextBox</tabstop>
- <tabstop>postExitCmdTextBox</tabstop>
- <tabstop>settingsTabs</tabstop>
- </tabstops>
- <resources>
- <include location="../../graphics.qrc"/>
- </resources>
- <connections>
- <connection>
- <sender>buttonBox</sender>
- <signal>accepted()</signal>
- <receiver>SettingsDialog</receiver>
- <slot>accept()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>257</x>
- <y>410</y>
- </hint>
- <hint type="destinationlabel">
- <x>157</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>buttonBox</sender>
- <signal>rejected()</signal>
- <receiver>SettingsDialog</receiver>
- <slot>reject()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>325</x>
- <y>410</y>
- </hint>
- <hint type="destinationlabel">
- <x>286</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- </connections>
- <buttongroups>
- <buttongroup name="sortingModeGroup"/>
- <buttongroup name="proxyGroup"/>
- </buttongroups>
-</ui>
diff --git a/gui/pages/BasePageProvider.h b/gui/pages/BasePageProvider.h
index cff9c8e7..5e5a11fb 100644
--- a/gui/pages/BasePageProvider.h
+++ b/gui/pages/BasePageProvider.h
@@ -17,6 +17,7 @@
#include "BasePage.h"
#include <memory>
+#include <functional>
class BasePageProvider
{
@@ -25,4 +26,44 @@ public:
virtual QString dialogTitle() = 0;
};
+class GenericPageProvider : public BasePageProvider
+{
+ typedef std::function<BasePage *()> PageCreator;
+public:
+ explicit GenericPageProvider(const QString &dialogTitle)
+ : m_dialogTitle(dialogTitle)
+ {
+ }
+
+ QList<BasePage *> getPages() override
+ {
+ QList<BasePage *> pages;
+ for (PageCreator creator : m_creators)
+ {
+ pages.append(creator());
+ }
+ return pages;
+ }
+ QString dialogTitle() override { return m_dialogTitle; }
+
+ void setDialogTitle(const QString &title)
+ {
+ m_dialogTitle = title;
+ }
+ void addPageCreator(PageCreator page)
+ {
+ m_creators.append(page);
+ }
+
+ template<typename PageClass>
+ void addPage()
+ {
+ addPageCreator([](){return new PageClass();});
+ }
+
+private:
+ QList<PageCreator> m_creators;
+ QString m_dialogTitle;
+};
+
typedef std::shared_ptr<BasePageProvider> BasePageProviderPtr;
diff --git a/gui/pages/LegacyJarModPage.cpp b/gui/pages/LegacyJarModPage.cpp
index 16a2ff66..8ff23ae2 100644
--- a/gui/pages/LegacyJarModPage.cpp
+++ b/gui/pages/LegacyJarModPage.cpp
@@ -35,6 +35,8 @@ LegacyJarModPage::LegacyJarModPage(LegacyInstance *inst, QWidget *parent)
: QWidget(parent), ui(new Ui::LegacyJarModPage), m_inst(inst)
{
ui->setupUi(this);
+ ui->tabWidget->tabBar()->hide();
+
m_jarmods = m_inst->jarModList();
ui->jarModsTreeView->setModel(m_jarmods.get());
ui->jarModsTreeView->setDragDropMode(QAbstractItemView::DragDrop);
diff --git a/gui/pages/LegacyJarModPage.ui b/gui/pages/LegacyJarModPage.ui
index a1da2b20..50edfc8e 100644
--- a/gui/pages/LegacyJarModPage.ui
+++ b/gui/pages/LegacyJarModPage.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>378</width>
- <height>324</height>
+ <width>659</width>
+ <height>593</height>
</rect>
</property>
<property name="windowTitle">
@@ -27,100 +27,114 @@
<number>0</number>
</property>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="ModListView" name="jarModsTreeView">
- <property name="verticalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOn</enum>
- </property>
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOff</enum>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QVBoxLayout" name="jarModsButtonBox">
- <item>
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Selection</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="rmJarBtn">
- <property name="text">
- <string>&amp;Remove</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="moveJarUpBtn">
- <property name="text">
- <string>Move &amp;Up</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="moveJarDownBtn">
- <property name="text">
- <string>Move &amp;Down</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="LineSeparator" name="separator" native="true"/>
- </item>
- <item>
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Install</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="addJarBtn">
- <property name="text">
- <string>&amp;Add jar mod</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="addForgeBtn">
- <property name="text">
- <string>Install Forge</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QPushButton" name="viewJarBtn">
- <property name="text">
- <string>&amp;View Folder</string>
- </property>
- </widget>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="ModListView" name="jarModsTreeView">
+ <property name="verticalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOn</enum>
+ </property>
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="jarModsButtonBox">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Selection</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="rmJarBtn">
+ <property name="text">
+ <string>&amp;Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="moveJarUpBtn">
+ <property name="text">
+ <string>Move &amp;Up</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="moveJarDownBtn">
+ <property name="text">
+ <string>Move &amp;Down</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="LineSeparator" name="separator" native="true"/>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Install</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="addJarBtn">
+ <property name="text">
+ <string>&amp;Add jar mod</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="addForgeBtn">
+ <property name="text">
+ <string>Install Forge</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="viewJarBtn">
+ <property name="text">
+ <string>&amp;View Folder</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
</item>
</layout>
- </item>
- </layout>
+ </widget>
+ </widget>
</item>
<item>
<widget class="MCModInfoFrame" name="jarMIFrame">
diff --git a/gui/pages/LogPage.cpp b/gui/pages/LogPage.cpp
index 601c738f..7fbf5929 100644
--- a/gui/pages/LogPage.cpp
+++ b/gui/pages/LogPage.cpp
@@ -11,6 +11,7 @@ LogPage::LogPage(MinecraftProcess *proc, QWidget *parent)
: QWidget(parent), ui(new Ui::LogPage), m_process(proc)
{
ui->setupUi(this);
+ ui->tabWidget->tabBar()->hide();
connect(m_process, SIGNAL(log(QString, MessageLevel::Enum)), this,
SLOT(write(QString, MessageLevel::Enum)));
}
diff --git a/gui/pages/LogPage.ui b/gui/pages/LogPage.ui
index d6b0a0c0..b87a7522 100644
--- a/gui/pages/LogPage.ui
+++ b/gui/pages/LogPage.ui
@@ -13,7 +13,7 @@
<property name="windowTitle">
<string>Log</string>
</property>
- <layout class="QGridLayout" name="gridLayout">
+ <layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
@@ -26,112 +26,126 @@
<property name="bottomMargin">
<number>0</number>
</property>
- <item row="2" column="1">
- <widget class="QLineEdit" name="lineEdit">
- <property name="enabled">
- <bool>false</bool>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
</property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="2" column="0">
+ <widget class="QLabel" name="label">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Search:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="lineEdit">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QPushButton" name="pushButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Find next</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="3">
+ <widget class="QPlainTextEdit" name="text">
+ <property name="undoRedoEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ <property name="plainText">
+ <string notr="true"/>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ <property name="centerOnScroll">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="3">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QCheckBox" name="checkBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Keep updating</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnCopy">
+ <property name="toolTip">
+ <string>Copy the whole log into the clipboard</string>
+ </property>
+ <property name="text">
+ <string>&amp;Copy</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnPaste">
+ <property name="toolTip">
+ <string>Upload the log to paste.ee - it will stay online for a month</string>
+ </property>
+ <property name="text">
+ <string>Upload</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnClear">
+ <property name="toolTip">
+ <string>Clear the log</string>
+ </property>
+ <property name="text">
+ <string>Clear</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QLabel" name="label">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Search:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QPushButton" name="pushButton">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Find next</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0" colspan="3">
- <widget class="QPlainTextEdit" name="text">
- <property name="undoRedoEnabled">
- <bool>false</bool>
- </property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
- <property name="plainText">
- <string notr="true"/>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- <property name="centerOnScroll">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="0" column="0" colspan="3">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QCheckBox" name="checkBox">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Keep updating</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="btnCopy">
- <property name="toolTip">
- <string>Copy the whole log into the clipboard</string>
- </property>
- <property name="text">
- <string>&amp;Copy</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnPaste">
- <property name="toolTip">
- <string>Upload the log to paste.ee - it will stay online for a month</string>
- </property>
- <property name="text">
- <string>Upload</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnClear">
- <property name="toolTip">
- <string>Clear the log</string>
- </property>
- <property name="text">
- <string>Clear</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
</layout>
</widget>
<resources/>
diff --git a/gui/pages/ModFolderPage.cpp b/gui/pages/ModFolderPage.cpp
index d94696ec..24421e55 100644
--- a/gui/pages/ModFolderPage.cpp
+++ b/gui/pages/ModFolderPage.cpp
@@ -38,6 +38,7 @@ ModFolderPage::ModFolderPage(BaseInstance *inst, std::shared_ptr<ModList> mods,
: QWidget(parent), ui(new Ui::ModFolderPage)
{
ui->setupUi(this);
+ ui->tabWidget->tabBar()->hide();
m_inst = inst;
m_mods = mods;
m_id = id;
diff --git a/gui/pages/ModFolderPage.ui b/gui/pages/ModFolderPage.ui
index eb29a2c0..019b8faf 100644
--- a/gui/pages/ModFolderPage.ui
+++ b/gui/pages/ModFolderPage.ui
@@ -13,7 +13,7 @@
<property name="windowTitle">
<string>Mods</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
+ <layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
@@ -27,10 +27,16 @@
<number>0</number>
</property>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
<widget class="ModListView" name="modTreeView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
@@ -46,56 +52,56 @@
</property>
</widget>
</item>
- </layout>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QPushButton" name="addModBtn">
- <property name="text">
- <string>&amp;Add</string>
- </property>
- </widget>
+ <item row="0" column="1">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QPushButton" name="addModBtn">
+ <property name="text">
+ <string>&amp;Add</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="rmModBtn">
+ <property name="text">
+ <string>&amp;Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="viewModBtn">
+ <property name="text">
+ <string>&amp;View Folder</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
- <item>
- <widget class="QPushButton" name="rmModBtn">
- <property name="text">
- <string>&amp;Remove</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="viewModBtn">
- <property name="text">
- <string>&amp;View Folder</string>
+ <item row="1" column="0" colspan="2">
+ <widget class="MCModInfoFrame" name="frame">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
</property>
</widget>
</item>
</layout>
- </item>
- </layout>
- </item>
- <item>
- <widget class="MCModInfoFrame" name="frame">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
+ </widget>
</widget>
</item>
</layout>
diff --git a/gui/pages/NotesPage.cpp b/gui/pages/NotesPage.cpp
index a2558e3c..48bb468c 100644
--- a/gui/pages/NotesPage.cpp
+++ b/gui/pages/NotesPage.cpp
@@ -5,6 +5,7 @@ NotesPage::NotesPage(BaseInstance *inst, QWidget *parent)
: QWidget(parent), ui(new Ui::NotesPage), m_inst(inst)
{
ui->setupUi(this);
+ ui->tabWidget->tabBar()->hide();
ui->noteEditor->setText(m_inst->notes());
}
diff --git a/gui/pages/NotesPage.ui b/gui/pages/NotesPage.ui
index ab33ffd3..8da01c8b 100644
--- a/gui/pages/NotesPage.ui
+++ b/gui/pages/NotesPage.ui
@@ -6,14 +6,14 @@
<rect>
<x>0</x>
<y>0</y>
- <width>400</width>
- <height>300</height>
+ <width>731</width>
+ <height>538</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
@@ -27,16 +27,30 @@
<number>0</number>
</property>
<item>
- <widget class="QTextEdit" name="noteEditor">
- <property name="verticalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOn</enum>
- </property>
- <property name="acceptRichText">
- <bool>false</bool>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextEditable|Qt::TextEditorInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
</property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTextEdit" name="noteEditor">
+ <property name="verticalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOn</enum>
+ </property>
+ <property name="acceptRichText">
+ <bool>false</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextEditable|Qt::TextEditorInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
</layout>
diff --git a/gui/pages/OtherLogsPage.cpp b/gui/pages/OtherLogsPage.cpp
index 555075e3..55c632fd 100644
--- a/gui/pages/OtherLogsPage.cpp
+++ b/gui/pages/OtherLogsPage.cpp
@@ -28,6 +28,7 @@ OtherLogsPage::OtherLogsPage(BaseInstance *instance, QWidget *parent)
m_watcher(new RecursiveFileSystemWatcher(this))
{
ui->setupUi(this);
+ ui->tabWidget->tabBar()->hide();
m_watcher->setFileExpression("(.*\\.log(\\.[0-9]*)?$)|(crash-.*\\.txt)");
m_watcher->setRootDir(QDir::current().absoluteFilePath(m_instance->minecraftRoot()));
diff --git a/gui/pages/OtherLogsPage.ui b/gui/pages/OtherLogsPage.ui
index 1083ebcb..08200684 100644
--- a/gui/pages/OtherLogsPage.ui
+++ b/gui/pages/OtherLogsPage.ui
@@ -13,7 +13,7 @@
<property name="windowTitle">
<string>Form</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
@@ -27,70 +27,84 @@
<number>0</number>
</property>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QComboBox" name="selectLogBox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnReload">
- <property name="text">
- <string>Reload</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnCopy">
- <property name="toolTip">
- <string>Copy the whole log into the clipboard</string>
- </property>
- <property name="text">
- <string>&amp;Copy</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnPaste">
- <property name="toolTip">
- <string>Upload the log to paste.ee - it will stay online for a month</string>
- </property>
- <property name="text">
- <string>Upload</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnDelete">
- <property name="toolTip">
- <string>Clear the log</string>
- </property>
- <property name="text">
- <string>Delete</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QPlainTextEdit" name="text">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="verticalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOn</enum>
- </property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
</property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QComboBox" name="selectLogBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnReload">
+ <property name="text">
+ <string>Reload</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnCopy">
+ <property name="toolTip">
+ <string>Copy the whole log into the clipboard</string>
+ </property>
+ <property name="text">
+ <string>&amp;Copy</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnPaste">
+ <property name="toolTip">
+ <string>Upload the log to paste.ee - it will stay online for a month</string>
+ </property>
+ <property name="text">
+ <string>Upload</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnDelete">
+ <property name="toolTip">
+ <string>Clear the log</string>
+ </property>
+ <property name="text">
+ <string>Delete</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="text">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="verticalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOn</enum>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
</layout>
diff --git a/gui/pages/ScreenshotsPage.cpp b/gui/pages/ScreenshotsPage.cpp
index 004f797b..d47a2897 100644
--- a/gui/pages/ScreenshotsPage.cpp
+++ b/gui/pages/ScreenshotsPage.cpp
@@ -222,6 +222,7 @@ ScreenshotsPage::ScreenshotsPage(BaseInstance *instance, QWidget *parent)
m_valid = ensureFolderPathExists(m_folder);
ui->setupUi(this);
+ ui->tabWidget->tabBar()->hide();
ui->listView->setModel(m_filterModel.get());
ui->listView->setIconSize(QSize(128, 128));
ui->listView->setGridSize(QSize(192, 160));
diff --git a/gui/pages/ScreenshotsPage.ui b/gui/pages/ScreenshotsPage.ui
index 5951ab02..30b55092 100644
--- a/gui/pages/ScreenshotsPage.ui
+++ b/gui/pages/ScreenshotsPage.ui
@@ -13,7 +13,7 @@
<property name="windowTitle">
<string>Mods</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
+ <layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
@@ -27,9 +27,15 @@
<number>0</number>
</property>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ <layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QListView" name="listView">
<property name="selectionMode">
@@ -40,54 +46,54 @@
</property>
</widget>
</item>
- </layout>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QPushButton" name="uploadBtn">
- <property name="text">
- <string>&amp;Upload</string>
- </property>
- </widget>
- </item>
<item>
- <widget class="QPushButton" name="deleteBtn">
- <property name="text">
- <string>&amp;Delete</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="renameBtn">
- <property name="text">
- <string>&amp;Rename</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="viewFolderBtn">
- <property name="text">
- <string>&amp;View Folder</string>
- </property>
- </widget>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QPushButton" name="uploadBtn">
+ <property name="text">
+ <string>&amp;Upload</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="deleteBtn">
+ <property name="text">
+ <string>&amp;Delete</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="renameBtn">
+ <property name="text">
+ <string>&amp;Rename</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="viewFolderBtn">
+ <property name="text">
+ <string>&amp;View Folder</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
</layout>
- </item>
- </layout>
+ </widget>
+ </widget>
</item>
</layout>
</widget>
diff --git a/gui/pages/VersionPage.cpp b/gui/pages/VersionPage.cpp
index 6e29dd41..e19cf7cc 100644
--- a/gui/pages/VersionPage.cpp
+++ b/gui/pages/VersionPage.cpp
@@ -63,7 +63,7 @@ VersionPage::VersionPage(OneSixInstance *inst, QWidget *parent)
: QWidget(parent), ui(new Ui::VersionPage), m_inst(inst)
{
ui->setupUi(this);
- // libraries!
+ ui->tabWidget->tabBar()->hide();
m_version = m_inst->getFullVersion();
if (m_version)
diff --git a/gui/pages/VersionPage.ui b/gui/pages/VersionPage.ui
index f770df55..9b270d01 100644
--- a/gui/pages/VersionPage.ui
+++ b/gui/pages/VersionPage.ui
@@ -6,17 +6,14 @@
<rect>
<x>0</x>
<y>0</y>
- <width>400</width>
- <height>475</height>
+ <width>693</width>
+ <height>575</height>
</rect>
</property>
<property name="windowTitle">
<string>Version</string>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="spacing">
- <number>6</number>
- </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
@@ -30,152 +27,162 @@
<number>0</number>
</property>
<item>
- <layout class="QVBoxLayout" name="verticalLayout_10">
- <item>
- <widget class="ModListView" name="libraryTreeView">
- <property name="verticalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOn</enum>
- </property>
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOff</enum>
- </property>
- <property name="headerHidden">
- <bool>false</bool>
- </property>
- <attribute name="headerVisible">
- <bool>true</bool>
- </attribute>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_4">
- <item>
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Selection</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="changeMCVersionBtn">
- <property name="text">
- <string>Change version</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="moveLibraryUpBtn">
- <property name="toolTip">
- <string>This isn't implemented yet.</string>
- </property>
- <property name="text">
- <string>Move up</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="moveLibraryDownBtn">
- <property name="toolTip">
- <string>This isn't implemented yet.</string>
- </property>
- <property name="text">
- <string>Move down</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="removeLibraryBtn">
- <property name="text">
- <string>Remove</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="LineSeparator" name="separator" native="true"/>
- </item>
- <item>
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Install</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="forgeBtn">
- <property name="toolTip">
- <string>Replace any current custom version with Minecraft Forge</string>
- </property>
- <property name="text">
- <string>Install Forge</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="liteloaderBtn">
- <property name="text">
- <string>Install LiteLoader</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="jarmodBtn">
- <property name="text">
- <string>Add jar mod</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="LineSeparator" name="widget" native="true"/>
- </item>
- <item>
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>List</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="resetLibraryOrderBtn">
- <property name="toolTip">
- <string>This isn't implemented yet.</string>
- </property>
- <property name="text">
- <string>Reset order</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="reloadLibrariesBtn">
- <property name="text">
- <string>Reload</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_7">
- <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 class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="ModListView" name="libraryTreeView">
+ <property name="verticalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOn</enum>
+ </property>
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="headerHidden">
+ <bool>false</bool>
+ </property>
+ <attribute name="headerVisible">
+ <bool>true</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Selection</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="changeMCVersionBtn">
+ <property name="text">
+ <string>Change version</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="moveLibraryUpBtn">
+ <property name="toolTip">
+ <string>This isn't implemented yet.</string>
+ </property>
+ <property name="text">
+ <string>Move up</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="moveLibraryDownBtn">
+ <property name="toolTip">
+ <string>This isn't implemented yet.</string>
+ </property>
+ <property name="text">
+ <string>Move down</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="removeLibraryBtn">
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="LineSeparator" name="separator" native="true"/>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Install</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="forgeBtn">
+ <property name="toolTip">
+ <string>Replace any current custom version with Minecraft Forge</string>
+ </property>
+ <property name="text">
+ <string>Install Forge</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="liteloaderBtn">
+ <property name="text">
+ <string>Install LiteLoader</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="jarmodBtn">
+ <property name="text">
+ <string>Add jar mod</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="LineSeparator" name="widget" native="true"/>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>List</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="resetLibraryOrderBtn">
+ <property name="toolTip">
+ <string>This isn't implemented yet.</string>
+ </property>
+ <property name="text">
+ <string>Reset order</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="reloadLibrariesBtn">
+ <property name="text">
+ <string>Reload</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_7">
+ <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>
+ </item>
+ </layout>
+ </widget>
+ </widget>
</item>
</layout>
</widget>
diff --git a/gui/dialogs/AccountListDialog.cpp b/gui/pages/global/AccountListPage.cpp
index 688cffa8..00487d57 100644
--- a/gui/dialogs/AccountListDialog.cpp
+++ b/gui/pages/global/AccountListPage.cpp
@@ -13,30 +13,31 @@
* limitations under the License.
*/
-#include "AccountListDialog.h"
-#include "ui_AccountListDialog.h"
+#include "AccountListPage.h"
+#include "ui_AccountListPage.h"
#include <QItemSelectionModel>
#include <logger/QsLog.h>
-#include <logic/net/NetJob.h>
-#include <logic/net/URLConstants.h>
+#include "logic/net/NetJob.h"
+#include "logic/net/URLConstants.h"
-#include <gui/dialogs/EditAccountDialog.h>
-#include <gui/dialogs/ProgressDialog.h>
-#include <gui/dialogs/AccountSelectDialog.h>
-#include <gui/dialogs/LoginDialog.h>
-#include "CustomMessageBox.h"
-#include <logic/tasks/Task.h>
-#include <logic/auth/YggdrasilTask.h>
+#include "gui/dialogs/EditAccountDialog.h"
+#include "gui/dialogs/ProgressDialog.h"
+#include "gui/dialogs/AccountSelectDialog.h"
+#include "gui/dialogs/LoginDialog.h"
+#include "gui/dialogs/CustomMessageBox.h"
+#include "logic/tasks/Task.h"
+#include "logic/auth/YggdrasilTask.h"
#include <MultiMC.h>
-AccountListDialog::AccountListDialog(QWidget *parent)
- : QDialog(parent), ui(new Ui::AccountListDialog)
+AccountListPage::AccountListPage(QWidget *parent)
+ : QWidget(parent), ui(new Ui::AccountListPage)
{
ui->setupUi(this);
+ ui->tabWidget->tabBar()->hide();
m_accounts = MMC->accounts();
@@ -58,23 +59,23 @@ AccountListDialog::AccountListDialog(QWidget *parent)
updateButtonStates();
}
-AccountListDialog::~AccountListDialog()
+AccountListPage::~AccountListPage()
{
delete ui;
}
-void AccountListDialog::listChanged()
+void AccountListPage::listChanged()
{
updateButtonStates();
}
-void AccountListDialog::on_addAccountBtn_clicked()
+void AccountListPage::on_addAccountBtn_clicked()
{
addAccount(tr("Please enter your Mojang or Minecraft account username and password to add "
"your account."));
}
-void AccountListDialog::on_rmAccountBtn_clicked()
+void AccountListPage::on_rmAccountBtn_clicked()
{
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
if (selection.size() > 0)
@@ -84,7 +85,7 @@ void AccountListDialog::on_rmAccountBtn_clicked()
}
}
-void AccountListDialog::on_setDefaultBtn_clicked()
+void AccountListPage::on_setDefaultBtn_clicked()
{
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
if (selection.size() > 0)
@@ -96,17 +97,12 @@ void AccountListDialog::on_setDefaultBtn_clicked()
}
}
-void AccountListDialog::on_noDefaultBtn_clicked()
+void AccountListPage::on_noDefaultBtn_clicked()
{
m_accounts->setActiveAccount("");
}
-void AccountListDialog::on_closeBtnBox_rejected()
-{
- close();
-}
-
-void AccountListDialog::updateButtonStates()
+void AccountListPage::updateButtonStates()
{
// If there is no selection, disable buttons that require something selected.
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
@@ -117,7 +113,7 @@ void AccountListDialog::updateButtonStates()
ui->noDefaultBtn->setDown(m_accounts->activeAccount().get() == nullptr);
}
-void AccountListDialog::addAccount(const QString &errMsg)
+void AccountListPage::addAccount(const QString &errMsg)
{
// TODO: The login dialog isn't quite done yet
MojangAccountPtr account = LoginDialog::newAccount(this, errMsg);
diff --git a/gui/dialogs/AccountListDialog.h b/gui/pages/global/AccountListPage.h
index fe0c8773..fd2c96e3 100644
--- a/gui/dialogs/AccountListDialog.h
+++ b/gui/pages/global/AccountListPage.h
@@ -16,24 +16,42 @@
#pragma once
#include <QDialog>
-
#include <memory>
+#include "gui/pages/BasePage.h"
+
#include "logic/auth/MojangAccountList.h"
namespace Ui
{
-class AccountListDialog;
+class AccountListPage;
}
class AuthenticateTask;
-class AccountListDialog : public QDialog
+class AccountListPage : public QWidget, public BasePage
{
Q_OBJECT
public:
- explicit AccountListDialog(QWidget *parent = 0);
- ~AccountListDialog();
+ explicit AccountListPage(QWidget *parent = 0);
+ ~AccountListPage();
+
+ QString displayName() const override
+ {
+ return tr("Accounts");
+ }
+ QIcon icon() const override
+ {
+ return QIcon::fromTheme("noaccount");
+ }
+ QString id() const override
+ {
+ return "accounts";
+ }
+ QString helpPage() const override
+ {
+ return "Accounts";
+ }
public
slots:
@@ -45,9 +63,6 @@ slots:
void on_noDefaultBtn_clicked();
- // This will be sent when the "close" button is clicked.
- void on_closeBtnBox_rejected();
-
void listChanged();
//! Updates the states of the dialog's buttons.
@@ -61,5 +76,5 @@ slots:
void addAccount(const QString& errMsg="");
private:
- Ui::AccountListDialog *ui;
+ Ui::AccountListPage *ui;
};
diff --git a/gui/pages/global/AccountListPage.ui b/gui/pages/global/AccountListPage.ui
new file mode 100644
index 00000000..8ad78cf4
--- /dev/null
+++ b/gui/pages/global/AccountListPage.ui
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AccountListPage</class>
+ <widget class="QWidget" name="AccountListPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>694</width>
+ <height>609</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Manage Accounts</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="welcomeLabel">
+ <property name="text">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Welcome! If you're new here, you can click the &amp;quot;Add&amp;quot; button to add your Mojang or Minecraft account.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QTreeView" name="listView"/>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="manageAcctsBtnBox">
+ <item>
+ <widget class="QPushButton" name="addAccountBtn">
+ <property name="text">
+ <string>&amp;Add</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="rmAccountBtn">
+ <property name="text">
+ <string>&amp;Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="buttonSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setDefaultBtn">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set the currently selected account as the active account. The active account is the account that is used to log in (unless it is overridden in an instance-specific setting).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>&amp;Set Default</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="noDefaultBtn">
+ <property name="toolTip">
+ <string>Set no default account. This will cause MultiMC to prompt you to select an account every time you launch an instance that doesn't have its own default set.</string>
+ </property>
+ <property name="text">
+ <string>&amp;No Default</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/gui/pages/global/ExternalToolsPage.cpp b/gui/pages/global/ExternalToolsPage.cpp
new file mode 100644
index 00000000..417a13e3
--- /dev/null
+++ b/gui/pages/global/ExternalToolsPage.cpp
@@ -0,0 +1,238 @@
+/* Copyright 2014 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ExternalToolsPage.h"
+#include "ui_ExternalToolsPage.h"
+
+#include <QMessageBox>
+#include <QFileDialog>
+#include <QStandardPaths>
+
+#include <pathutils.h>
+
+#include "logic/settings/SettingsObject.h"
+#include "logic/tools/BaseProfiler.h"
+#include "MultiMC.h"
+
+ExternalToolsPage::ExternalToolsPage(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::ExternalToolsPage)
+{
+ ui->setupUi(this);
+ ui->tabWidget->tabBar()->hide();
+
+ #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
+ ui->jsonEditorTextBox->setClearButtonEnabled(true);
+ #endif
+
+ ui->mceditLink->setOpenExternalLinks(true);
+ ui->jvisualvmLink->setOpenExternalLinks(true);
+ ui->jprofilerLink->setOpenExternalLinks(true);
+ loadSettings();
+}
+
+ExternalToolsPage::~ExternalToolsPage()
+{
+ delete ui;
+}
+
+void ExternalToolsPage::loadSettings()
+{
+ auto s = MMC->settings();
+ ui->jprofilerPathEdit->setText(s->get("JProfilerPath").toString());
+ ui->jvisualvmPathEdit->setText(s->get("JVisualVMPath").toString());
+ ui->mceditPathEdit->setText(s->get("MCEditPath").toString());
+
+ // Editors
+ ui->jsonEditorTextBox->setText(s->get("JsonEditor").toString());
+}
+void ExternalToolsPage::applySettings()
+{
+ auto s = MMC->settings();
+ s->set("JProfilerPath", ui->jprofilerPathEdit->text());
+ s->set("JVisualVMPath", ui->jvisualvmPathEdit->text());
+ s->set("MCEditPath", ui->mceditPathEdit->text());
+
+ // Editors
+ QString jsonEditor = ui->jsonEditorTextBox->text();
+ if (!jsonEditor.isEmpty() &&
+ (!QFileInfo(jsonEditor).exists() || !QFileInfo(jsonEditor).isExecutable()))
+ {
+ QString found = QStandardPaths::findExecutable(jsonEditor);
+ if (!found.isEmpty())
+ {
+ jsonEditor = found;
+ }
+ }
+ s->set("JsonEditor", jsonEditor);
+}
+
+void ExternalToolsPage::on_jprofilerPathBtn_clicked()
+{
+ QString raw_dir = ui->jprofilerPathEdit->text();
+ QString error;
+ do
+ {
+ raw_dir = QFileDialog::getExistingDirectory(this, tr("JProfiler 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 ExternalToolsPage::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 ExternalToolsPage::on_jvisualvmPathBtn_clicked()
+{
+ QString raw_dir = ui->jvisualvmPathEdit->text();
+ QString error;
+ do
+ {
+ raw_dir = QFileDialog::getOpenFileName(this, tr("JVisualVM Executable"), raw_dir);
+ if (raw_dir.isEmpty())
+ {
+ break;
+ }
+ QString cooked_dir = 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 ExternalToolsPage::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 ExternalToolsPage::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 ExternalToolsPage::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"));
+ }
+}
+
+void ExternalToolsPage::on_jsonEditorBrowseBtn_clicked()
+{
+ QString raw_file = QFileDialog::getOpenFileName(
+ this, tr("JSON Editor"),
+ ui->jsonEditorTextBox->text().isEmpty()
+#if defined(Q_OS_LINUX)
+ ? QString("/usr/bin")
+#else
+ ? QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).first()
+#endif
+ : ui->jsonEditorTextBox->text());
+ QString cooked_file = NormalizePath(raw_file);
+
+ if (cooked_file.isEmpty())
+ {
+ return;
+ }
+
+ // it has to exist and be an executable
+ if (QFileInfo(cooked_file).exists() && QFileInfo(cooked_file).isExecutable())
+ {
+ ui->jsonEditorTextBox->setText(cooked_file);
+ }
+ else
+ {
+ QMessageBox::warning(this, tr("Invalid"),
+ tr("The file chosen does not seem to be an executable"));
+ }
+}
+
+bool ExternalToolsPage::apply()
+{
+ applySettings();
+ return true;
+}
diff --git a/gui/pages/global/ExternalToolsPage.h b/gui/pages/global/ExternalToolsPage.h
new file mode 100644
index 00000000..027e164e
--- /dev/null
+++ b/gui/pages/global/ExternalToolsPage.h
@@ -0,0 +1,68 @@
+/* Copyright 2014 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <QWidget>
+
+#include "gui/pages/BasePage.h"
+
+namespace Ui {
+class ExternalToolsPage;
+}
+
+class ExternalToolsPage : public QWidget, public BasePage
+{
+ Q_OBJECT
+
+public:
+ explicit ExternalToolsPage(QWidget *parent = 0);
+ ~ExternalToolsPage();
+
+ QString displayName() const override
+ {
+ return tr("External Tools");
+ }
+ QIcon icon() const override
+ {
+ return QIcon::fromTheme("plugin-blue");
+ }
+ QString id() const override
+ {
+ return "external-tools";
+ }
+ QString helpPage() const override
+ {
+ return "External-tools";
+ }
+ virtual bool apply();
+
+private:
+ void loadSettings();
+ void applySettings();
+
+private:
+ Ui::ExternalToolsPage *ui;
+
+private
+slots:
+ void on_jprofilerPathBtn_clicked();
+ void on_jprofilerCheckBtn_clicked();
+ void on_jvisualvmPathBtn_clicked();
+ void on_jvisualvmCheckBtn_clicked();
+ void on_mceditPathBtn_clicked();
+ void on_mceditCheckBtn_clicked();
+ void on_jsonEditorBrowseBtn_clicked();
+};
diff --git a/gui/pages/global/ExternalToolsPage.ui b/gui/pages/global/ExternalToolsPage.ui
new file mode 100644
index 00000000..ba1b6f01
--- /dev/null
+++ b/gui/pages/global/ExternalToolsPage.ui
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ExternalToolsPage</class>
+ <widget class="QWidget" name="ExternalToolsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>673</width>
+ <height>751</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://www.ej-technologies.com/products/jprofiler/overview.html&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.ej-technologies.com/products/jprofiler/overview.html&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://visualvm.java.net/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://visualvm.java.net/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://www.mcedit.net/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.mcedit.net/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="editorsBox">
+ <property name="title">
+ <string>External Editors (leave empty for system default)</string>
+ </property>
+ <layout class="QGridLayout" name="foldersBoxLayout_2">
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="jsonEditorTextBox"/>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="labelJsonEditor">
+ <property name="text">
+ <string>Text Editor:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QToolButton" name="jsonEditorBrowseBtn">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>216</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/gui/pages/global/JavaPage.cpp b/gui/pages/global/JavaPage.cpp
new file mode 100644
index 00000000..86451411
--- /dev/null
+++ b/gui/pages/global/JavaPage.cpp
@@ -0,0 +1,146 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "JavaPage.h"
+#include "ui_JavaPage.h"
+
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QDir>
+
+#include <pathutils.h>
+
+#include "logic/NagUtils.h"
+
+#include "gui/Platform.h"
+#include "gui/dialogs/VersionSelectDialog.h"
+#include <gui/ColumnResizer.h>
+
+#include "logic/java/JavaUtils.h"
+#include "logic/java/JavaVersionList.h"
+#include "logic/java/JavaChecker.h"
+
+#include "logic/settings/SettingsObject.h"
+#include "MultiMC.h"
+
+JavaPage::JavaPage(QWidget *parent) : QWidget(parent), ui(new Ui::JavaPage)
+{
+ ui->setupUi(this);
+ ui->tabWidget->tabBar()->hide();
+
+ auto resizer = new ColumnResizer(this);
+ resizer->addWidgetsFromLayout(ui->javaSettingsGroupBox->layout(), 0);
+ resizer->addWidgetsFromLayout(ui->customCommandsGroupBox->layout(), 0);
+
+ loadSettings();
+}
+
+JavaPage::~JavaPage()
+{
+ delete ui;
+}
+
+bool JavaPage::apply()
+{
+ applySettings();
+ return true;
+}
+
+void JavaPage::applySettings()
+{
+ auto s = MMC->settings();
+ // Memory
+ s->set("MinMemAlloc", ui->minMemSpinBox->value());
+ s->set("MaxMemAlloc", ui->maxMemSpinBox->value());
+ s->set("PermGen", ui->permGenSpinBox->value());
+
+ // Java Settings
+ s->set("JavaPath", ui->javaPathTextBox->text());
+ s->set("JvmArgs", ui->jvmArgsTextBox->text());
+ NagUtils::checkJVMArgs(s->get("JvmArgs").toString(), this->parentWidget());
+
+ // Custom Commands
+ s->set("PreLaunchCommand", ui->preLaunchCmdTextBox->text());
+ s->set("PostExitCommand", ui->postExitCmdTextBox->text());
+}
+void JavaPage::loadSettings()
+{
+ auto s = MMC->settings();
+ // Memory
+ ui->minMemSpinBox->setValue(s->get("MinMemAlloc").toInt());
+ ui->maxMemSpinBox->setValue(s->get("MaxMemAlloc").toInt());
+ ui->permGenSpinBox->setValue(s->get("PermGen").toInt());
+
+ // Java Settings
+ ui->javaPathTextBox->setText(s->get("JavaPath").toString());
+ ui->jvmArgsTextBox->setText(s->get("JvmArgs").toString());
+
+ // Custom Commands
+ ui->preLaunchCmdTextBox->setText(s->get("PreLaunchCommand").toString());
+ ui->postExitCmdTextBox->setText(s->get("PostExitCommand").toString());
+}
+
+void JavaPage::on_javaDetectBtn_clicked()
+{
+ JavaVersionPtr java;
+
+ VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true);
+ vselect.setResizeOn(2);
+ vselect.exec();
+
+ if (vselect.result() == QDialog::Accepted && vselect.selectedVersion())
+ {
+ java = std::dynamic_pointer_cast<JavaVersion>(vselect.selectedVersion());
+ ui->javaPathTextBox->setText(java->path);
+ }
+}
+void JavaPage::on_javaBrowseBtn_clicked()
+{
+ QString dir = QFileDialog::getOpenFileName(this, tr("Find Java executable"));
+ if (!dir.isNull())
+ {
+ ui->javaPathTextBox->setText(dir);
+ }
+}
+void JavaPage::on_javaTestBtn_clicked()
+{
+ checker.reset(new JavaChecker());
+ connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
+ SLOT(checkFinished(JavaCheckResult)));
+ checker->path = ui->javaPathTextBox->text();
+ checker->performCheck();
+}
+
+void JavaPage::checkFinished(JavaCheckResult result)
+{
+ if (result.valid)
+ {
+ QString text;
+ text += "Java test succeeded!\n";
+ if (result.is_64bit)
+ text += "Using 64bit java.\n";
+ text += "\n";
+ text += "Platform reported: " + result.realPlatform + "\n";
+ text += "Java version reported: " + result.javaVersion;
+ QMessageBox::information(this, tr("Java test success"), text);
+ }
+ else
+ {
+ QMessageBox::warning(
+ this, tr("Java test failure"),
+ tr("The specified java binary didn't work. You should use the auto-detect feature, "
+ "or set the path to the java executable."));
+ }
+}
diff --git a/gui/pages/global/JavaPage.h b/gui/pages/global/JavaPage.h
new file mode 100644
index 00000000..d0228bd2
--- /dev/null
+++ b/gui/pages/global/JavaPage.h
@@ -0,0 +1,72 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+#include <QDialog>
+
+#include "logic/java/JavaChecker.h"
+#include "gui/pages/BasePage.h"
+
+class SettingsObject;
+
+namespace Ui
+{
+class JavaPage;
+}
+
+class JavaPage : public QWidget, public BasePage
+{
+ Q_OBJECT
+
+public:
+ explicit JavaPage(QWidget *parent = 0);
+ ~JavaPage();
+
+ QString displayName() const override
+ {
+ return tr("Java");
+ }
+ QIcon icon() const override
+ {
+ return QIcon::fromTheme("java");
+ }
+ QString id() const override
+ {
+ return "java-settings";
+ }
+ QString helpPage() const override
+ {
+ return "Java-settings";
+ }
+ bool apply() override;
+
+private:
+ void applySettings();
+ void loadSettings();
+
+private
+slots:
+ void on_javaDetectBtn_clicked();
+ void on_javaTestBtn_clicked();
+ void on_javaBrowseBtn_clicked();
+
+ void checkFinished(JavaCheckResult result);
+
+private:
+ Ui::JavaPage *ui;
+ std::shared_ptr<JavaChecker> checker;
+};
diff --git a/gui/pages/global/JavaPage.ui b/gui/pages/global/JavaPage.ui
new file mode 100644
index 00000000..6ae41a49
--- /dev/null
+++ b/gui/pages/global/JavaPage.ui
@@ -0,0 +1,303 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>JavaPage</class>
+ <widget class="QWidget" name="JavaPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>545</width>
+ <height>609</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Settings</string>
+ </property>
+ <property name="windowIcon">
+ <iconset>
+ <normaloff>:/icons/toolbar/settings</normaloff>:/icons/toolbar/settings</iconset>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QGroupBox" name="memoryGroupBox">
+ <property name="title">
+ <string>Memory</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="maxMemSpinBox">
+ <property name="toolTip">
+ <string>The maximum amount of memory Minecraft is allowed to use.</string>
+ </property>
+ <property name="suffix">
+ <string> MB</string>
+ </property>
+ <property name="minimum">
+ <number>512</number>
+ </property>
+ <property name="maximum">
+ <number>65536</number>
+ </property>
+ <property name="singleStep">
+ <number>128</number>
+ </property>
+ <property name="value">
+ <number>1024</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="labelMinMem">
+ <property name="text">
+ <string>Minimum memory allocation:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="labelMaxMem">
+ <property name="text">
+ <string>Maximum memory allocation:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="minMemSpinBox">
+ <property name="toolTip">
+ <string>The amount of memory Minecraft is started with.</string>
+ </property>
+ <property name="suffix">
+ <string> MB</string>
+ </property>
+ <property name="minimum">
+ <number>256</number>
+ </property>
+ <property name="maximum">
+ <number>65536</number>
+ </property>
+ <property name="singleStep">
+ <number>128</number>
+ </property>
+ <property name="value">
+ <number>256</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="labelPermGen">
+ <property name="text">
+ <string>PermGen:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QSpinBox" name="permGenSpinBox">
+ <property name="toolTip">
+ <string>The amount of memory available to store loaded Java classes.</string>
+ </property>
+ <property name="suffix">
+ <string> MB</string>
+ </property>
+ <property name="minimum">
+ <number>64</number>
+ </property>
+ <property name="maximum">
+ <number>999999999</number>
+ </property>
+ <property name="singleStep">
+ <number>8</number>
+ </property>
+ <property name="value">
+ <number>64</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="javaSettingsGroupBox">
+ <property name="title">
+ <string>Java Runtime</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <widget class="QLabel" name="labelJavaPath">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Java path:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="javaDetectBtn">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Auto-detect...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="javaTestBtn">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Test</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="labelJVMArgs">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>JVM arguments:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLineEdit" name="javaPathTextBox"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="javaBrowseBtn">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>28</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="1" colspan="2">
+ <widget class="QLineEdit" name="jvmArgsTextBox"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="customCommandsGroupBox">
+ <property name="title">
+ <string>Custom Commands</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="1" column="0">
+ <widget class="QLabel" name="labelPostExitCmd">
+ <property name="text">
+ <string>Post-exit command:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="labelPreLaunchCmd">
+ <property name="text">
+ <string>Pre-launch command:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="preLaunchCmdTextBox"/>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="postExitCmdTextBox"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelCustomCmdsDescription">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Pre-launch command runs before the instance launches and post-exit command runs after it exits. Both will be run in MultiMC's working directory with INST_ID, INST_DIR, and INST_NAME as environment variables.</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>minMemSpinBox</tabstop>
+ <tabstop>maxMemSpinBox</tabstop>
+ <tabstop>permGenSpinBox</tabstop>
+ <tabstop>javaPathTextBox</tabstop>
+ <tabstop>javaBrowseBtn</tabstop>
+ <tabstop>javaDetectBtn</tabstop>
+ <tabstop>javaTestBtn</tabstop>
+ <tabstop>jvmArgsTextBox</tabstop>
+ <tabstop>preLaunchCmdTextBox</tabstop>
+ <tabstop>postExitCmdTextBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/gui/pages/global/MinecraftPage.cpp b/gui/pages/global/MinecraftPage.cpp
new file mode 100644
index 00000000..0fe56fde
--- /dev/null
+++ b/gui/pages/global/MinecraftPage.cpp
@@ -0,0 +1,104 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MinecraftPage.h"
+#include "ui_MinecraftPage.h"
+
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QDir>
+
+#include <pathutils.h>
+
+#include "gui/Platform.h"
+#include "gui/dialogs/VersionSelectDialog.h"
+#include "gui/dialogs/CustomMessageBox.h"
+
+#include "logic/NagUtils.h"
+
+#include "logic/java/JavaUtils.h"
+#include "logic/java/JavaVersionList.h"
+#include "logic/java/JavaChecker.h"
+
+#include "logic/updater/UpdateChecker.h"
+
+#include "logic/tools/BaseProfiler.h"
+
+#include "logic/settings/SettingsObject.h"
+#include "MultiMC.h"
+
+MinecraftPage::MinecraftPage(QWidget *parent) : QWidget(parent), ui(new Ui::MinecraftPage)
+{
+ ui->setupUi(this);
+ ui->tabWidget->tabBar()->hide();
+ loadSettings();
+ updateCheckboxStuff();
+}
+
+MinecraftPage::~MinecraftPage()
+{
+ delete ui;
+}
+
+bool MinecraftPage::apply()
+{
+ applySettings();
+ return true;
+}
+
+void MinecraftPage::updateCheckboxStuff()
+{
+ ui->windowWidthSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
+ ui->windowHeightSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
+}
+
+void MinecraftPage::on_maximizedCheckBox_clicked(bool checked)
+{
+ Q_UNUSED(checked);
+ updateCheckboxStuff();
+}
+
+
+void MinecraftPage::applySettings()
+{
+ auto s = MMC->settings();
+ // Minecraft version updates
+ s->set("AutoUpdateMinecraftVersions", ui->autoupdateMinecraft->isChecked());
+
+ // Console
+ s->set("ShowConsole", ui->showConsoleCheck->isChecked());
+ s->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked());
+
+ // Window Size
+ s->set("LaunchMaximized", ui->maximizedCheckBox->isChecked());
+ s->set("MinecraftWinWidth", ui->windowWidthSpinBox->value());
+ s->set("MinecraftWinHeight", ui->windowHeightSpinBox->value());
+}
+
+void MinecraftPage::loadSettings()
+{
+ auto s = MMC->settings();
+ // Minecraft version updates
+ ui->autoupdateMinecraft->setChecked(s->get("AutoUpdateMinecraftVersions").toBool());
+
+ // Console
+ ui->showConsoleCheck->setChecked(s->get("ShowConsole").toBool());
+ ui->autoCloseConsoleCheck->setChecked(s->get("AutoCloseConsole").toBool());
+
+ // Window Size
+ ui->maximizedCheckBox->setChecked(s->get("LaunchMaximized").toBool());
+ ui->windowWidthSpinBox->setValue(s->get("MinecraftWinWidth").toInt());
+ ui->windowHeightSpinBox->setValue(s->get("MinecraftWinHeight").toInt());
+}
diff --git a/gui/pages/global/MinecraftPage.h b/gui/pages/global/MinecraftPage.h
new file mode 100644
index 00000000..90299020
--- /dev/null
+++ b/gui/pages/global/MinecraftPage.h
@@ -0,0 +1,69 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+#include <QDialog>
+
+#include "logic/java/JavaChecker.h"
+#include "gui/pages/BasePage.h"
+
+class SettingsObject;
+
+namespace Ui
+{
+class MinecraftPage;
+}
+
+class MinecraftPage : public QWidget, public BasePage
+{
+ Q_OBJECT
+
+public:
+ explicit MinecraftPage(QWidget *parent = 0);
+ ~MinecraftPage();
+
+ QString displayName() const override
+ {
+ return tr("Minecraft");
+ }
+ QIcon icon() const override
+ {
+ return QIcon::fromTheme("minecraft");
+ }
+ QString id() const override
+ {
+ return "minecraft-settings";
+ }
+ QString helpPage() const override
+ {
+ return "Minecraft-settings";
+ }
+ bool apply() override;
+
+private:
+ void updateCheckboxStuff();
+ void applySettings();
+ void loadSettings();
+
+private
+slots:
+ void on_maximizedCheckBox_clicked(bool checked);
+
+private:
+ Ui::MinecraftPage *ui;
+
+};
diff --git a/gui/pages/global/MinecraftPage.ui b/gui/pages/global/MinecraftPage.ui
new file mode 100644
index 00000000..e938d09d
--- /dev/null
+++ b/gui/pages/global/MinecraftPage.ui
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MinecraftPage</class>
+ <widget class="QWidget" name="MinecraftPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>545</width>
+ <height>609</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Settings</string>
+ </property>
+ <property name="windowIcon">
+ <iconset>
+ <normaloff>:/icons/toolbar/settings</normaloff>:/icons/toolbar/settings</iconset>
+ </property>
+ <layout class="QVBoxLayout" name="mainLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="tabShape">
+ <enum>QTabWidget::Rounded</enum>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="minecraftTab">
+ <attribute name="title">
+ <string>Minecraft</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QGroupBox" name="groupBox_5">
+ <property name="title">
+ <string>Minecraft Version Updates</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_14">
+ <item>
+ <widget class="QCheckBox" name="autoupdateMinecraft">
+ <property name="text">
+ <string>Automatically update to latest version revision</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="windowSizeGroupBox">
+ <property name="title">
+ <string>Window Size</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QCheckBox" name="maximizedCheckBox">
+ <property name="text">
+ <string>Start Minecraft maximized?</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayoutWindowSize">
+ <item row="1" column="0">
+ <widget class="QLabel" name="labelWindowHeight">
+ <property name="text">
+ <string>Window height:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="labelWindowWidth">
+ <property name="text">
+ <string>Window width:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="windowWidthSpinBox">
+ <property name="minimum">
+ <number>854</number>
+ </property>
+ <property name="maximum">
+ <number>65536</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>854</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="windowHeightSpinBox">
+ <property name="minimum">
+ <number>480</number>
+ </property>
+ <property name="maximum">
+ <number>65536</number>
+ </property>
+ <property name="value">
+ <number>480</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="consoleSettingsBox">
+ <property name="title">
+ <string>Console Settings</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="showConsoleCheck">
+ <property name="text">
+ <string>Show console while the game is running?</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="autoCloseConsoleCheck">
+ <property name="text">
+ <string>Automatically close console when the game quits?</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacerMinecraft">
+ <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>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>autoupdateMinecraft</tabstop>
+ <tabstop>maximizedCheckBox</tabstop>
+ <tabstop>windowWidthSpinBox</tabstop>
+ <tabstop>windowHeightSpinBox</tabstop>
+ <tabstop>showConsoleCheck</tabstop>
+ <tabstop>autoCloseConsoleCheck</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/gui/pages/global/MultiMCPage.cpp b/gui/pages/global/MultiMCPage.cpp
new file mode 100644
index 00000000..2d6eb7d5
--- /dev/null
+++ b/gui/pages/global/MultiMCPage.cpp
@@ -0,0 +1,340 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MultiMCPage.h"
+#include "ui_MultiMCPage.h"
+
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QDir>
+
+#include <pathutils.h>
+
+#include "gui/Platform.h"
+#include "gui/dialogs/VersionSelectDialog.h"
+#include "gui/dialogs/CustomMessageBox.h"
+#include <gui/ColumnResizer.h>
+
+#include "logic/NagUtils.h"
+
+#include "logic/java/JavaUtils.h"
+#include "logic/java/JavaVersionList.h"
+#include "logic/java/JavaChecker.h"
+
+#include "logic/updater/UpdateChecker.h"
+
+#include "logic/tools/BaseProfiler.h"
+
+#include "logic/settings/SettingsObject.h"
+#include "MultiMC.h"
+
+// FIXME: possibly move elsewhere
+enum InstSortMode
+{
+ // Sort alphabetically by name.
+ Sort_Name,
+ // Sort by which instance was launched most recently.
+ Sort_LastLaunch
+};
+
+MultiMCPage::MultiMCPage(QWidget *parent) : QWidget(parent), ui(new Ui::MultiMCPage)
+{
+ ui->setupUi(this);
+ ui->sortingModeGroup->setId(ui->sortByNameBtn, Sort_Name);
+ ui->sortingModeGroup->setId(ui->sortLastLaunchedBtn, Sort_LastLaunch);
+
+ auto resizer = new ColumnResizer(this);
+ resizer->addWidgetsFromLayout(ui->groupBox->layout(), 1);
+ resizer->addWidgetsFromLayout(ui->foldersBox->layout(), 1);
+
+ loadSettings();
+
+ QObject::connect(MMC->updateChecker().get(), &UpdateChecker::channelListLoaded, this,
+ &MultiMCPage::refreshUpdateChannelList);
+
+ if (MMC->updateChecker()->hasChannels())
+ {
+ refreshUpdateChannelList();
+ }
+ else
+ {
+ MMC->updateChecker()->updateChanList(false);
+ }
+}
+
+MultiMCPage::~MultiMCPage()
+{
+ delete ui;
+}
+
+bool MultiMCPage::apply()
+{
+ applySettings();
+ return true;
+}
+
+void MultiMCPage::on_ftbLauncherBrowseBtn_clicked()
+{
+ QString raw_dir = QFileDialog::getExistingDirectory(this, tr("FTB Launcher Directory"),
+ ui->ftbLauncherBox->text());
+ QString cooked_dir = NormalizePath(raw_dir);
+
+ // do not allow current dir - it's dirty. Do not allow dirs that don't exist
+ if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
+ {
+ ui->ftbLauncherBox->setText(cooked_dir);
+ }
+}
+void MultiMCPage::on_ftbBrowseBtn_clicked()
+{
+ 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
+ if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
+ {
+ ui->ftbBox->setText(cooked_dir);
+ }
+}
+
+void MultiMCPage::on_instDirBrowseBtn_clicked()
+{
+ QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Instance Directory"),
+ ui->instDirTextBox->text());
+ QString cooked_dir = NormalizePath(raw_dir);
+
+ // do not allow current dir - it's dirty. Do not allow dirs that don't exist
+ if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
+ {
+ ui->instDirTextBox->setText(cooked_dir);
+ }
+}
+void MultiMCPage::on_iconsDirBrowseBtn_clicked()
+{
+ QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Icons Directory"),
+ ui->iconsDirTextBox->text());
+ QString cooked_dir = NormalizePath(raw_dir);
+
+ // do not allow current dir - it's dirty. Do not allow dirs that don't exist
+ if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
+ {
+ ui->iconsDirTextBox->setText(cooked_dir);
+ }
+}
+void MultiMCPage::on_modsDirBrowseBtn_clicked()
+{
+ QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Mods Directory"),
+ ui->modsDirTextBox->text());
+ QString cooked_dir = NormalizePath(raw_dir);
+
+ // do not allow current dir - it's dirty. Do not allow dirs that don't exist
+ if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
+ {
+ ui->modsDirTextBox->setText(cooked_dir);
+ }
+}
+void MultiMCPage::on_lwjglDirBrowseBtn_clicked()
+{
+ QString raw_dir = QFileDialog::getExistingDirectory(this, tr("LWJGL Directory"),
+ ui->lwjglDirTextBox->text());
+ QString cooked_dir = NormalizePath(raw_dir);
+
+ // do not allow current dir - it's dirty. Do not allow dirs that don't exist
+ if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
+ {
+ ui->lwjglDirTextBox->setText(cooked_dir);
+ }
+}
+
+void MultiMCPage::refreshUpdateChannelList()
+{
+ // Stop listening for selection changes. It's going to change a lot while we update it and
+ // we don't need to update the
+ // description label constantly.
+ QObject::disconnect(ui->updateChannelComboBox, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(updateChannelSelectionChanged(int)));
+
+ QList<UpdateChecker::ChannelListEntry> channelList = MMC->updateChecker()->getChannelList();
+ ui->updateChannelComboBox->clear();
+ int selection = -1;
+ for (int i = 0; i < channelList.count(); i++)
+ {
+ UpdateChecker::ChannelListEntry entry = channelList.at(i);
+
+ // When it comes to selection, we'll rely on the indexes of a channel entry being the
+ // same in the
+ // combo box as it is in the update checker's channel list.
+ // This probably isn't very safe, but the channel list doesn't change often enough (or
+ // at all) for
+ // this to be a big deal. Hope it doesn't break...
+ ui->updateChannelComboBox->addItem(entry.name);
+
+ // If the update channel we just added was the selected one, set the current index in
+ // the combo box to it.
+ if (entry.id == m_currentUpdateChannel)
+ {
+ 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)));
+ refreshUpdateChannelDesc();
+
+ // Now that we've updated the channel list, we can enable the combo box.
+ // It starts off disabled so that if the channel list hasn't been loaded, it will be
+ // disabled.
+ ui->updateChannelComboBox->setEnabled(true);
+}
+
+void MultiMCPage::updateChannelSelectionChanged(int index)
+{
+ refreshUpdateChannelDesc();
+}
+
+void MultiMCPage::refreshUpdateChannelDesc()
+{
+ // Get the channel list.
+ QList<UpdateChecker::ChannelListEntry> channelList = MMC->updateChecker()->getChannelList();
+ int selectedIndex = ui->updateChannelComboBox->currentIndex();
+ if (selectedIndex < 0)
+ {
+ return;
+ }
+ if (selectedIndex < channelList.count())
+ {
+ // Find the channel list entry with the given index.
+ UpdateChecker::ChannelListEntry selected = channelList.at(selectedIndex);
+
+ // Set the description text.
+ ui->updateChannelDescLabel->setText(selected.description);
+
+ // Set the currently selected channel ID.
+ m_currentUpdateChannel = selected.id;
+ }
+}
+
+void MultiMCPage::applySettings()
+{
+ auto s = MMC->settings();
+ // Language
+ s->set("Language",
+ ui->languageBox->itemData(ui->languageBox->currentIndex()).toLocale().bcp47Name());
+
+ if (ui->resetNotificationsBtn->isChecked())
+ {
+ s->set("ShownNotifications", QString());
+ }
+
+ // Updates
+ s->set("AutoUpdate", ui->autoUpdateCheckBox->isChecked());
+ s->set("UpdateChannel", m_currentUpdateChannel);
+ //FIXME: make generic
+ switch (ui->themeComboBox->currentIndex())
+ {
+ case 1:
+ s->set("IconTheme", "pe_dark");
+ break;
+ case 2:
+ s->set("IconTheme", "pe_light");
+ break;
+ case 0:
+ default:
+ s->set("IconTheme", "multimc");
+ break;
+ }
+ // FTB
+ s->set("TrackFTBInstances", ui->trackFtbBox->isChecked());
+ s->set("FTBLauncherRoot", ui->ftbLauncherBox->text());
+ s->set("FTBRoot", ui->ftbBox->text());
+
+ // Folders
+ // TODO: Offer to move instances to new instance folder.
+ s->set("InstanceDir", ui->instDirTextBox->text());
+ s->set("CentralModsDir", ui->modsDirTextBox->text());
+ s->set("LWJGLDir", ui->lwjglDirTextBox->text());
+ s->set("IconsDir", ui->iconsDirTextBox->text());
+
+ auto sortMode = (InstSortMode)ui->sortingModeGroup->checkedId();
+ switch (sortMode)
+ {
+ case Sort_LastLaunch:
+ s->set("InstSortMode", "LastLaunch");
+ break;
+ case Sort_Name:
+ default:
+ s->set("InstSortMode", "Name");
+ break;
+ }
+}
+void MultiMCPage::loadSettings()
+{
+ auto s = MMC->settings();
+ // Language
+ ui->languageBox->clear();
+ ui->languageBox->addItem(tr("English"), QLocale(QLocale::English));
+ foreach(const QString & lang, QDir(MMC->staticData() + "/translations")
+ .entryList(QStringList() << "*.qm", QDir::Files))
+ {
+ QLocale locale(lang.section(QRegExp("[_\\.]"), 1));
+ ui->languageBox->addItem(QLocale::languageToString(locale.language()), locale);
+ }
+ ui->languageBox->setCurrentIndex(
+ ui->languageBox->findData(QLocale(s->get("Language").toString())));
+
+ // Updates
+ ui->autoUpdateCheckBox->setChecked(s->get("AutoUpdate").toBool());
+ m_currentUpdateChannel = s->get("UpdateChannel").toString();
+ //FIXME: make generic
+ auto theme = s->get("IconTheme").toString();
+ if (theme == "pe_dark")
+ {
+ ui->themeComboBox->setCurrentIndex(1);
+ }
+ else if (theme == "pe_light")
+ {
+ ui->themeComboBox->setCurrentIndex(2);
+ }
+ else
+ {
+ ui->themeComboBox->setCurrentIndex(0);
+ }
+ // FTB
+ ui->trackFtbBox->setChecked(s->get("TrackFTBInstances").toBool());
+ ui->ftbLauncherBox->setText(s->get("FTBLauncherRoot").toString());
+ ui->ftbBox->setText(s->get("FTBRoot").toString());
+
+ // Folders
+ ui->instDirTextBox->setText(s->get("InstanceDir").toString());
+ ui->modsDirTextBox->setText(s->get("CentralModsDir").toString());
+ ui->lwjglDirTextBox->setText(s->get("LWJGLDir").toString());
+ ui->iconsDirTextBox->setText(s->get("IconsDir").toString());
+
+ QString sortMode = s->get("InstSortMode").toString();
+
+ if (sortMode == "LastLaunch")
+ {
+ ui->sortLastLaunchedBtn->setChecked(true);
+ }
+ else
+ {
+ ui->sortByNameBtn->setChecked(true);
+ }
+}
diff --git a/gui/dialogs/SettingsDialog.h b/gui/pages/global/MultiMCPage.h
index c65e9fb5..b465355f 100644
--- a/gui/dialogs/SettingsDialog.h
+++ b/gui/pages/global/MultiMCPage.h
@@ -19,69 +19,55 @@
#include <QDialog>
#include "logic/java/JavaChecker.h"
+#include "gui/pages/BasePage.h"
class SettingsObject;
namespace Ui
{
-class SettingsDialog;
+class MultiMCPage;
}
-class SettingsDialog : public QDialog
+class MultiMCPage : public QWidget, public BasePage
{
Q_OBJECT
public:
- explicit SettingsDialog(QWidget *parent = 0);
- ~SettingsDialog();
+ explicit MultiMCPage(QWidget *parent = 0);
+ ~MultiMCPage();
+
+ QString displayName() const override
+ {
+ return tr("MultiMC");
+ }
+ QIcon icon() const override
+ {
+ return QIcon::fromTheme("multimc");
+ }
+ QString id() const override
+ {
+ return "multimc-settings";
+ }
+ QString helpPage() const override
+ {
+ return "MultiMC-settings";
+ }
+ bool apply() override;
- void updateCheckboxStuff();
-
- void applySettings(SettingsObject *s);
- void loadSettings(SettingsObject *s);
-
-protected:
- virtual void showEvent(QShowEvent *ev);
- virtual void closeEvent(QCloseEvent *ev);
+private:
+ void applySettings();
+ void loadSettings();
private
slots:
void on_ftbLauncherBrowseBtn_clicked();
-
void on_ftbBrowseBtn_clicked();
void on_instDirBrowseBtn_clicked();
-
void on_modsDirBrowseBtn_clicked();
-
void on_lwjglDirBrowseBtn_clicked();
-
-
- void on_jsonEditorBrowseBtn_clicked();
-
void on_iconsDirBrowseBtn_clicked();
- void on_maximizedCheckBox_clicked(bool checked);
-
- void on_buttonBox_accepted();
-
- void on_buttonBox_rejected();
-
- void on_javaDetectBtn_clicked();
-
- void on_javaTestBtn_clicked();
-
- void on_javaBrowseBtn_clicked();
-
- 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.
*/
@@ -93,11 +79,9 @@ slots:
void refreshUpdateChannelDesc();
void updateChannelSelectionChanged(int index);
- void proxyChanged(int);
private:
- Ui::SettingsDialog *ui;
- std::shared_ptr<JavaChecker> checker;
+ Ui::MultiMCPage *ui;
/*!
* Stores the currently selected update channel.
diff --git a/gui/pages/global/MultiMCPage.ui b/gui/pages/global/MultiMCPage.ui
new file mode 100644
index 00000000..f456ebc1
--- /dev/null
+++ b/gui/pages/global/MultiMCPage.ui
@@ -0,0 +1,399 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MultiMCPage</class>
+ <widget class="QWidget" name="MultiMCPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>545</width>
+ <height>609</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Settings</string>
+ </property>
+ <property name="windowIcon">
+ <iconset>
+ <normaloff>:/icons/toolbar/settings</normaloff>:/icons/toolbar/settings</iconset>
+ </property>
+ <layout class="QVBoxLayout" name="mainLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="tabShape">
+ <enum>QTabWidget::Rounded</enum>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="featuresTab">
+ <attribute name="title">
+ <string>Features</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_9">
+ <item>
+ <widget class="QGroupBox" name="updateSettingsBox">
+ <property name="title">
+ <string>Update Settings</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_7">
+ <item>
+ <widget class="QCheckBox" name="autoUpdateCheckBox">
+ <property name="text">
+ <string>Check for updates when MultiMC starts?</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="updateChannelLabel">
+ <property name="text">
+ <string>Update Channel:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="updateChannelComboBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="updateChannelDescLabel">
+ <property name="text">
+ <string>No channel selected.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>FTB</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="2" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Launcher:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="ftbLauncherBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLineEdit" name="ftbBox"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Files:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QToolButton" name="ftbBrowseBtn">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QToolButton" name="ftbLauncherBrowseBtn">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::TabFocus</enum>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="3">
+ <widget class="QCheckBox" name="trackFtbBox">
+ <property name="text">
+ <string>Track FTB instances</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="foldersBox">
+ <property name="title">
+ <string>Folders</string>
+ </property>
+ <layout class="QGridLayout" name="foldersBoxLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="labelInstDir">
+ <property name="text">
+ <string>Instances:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="instDirTextBox"/>
+ </item>
+ <item row="0" column="2">
+ <widget class="QToolButton" name="instDirBrowseBtn">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="labelModsDir">
+ <property name="text">
+ <string>Mods:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="modsDirTextBox"/>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="lwjglDirTextBox"/>
+ </item>
+ <item row="1" column="2">
+ <widget class="QToolButton" name="modsDirBrowseBtn">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="labelLWJGLDir">
+ <property name="text">
+ <string>LWJGL:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QToolButton" name="lwjglDirBrowseBtn">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLineEdit" name="iconsDirTextBox"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="labelIconsDir">
+ <property name="text">
+ <string>Icons:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QToolButton" name="iconsDirBrowseBtn">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <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 class="QWidget" name="generalTab">
+ <attribute name="title">
+ <string>User Interface</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="title">
+ <string>MultiMC notifications</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <widget class="QPushButton" name="resetNotificationsBtn">
+ <property name="text">
+ <string>Reset hidden notifications</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="sortingModeBox">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="title">
+ <string>Instance view sorting mode</string>
+ </property>
+ <layout class="QHBoxLayout" name="sortingModeBoxLayout">
+ <item>
+ <widget class="QRadioButton" name="sortLastLaunchedBtn">
+ <property name="text">
+ <string>By last launched</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">sortingModeGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="sortByNameBtn">
+ <property name="text">
+ <string>By name</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">sortingModeGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Language (needs restart):</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QComboBox" name="languageBox"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="themeBox">
+ <property name="title">
+ <string>Icon Theme (needs restart, work in progress)</string>
+ </property>
+ <layout class="QHBoxLayout" name="themeBoxLayout">
+ <item>
+ <widget class="QComboBox" name="themeComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string>Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Simple</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Simple (Light Icons)</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="generalTabSpacer">
+ <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>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>autoUpdateCheckBox</tabstop>
+ <tabstop>updateChannelComboBox</tabstop>
+ <tabstop>trackFtbBox</tabstop>
+ <tabstop>ftbLauncherBox</tabstop>
+ <tabstop>ftbLauncherBrowseBtn</tabstop>
+ <tabstop>ftbBox</tabstop>
+ <tabstop>ftbBrowseBtn</tabstop>
+ <tabstop>instDirTextBox</tabstop>
+ <tabstop>instDirBrowseBtn</tabstop>
+ <tabstop>modsDirTextBox</tabstop>
+ <tabstop>modsDirBrowseBtn</tabstop>
+ <tabstop>lwjglDirTextBox</tabstop>
+ <tabstop>lwjglDirBrowseBtn</tabstop>
+ <tabstop>iconsDirTextBox</tabstop>
+ <tabstop>iconsDirBrowseBtn</tabstop>
+ <tabstop>resetNotificationsBtn</tabstop>
+ <tabstop>sortLastLaunchedBtn</tabstop>
+ <tabstop>sortByNameBtn</tabstop>
+ <tabstop>languageBox</tabstop>
+ <tabstop>themeComboBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+ <buttongroups>
+ <buttongroup name="sortingModeGroup"/>
+ </buttongroups>
+</ui>
diff --git a/gui/pages/global/ProxyPage.cpp b/gui/pages/global/ProxyPage.cpp
new file mode 100644
index 00000000..5578fbb7
--- /dev/null
+++ b/gui/pages/global/ProxyPage.cpp
@@ -0,0 +1,95 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ProxyPage.h"
+#include "ui_ProxyPage.h"
+
+#include "logic/settings/SettingsObject.h"
+#include "MultiMC.h"
+
+ProxyPage::ProxyPage(QWidget *parent) : QWidget(parent), ui(new Ui::ProxyPage)
+{
+ ui->setupUi(this);
+ ui->tabWidget->tabBar()->hide();
+ loadSettings();
+ updateCheckboxStuff();
+
+ connect(ui->proxyGroup, SIGNAL(buttonClicked(int)), SLOT(proxyChanged(int)));
+}
+
+ProxyPage::~ProxyPage()
+{
+ delete ui;
+}
+
+bool ProxyPage::apply()
+{
+ applySettings();
+ return true;
+}
+
+void ProxyPage::updateCheckboxStuff()
+{
+ ui->proxyAddrBox->setEnabled(!ui->proxyNoneBtn->isChecked() &&
+ !ui->proxyDefaultBtn->isChecked());
+ ui->proxyAuthBox->setEnabled(!ui->proxyNoneBtn->isChecked() &&
+ !ui->proxyDefaultBtn->isChecked());
+}
+
+void ProxyPage::proxyChanged(int)
+{
+ updateCheckboxStuff();
+}
+
+void ProxyPage::applySettings()
+{
+ auto s = MMC->settings();
+
+ // Proxy
+ QString proxyType = "None";
+ if (ui->proxyDefaultBtn->isChecked())
+ proxyType = "Default";
+ else if (ui->proxyNoneBtn->isChecked())
+ proxyType = "None";
+ else if (ui->proxySOCKS5Btn->isChecked())
+ proxyType = "SOCKS5";
+ else if (ui->proxyHTTPBtn->isChecked())
+ proxyType = "HTTP";
+
+ s->set("ProxyType", proxyType);
+ s->set("ProxyAddr", ui->proxyAddrEdit->text());
+ s->set("ProxyPort", ui->proxyPortEdit->value());
+ s->set("ProxyUser", ui->proxyUserEdit->text());
+ s->set("ProxyPass", ui->proxyPassEdit->text());
+}
+void ProxyPage::loadSettings()
+{
+ auto s = MMC->settings();
+ // Proxy
+ QString proxyType = s->get("ProxyType").toString();
+ if (proxyType == "Default")
+ ui->proxyDefaultBtn->setChecked(true);
+ else if (proxyType == "None")
+ ui->proxyNoneBtn->setChecked(true);
+ else if (proxyType == "SOCKS5")
+ ui->proxySOCKS5Btn->setChecked(true);
+ else if (proxyType == "HTTP")
+ ui->proxyHTTPBtn->setChecked(true);
+
+ ui->proxyAddrEdit->setText(s->get("ProxyAddr").toString());
+ ui->proxyPortEdit->setValue(s->get("ProxyPort").value<qint16>());
+ ui->proxyUserEdit->setText(s->get("ProxyUser").toString());
+ ui->proxyPassEdit->setText(s->get("ProxyPass").toString());
+}
diff --git a/gui/pages/global/ProxyPage.h b/gui/pages/global/ProxyPage.h
new file mode 100644
index 00000000..700a3af0
--- /dev/null
+++ b/gui/pages/global/ProxyPage.h
@@ -0,0 +1,66 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+#include <QDialog>
+
+#include "logic/java/JavaChecker.h"
+#include "gui/pages/BasePage.h"
+
+namespace Ui
+{
+class ProxyPage;
+}
+
+class ProxyPage : public QWidget, public BasePage
+{
+ Q_OBJECT
+
+public:
+ explicit ProxyPage(QWidget *parent = 0);
+ ~ProxyPage();
+
+ QString displayName() const override
+ {
+ return tr("Proxy");
+ }
+ QIcon icon() const override
+ {
+ return QIcon::fromTheme("proxy");
+ }
+ QString id() const override
+ {
+ return "proxy-settings";
+ }
+ QString helpPage() const override
+ {
+ return "Proxy-settings";
+ }
+ bool apply() override;
+
+private:
+ void updateCheckboxStuff();
+ void applySettings();
+ void loadSettings();
+
+private
+slots:
+ void proxyChanged(int);
+
+private:
+ Ui::ProxyPage *ui;
+};
diff --git a/gui/pages/global/ProxyPage.ui b/gui/pages/global/ProxyPage.ui
new file mode 100644
index 00000000..7cddd66d
--- /dev/null
+++ b/gui/pages/global/ProxyPage.ui
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ProxyPage</class>
+ <widget class="QWidget" name="ProxyPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>607</width>
+ <height>632</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Settings</string>
+ </property>
+ <property name="windowIcon">
+ <iconset>
+ <normaloff>:/icons/toolbar/settings</normaloff>:/icons/toolbar/settings</iconset>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <widget class="QWidget" name="tabWidgetPage1" native="true">
+ <attribute name="title">
+ <string/>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="proxyTypeBox">
+ <property name="title">
+ <string>Type</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QRadioButton" name="proxyDefaultBtn">
+ <property name="toolTip">
+ <string>Uses your system's default proxy settings.</string>
+ </property>
+ <property name="text">
+ <string>Default</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">proxyGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="proxyNoneBtn">
+ <property name="text">
+ <string>None</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">proxyGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="proxySOCKS5Btn">
+ <property name="text">
+ <string>SOCKS5</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">proxyGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="proxyHTTPBtn">
+ <property name="text">
+ <string>HTTP</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">proxyGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="proxyAddrBox">
+ <property name="title">
+ <string>Address and Port</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="proxyAddrEdit">
+ <property name="placeholderText">
+ <string>127.0.0.1</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="proxyPortEdit">
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::PlusMinus</enum>
+ </property>
+ <property name="maximum">
+ <number>65535</number>
+ </property>
+ <property name="value">
+ <number>8080</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="proxyAuthBox">
+ <property name="title">
+ <string>Authentication</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_5">
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="proxyUserEdit"/>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="proxyUsernameLabel">
+ <property name="text">
+ <string>Username:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="proxyPasswordLabel">
+ <property name="text">
+ <string>Password:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="proxyPassEdit">
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QLabel" name="proxyPlainTextWarningLabel">
+ <property name="text">
+ <string>Note: Proxy username and password are stored in plain text inside MultiMC's configuration file!</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <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>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+ <buttongroups>
+ <buttongroup name="proxyGroup"/>
+ </buttongroups>
+</ui>
diff --git a/gui/widgets/PageContainer.cpp b/gui/widgets/PageContainer.cpp
index a68f94cd..0620c725 100644
--- a/gui/widgets/PageContainer.cpp
+++ b/gui/widgets/PageContainer.cpp
@@ -124,6 +124,9 @@ void PageContainer::createUI()
headerHLayout->addSpacerItem(
new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored));
headerHLayout->addWidget(m_iconHeader);
+ const int rightMargin = MMC->style()->pixelMetric(QStyle::PM_LayoutRightMargin);
+ headerHLayout->addSpacerItem(
+ new QSpacerItem(rightMargin, 0, QSizePolicy::Fixed, QSizePolicy::Ignored));
m_pageStack->setMargin(0);
m_pageStack->addWidget(new QWidget(this));
diff --git a/logic/BaseVersionList.h b/logic/BaseVersionList.h
index f903b52c..21b44e8d 100644
--- a/logic/BaseVersionList.h
+++ b/logic/BaseVersionList.h
@@ -100,10 +100,7 @@ public:
/*!
* Sorts the version list.
*/
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Woverloaded-virtual"
virtual void sort() = 0;
- #pragma clang diagnostic pop
protected
slots:
diff --git a/logic/DefaultVariable.h b/logic/DefaultVariable.h
new file mode 100644
index 00000000..38d7ecc2
--- /dev/null
+++ b/logic/DefaultVariable.h
@@ -0,0 +1,35 @@
+#pragma once
+
+template <typename T>
+class DefaultVariable
+{
+public:
+ DefaultVariable(const T & value)
+ {
+ defaultValue = value;
+ }
+ DefaultVariable<T> & operator =(const T & value)
+ {
+ currentValue = value;
+ is_default = currentValue == defaultValue;
+ is_explicit = true;
+ return *this;
+ }
+ operator const T &() const
+ {
+ return is_default ? defaultValue : currentValue;
+ }
+ bool isDefault() const
+ {
+ return is_default;
+ }
+ bool isExplicit() const
+ {
+ return is_explicit;
+ }
+private:
+ T currentValue;
+ T defaultValue;
+ bool is_default = true;
+ bool is_explicit = false;
+};
diff --git a/logic/InstanceList.cpp b/logic/InstanceList.cpp
index 8a68c334..650f5c80 100644
--- a/logic/InstanceList.cpp
+++ b/logic/InstanceList.cpp
@@ -331,7 +331,29 @@ QSet<FTBRecord> InstanceList::discoverFTBInstances()
continue;
record.name = attrs.value("name").toString();
record.logo = attrs.value("logo").toString();
- record.mcVersion = attrs.value("mcVersion").toString();
+ auto customVersions = attrs.value("customMCVersions");
+ if(!customVersions.isNull())
+ {
+ QMap<QString, QString> versionMatcher;
+ QString customVersionsStr = customVersions.toString();
+ QStringList list = customVersionsStr.split(';');
+ for(auto item: list)
+ {
+ auto segment = item.split('^');
+ if(segment.size() != 2)
+ {
+ QLOG_ERROR() << "FTB: Segment of size < 2 in " << customVersionsStr;
+ continue;
+ }
+ versionMatcher[segment[0]] = segment[1];
+ }
+ auto actualVersion = attrs.value("version").toString();
+ record.mcVersion = versionMatcher[actualVersion];
+ }
+ else
+ {
+ record.mcVersion = attrs.value("mcVersion").toString();
+ }
record.description = attrs.value("description").toString();
records.insert(record);
}
diff --git a/logic/LwjglVersionList.cpp b/logic/LwjglVersionList.cpp
index df46d7be..84aaf03d 100644
--- a/logic/LwjglVersionList.cpp
+++ b/logic/LwjglVersionList.cpp
@@ -22,7 +22,7 @@
#include "logger/QsLog.h"
-#define RSS_URL "http://sourceforge.net/api/file/index/project-id/58488/mtime/desc/rss"
+#define RSS_URL "http://sourceforge.net/projects/java-game-lib/rss"
LWJGLVersionList::LWJGLVersionList(QObject *parent) : QAbstractListModel(parent)
{
@@ -84,7 +84,7 @@ void LWJGLVersionList::loadList()
setLoading(true);
auto worker = MMC->qnam();
QNetworkRequest req(QUrl(RSS_URL));
- req.setRawHeader("Accept", "text/xml");
+ req.setRawHeader("Accept", "application/rss+xml, text/xml, */*");
req.setRawHeader("User-Agent", "MultiMC/5.0 (Uncached)");
reply = worker->get(req);
connect(reply, SIGNAL(finished()), SLOT(netRequestComplete()));
@@ -110,7 +110,8 @@ void LWJGLVersionList::netRequestComplete()
QString xmlErrorMsg;
int errorLine;
- if (!doc.setContent(reply->readAll(), false, &xmlErrorMsg, &errorLine))
+ auto rawData = reply->readAll();
+ if (!doc.setContent(rawData, false, &xmlErrorMsg, &errorLine))
{
failed("Failed to load LWJGL list. XML error: " + xmlErrorMsg + " at line " +
QString::number(errorLine));
@@ -146,10 +147,10 @@ void LWJGLVersionList::netRequestComplete()
QUrl url(link);
if (!url.isValid())
{
- QLOG_INFO() << "LWJGL version URL isn't valid:" << link << "Skipping.";
+ QLOG_WARN() << "LWJGL version URL isn't valid:" << link << "Skipping.";
continue;
}
-
+ QLOG_INFO() << "Discovered LWGL version" << name << "at" << link;
tempList.append(LWJGLVersion::Create(name, link));
}
}
@@ -183,7 +184,7 @@ const PtrLWJGLVersion LWJGLVersionList::getVersion(const QString &versionName)
void LWJGLVersionList::failed(QString msg)
{
- QLOG_INFO() << msg;
+ QLOG_ERROR() << msg;
emit loadListFailed(msg);
}
diff --git a/logic/VersionFilterData.cpp b/logic/VersionFilterData.cpp
index e8523018..866d4947 100644
--- a/logic/VersionFilterData.cpp
+++ b/logic/VersionFilterData.cpp
@@ -65,4 +65,8 @@ VersionFilterData::VersionFilterData()
* (these versions need to be tested by us first)
*/
legacyCutoffDate = timeFromS3Time("2013-06-25T15:08:56+02:00");
+ lwjglWhitelist =
+ QSet<QString>{"net.java.jinput:jinput", "net.java.jinput:jinput-platform",
+ "net.java.jutils:jutils", "org.lwjgl.lwjgl:lwjgl",
+ "org.lwjgl.lwjgl:lwjgl_util", "org.lwjgl.lwjgl:lwjgl-platform"};
}
diff --git a/logic/VersionFilterData.h b/logic/VersionFilterData.h
index e010adc7..98ecb36c 100644
--- a/logic/VersionFilterData.h
+++ b/logic/VersionFilterData.h
@@ -22,5 +22,7 @@ struct VersionFilterData
QSet<QString> legacyBlacklist;
// no new versions below this date will be accepted from Mojang servers
QDateTime legacyCutoffDate;
+ // Libraries that belong to LWJGL
+ QSet<QString> lwjglWhitelist;
};
extern VersionFilterData g_VersionFilterData;
diff --git a/logic/forge/ForgeInstaller.cpp b/logic/forge/ForgeInstaller.cpp
index 7ab0a09b..74db2bfc 100644
--- a/logic/forge/ForgeInstaller.cpp
+++ b/logic/forge/ForgeInstaller.cpp
@@ -133,8 +133,8 @@ bool ForgeInstaller::add(OneSixInstance *to)
int sliding_insert_window = 0;
{
QJsonArray librariesPlus;
- // A blacklist - we ignore these entirely
- QSet<QString> blacklist{"lwjgl", "lwjgl_util", "lwjgl-platform"};
+ // A blacklist
+ QSet<QString> blacklist{"authlib", "realms"};
//
QList<QString> xzlist{"org.scala-lang", "com.typesafe"};
// for each library in the version we are adding (except for the blacklisted)
@@ -143,15 +143,38 @@ bool ForgeInstaller::add(OneSixInstance *to)
QString libName = lib->name();
QString rawName = lib->rawName();
- // ignore blacklisted stuff
+ // ignore lwjgl libraries.
+ if (g_VersionFilterData.lwjglWhitelist.contains(lib->fullname()))
+ continue;
+ // ignore other blacklisted (realms, authlib)
if (blacklist.contains(libName))
continue;
// WARNING: This could actually break.
// if this is the actual forge lib, set an absolute url for the download
- if (libName.contains("minecraftforge"))
+ if(m_forge_version->type == ForgeVersion::Gradle)
+ {
+ if (libName == "forge")
+ {
+ lib->m_name.setClassifier("universal");
+ lib->finalize();
+ }
+ else if (libName == "minecraftforge")
+ {
+ QString forgeCoord ("net.minecraftforge:forge:%1:universal");
+ // using insane form of the MC version...
+ QString longVersion = m_forge_version->mcver + "-" + m_forge_version->jobbuildver;
+ GradleSpecifier spec(forgeCoord.arg(longVersion));
+ lib->m_name = spec;
+ lib->finalize();
+ }
+ }
+ else
{
- lib->setAbsoluteUrl(m_universal_url);
+ if (libName.contains("minecraftforge"))
+ {
+ lib->setAbsoluteUrl(m_universal_url);
+ }
}
// WARNING: This could actually break.
@@ -192,7 +215,7 @@ bool ForgeInstaller::add(OneSixInstance *to)
{
// add lib
libObj.insert("insert", QString("prepend"));
- if (lib->name() == "minecraftforge")
+ if (lib->name() == "minecraftforge" || lib->name() == "forge")
{
libObj.insert("MMC-depend", QString("hard"));
}
diff --git a/logic/forge/ForgeVersion.h b/logic/forge/ForgeVersion.h
index 466f46bd..c7adc572 100644
--- a/logic/forge/ForgeVersion.h
+++ b/logic/forge/ForgeVersion.h
@@ -17,6 +17,13 @@ struct ForgeVersion : public BaseVersion
QString filename();
QString url();
+ enum
+ {
+ Invalid,
+ Legacy,
+ Gradle
+ } type = Invalid;
+
bool usesInstaller();
int m_buildnr = 0;
diff --git a/logic/forge/ForgeVersionList.cpp b/logic/forge/ForgeVersionList.cpp
index efb30ba6..ee7c63e3 100644
--- a/logic/forge/ForgeVersionList.cpp
+++ b/logic/forge/ForgeVersionList.cpp
@@ -286,6 +286,7 @@ bool ForgeListLoadTask::parseForgeList(QList<BaseVersionPtr> &out)
fVersion->installer_filename = installer_filename;
fVersion->universal_filename = universal_filename;
fVersion->m_buildnr = build_nr;
+ fVersion->type = ForgeVersion::Legacy;
out.append(fVersion);
}
}
@@ -335,6 +336,10 @@ bool ForgeListLoadTask::parseForgeGradleList(QList<BaseVersionPtr> &out)
QJsonObject number = it.value().toObject();
std::shared_ptr<ForgeVersion> fVersion(new ForgeVersion());
fVersion->m_buildnr = number.value("build").toDouble();
+ if(fVersion->m_buildnr >= 953 && fVersion->m_buildnr <= 965)
+ {
+ QLOG_DEBUG() << fVersion->m_buildnr;
+ }
fVersion->jobbuildver = number.value("version").toString();
fVersion->branch = number.value("branch").toString("");
fVersion->mcver = number.value("mcversion").toString();
@@ -395,6 +400,7 @@ bool ForgeListLoadTask::parseForgeGradleList(QList<BaseVersionPtr> &out)
}
fVersion->universal_filename = universal_filename;
fVersion->installer_filename = installer_filename;
+ fVersion->type = ForgeVersion::Gradle;
out.append(fVersion);
}
return true;
diff --git a/logic/liteloader/LiteLoaderVersionList.cpp b/logic/liteloader/LiteLoaderVersionList.cpp
index eced78e9..af8509d6 100644
--- a/logic/liteloader/LiteLoaderVersionList.cpp
+++ b/logic/liteloader/LiteLoaderVersionList.cpp
@@ -212,7 +212,7 @@ void LLListLoadTask::listDownloaded()
{
auto lib = RawLibrary::fromJson(libobject, "versions.json");
// hack to make liteloader 1.7.10_00 work
- if(lib->m_name == "org.ow2.asm:asm-all:5.0.3")
+ if(lib->m_name == GradleSpecifier("org.ow2.asm:asm-all:5.0.3"))
{
lib->m_base_url = "http://repo.maven.apache.org/maven2/";
}
diff --git a/logic/minecraft/GradleSpecifier.h b/logic/minecraft/GradleSpecifier.h
new file mode 100644
index 00000000..8a02e4d9
--- /dev/null
+++ b/logic/minecraft/GradleSpecifier.h
@@ -0,0 +1,129 @@
+#pragma once
+
+#include <QString>
+#include <QStringList>
+#include "logic/DefaultVariable.h"
+
+struct GradleSpecifier
+{
+ GradleSpecifier()
+ {
+ m_valid = false;
+ }
+ GradleSpecifier(QString value)
+ {
+ operator=(value);
+ }
+ GradleSpecifier & operator =(const QString & value)
+ {
+ /*
+ org.gradle.test.classifiers : service : 1.0 : jdk15 @ jar
+ DEBUG 0 "org.gradle.test.classifiers:service:1.0:jdk15@jar"
+ DEBUG 1 "org.gradle.test.classifiers"
+ DEBUG 2 "service"
+ DEBUG 3 "1.0"
+ DEBUG 4 ":jdk15"
+ DEBUG 5 "jdk15"
+ DEBUG 6 "@jar"
+ DEBUG 7 "jar"
+ */
+ QRegExp matcher("([^:@]+):([^:@]+):([^:@]+)" "(:([^:@]+))?" "(@([^:@]+))?");
+ m_valid = matcher.exactMatch(value);
+ auto elements = matcher.capturedTexts();
+ m_groupId = elements[1];
+ m_artifactId = elements[2];
+ m_version = elements[3];
+ m_classifier = elements[5];
+ if(!elements[7].isEmpty())
+ {
+ m_extension = elements[7];
+ }
+ return *this;
+ }
+ operator QString() const
+ {
+ if(!m_valid)
+ return "INVALID";
+ QString retval = m_groupId + ":" + m_artifactId + ":" + m_version;
+ if(!m_classifier.isEmpty())
+ {
+ retval += ":" + m_classifier;
+ }
+ if(m_extension.isExplicit())
+ {
+ retval += "@" + m_extension;
+ }
+ return retval;
+ }
+ QString toPath() const
+ {
+ if(!m_valid)
+ return "INVALID";
+ QString path = m_groupId;
+ path.replace('.', '/');
+ path += '/' + m_artifactId + '/' + m_version + '/' + m_artifactId + '-' + m_version;
+ if(!m_classifier.isEmpty())
+ {
+ path += "-" + m_classifier;
+ }
+ path += "." + m_extension;
+ return path;
+ }
+ inline bool valid() const
+ {
+ return m_valid;
+ }
+ inline QString version() const
+ {
+ return m_version;
+ }
+ inline QString groupId() const
+ {
+ return m_groupId;
+ }
+ inline QString artifactId() const
+ {
+ return m_artifactId;
+ }
+ inline void setClassifier(const QString & classifier)
+ {
+ m_classifier = classifier;
+ }
+ inline QString classifier() const
+ {
+ return m_classifier;
+ }
+ inline QString extension() const
+ {
+ return m_extension;
+ }
+ inline QString artifactPrefix() const
+ {
+ return m_groupId + ":" + m_artifactId;
+ }
+ bool matchName(const GradleSpecifier & other)
+ {
+ return other.artifactId() == artifactId() && other.groupId() == groupId();
+ }
+ bool operator==(const GradleSpecifier & other)
+ {
+ if(m_groupId != other.m_groupId)
+ return false;
+ if(m_artifactId != other.m_artifactId)
+ return false;
+ if(m_version != other.m_version)
+ return false;
+ if(m_classifier != other.m_classifier)
+ return false;
+ if(m_extension != other.m_extension)
+ return false;
+ return true;
+ }
+private:
+ QString m_groupId;
+ QString m_artifactId;
+ QString m_version;
+ QString m_classifier;
+ DefaultVariable<QString> m_extension = DefaultVariable<QString>("jar");
+ bool m_valid = false;
+};
diff --git a/logic/minecraft/MinecraftVersion.cpp b/logic/minecraft/MinecraftVersion.cpp
index 488a180a..8368c430 100644
--- a/logic/minecraft/MinecraftVersion.cpp
+++ b/logic/minecraft/MinecraftVersion.cpp
@@ -2,6 +2,8 @@
#include "InstanceVersion.h"
#include "VersionBuildError.h"
#include "VersionBuilder.h"
+#include "MultiMC.h"
+#include "logic/settings/SettingsObject.h"
bool MinecraftVersion::usesLegacyLauncher()
{
@@ -141,3 +143,15 @@ QString MinecraftVersion::getPatchFilename()
{
return QString();
}
+
+bool MinecraftVersion::needsUpdate()
+{
+ auto settings = MMC->settings();
+ bool result = hasUpdate() && settings->get("AutoUpdateMinecraftVersions").toBool();
+ return result;
+}
+
+bool MinecraftVersion::hasUpdate()
+{
+ return m_versionSource == Remote || (m_versionSource == Local && upstreamUpdate);
+}
diff --git a/logic/minecraft/MinecraftVersion.h b/logic/minecraft/MinecraftVersion.h
index 82073a97..e06dadb1 100644
--- a/logic/minecraft/MinecraftVersion.h
+++ b/logic/minecraft/MinecraftVersion.h
@@ -45,14 +45,8 @@ public: /* methods */
virtual QString getPatchVersion() override;
virtual QString getPatchName() override;
virtual QString getPatchFilename() override;
- bool needsUpdate()
- {
- return m_versionSource == Remote;
- }
- bool hasUpdate()
- {
- return m_versionSource == Remote || (m_versionSource == Local && upstreamUpdate);
- }
+ bool needsUpdate();
+ bool hasUpdate();
private: /* methods */
void applyFileTo(InstanceVersion *version);
diff --git a/logic/minecraft/MinecraftVersionList.cpp b/logic/minecraft/MinecraftVersionList.cpp
index 3aa1ac01..ee228528 100644
--- a/logic/minecraft/MinecraftVersionList.cpp
+++ b/logic/minecraft/MinecraftVersionList.cpp
@@ -266,7 +266,8 @@ void MinecraftVersionList::loadMojangList(QJsonDocument jsonDoc, VersionSource s
QString versionTypeStr = versionObj.value("type").toString("");
if (versionTypeStr.isEmpty())
{
- // FIXME: log this somewhere
+ QLOG_ERROR() << "Ignoring" << versionID
+ << "because it doesn't have the version type set.";
continue;
}
// OneSix or Legacy. use filter to determine type
@@ -284,10 +285,13 @@ void MinecraftVersionList::loadMojangList(QJsonDocument jsonDoc, VersionSource s
}
else
{
- // FIXME: log this somewhere
+ QLOG_ERROR() << "Ignoring" << versionID
+ << "because it has an invalid version type.";
continue;
}
mcVersion->m_type = versionTypeStr;
+ QLOG_INFO() << "Loaded version" << versionID << "from"
+ << ((source == Remote) ? "remote" : "local") << "version list.";
tempList.append(mcVersion);
}
updateListData(tempList);
@@ -333,12 +337,6 @@ void MinecraftVersionList::updateListData(QList<BaseVersionPtr> versions)
{
continue;
}
- // is it actually an update?
- if (orig->m_updateTime >= added->m_updateTime)
- {
- // nope.
- continue;
- }
// alright, it's an update. put it inside the original, for further processing.
orig->upstreamUpdate = added;
}
@@ -451,13 +449,10 @@ void MCVListVersionUpdateTask::json_downloaded()
}
QList<RawLibraryPtr> filteredLibs;
QList<RawLibraryPtr> lwjglLibs;
- QSet<QString> lwjglFilter = {
- "net.java.jinput:jinput", "net.java.jinput:jinput-platform",
- "net.java.jutils:jutils", "org.lwjgl.lwjgl:lwjgl",
- "org.lwjgl.lwjgl:lwjgl_util", "org.lwjgl.lwjgl:lwjgl-platform"};
+
for (auto lib : file->overwriteLibs)
{
- if (lwjglFilter.contains(lib->fullname()))
+ if (g_VersionFilterData.lwjglWhitelist.contains(lib->fullname()))
{
lwjglLibs.append(lib);
}
@@ -581,9 +576,11 @@ void MinecraftVersionList::finalizeUpdate(QString version)
auto updatedVersion = std::dynamic_pointer_cast<MinecraftVersion>(m_vlist[idx]);
+ // reject any updates to builtin versions.
if (updatedVersion->m_versionSource == Builtin)
return;
+ // if we have an update for the version, replace it, make the update local
if (updatedVersion->upstreamUpdate)
{
auto updatedWith = updatedVersion->upstreamUpdate;
@@ -593,6 +590,7 @@ void MinecraftVersionList::finalizeUpdate(QString version)
}
else
{
+ // otherwise, just set the version as local;
updatedVersion->m_versionSource = Local;
}
diff --git a/logic/minecraft/OneSixLibrary.cpp b/logic/minecraft/OneSixLibrary.cpp
index 7f69d9f8..c562f353 100644
--- a/logic/minecraft/OneSixLibrary.cpp
+++ b/logic/minecraft/OneSixLibrary.cpp
@@ -30,7 +30,7 @@ OneSixLibrary::OneSixLibrary(RawLibraryPtr base)
m_hint = base->m_hint;
m_absolute_url = base->m_absolute_url;
extract_excludes = base->extract_excludes;
- m_native_suffixes = base->m_native_suffixes;
+ m_native_classifiers = base->m_native_classifiers;
m_rules = base->m_rules;
finalize();
}
@@ -42,31 +42,8 @@ OneSixLibraryPtr OneSixLibrary::fromRawLibrary(RawLibraryPtr lib)
void OneSixLibrary::finalize()
{
- QStringList parts = m_name.split(':');
- QString relative = parts[0];
- relative.replace('.', '/');
- relative += '/' + parts[1] + '/' + parts[2] + '/' + parts[1] + '-' + parts[2];
-
- if (!isNative())
- relative += ".jar";
- else
- {
- if (m_native_suffixes.contains(currentSystem))
- {
- relative += "-" + m_native_suffixes[currentSystem] + ".jar";
- }
- else
- {
- // really, bad.
- relative += ".jar";
- }
- }
-
- m_decentname = parts[1];
- m_decentversion = minVersion = parts[2];
- m_storage_path = relative;
- m_download_url = m_base_url + relative;
-
+ QString relative;
+
if (m_rules.empty())
{
m_is_active = true;
@@ -84,13 +61,32 @@ void OneSixLibrary::finalize()
}
if (isNative())
{
- m_is_active = m_is_active && m_native_suffixes.contains(currentSystem);
+ GradleSpecifier nativeSpec = m_name;
+ m_is_active = m_is_active && m_native_classifiers.contains(currentSystem);
m_decenttype = "Native";
+ if(m_native_classifiers.contains(currentSystem))
+ {
+ nativeSpec.setClassifier(m_native_classifiers[currentSystem]);
+ }
+ else
+ {
+ nativeSpec.setClassifier("INVALID");
+ }
+ relative = nativeSpec.toPath();
}
else
{
+ relative = m_name.toPath();
m_decenttype = "Java";
}
+
+ m_decentname = m_name.artifactId();
+ m_decentversion = minVersion = m_name.version();
+ m_storage_path = relative;
+ if(m_base_url.isEmpty())
+ m_download_url = QString("https://" + URLConstants::LIBRARY_BASE) + relative;
+ else
+ m_download_url = m_base_url + relative;
}
void OneSixLibrary::setName(const QString &name)
@@ -103,11 +99,11 @@ void OneSixLibrary::setBaseUrl(const QString &base_url)
}
void OneSixLibrary::addNative(OpSys os, const QString &suffix)
{
- m_native_suffixes[os] = suffix;
+ m_native_classifiers[os] = suffix;
}
void OneSixLibrary::clearSuffixes()
{
- m_native_suffixes.clear();
+ m_native_classifiers.clear();
}
void OneSixLibrary::setRules(QList<std::shared_ptr<Rule>> rules)
{
diff --git a/logic/minecraft/RawLibrary.cpp b/logic/minecraft/RawLibrary.cpp
index 7e0ebff0..76bd7260 100644
--- a/logic/minecraft/RawLibrary.cpp
+++ b/logic/minecraft/RawLibrary.cpp
@@ -13,20 +13,20 @@ RawLibraryPtr RawLibrary::fromJson(const QJsonObject &libObj, const QString &fil
}
out->m_name = libObj.value("name").toString();
- auto readString = [libObj, filename](const QString & key, QString & variable)
+ auto readString = [libObj, filename](const QString & key, QString & variable) -> bool
{
- if (libObj.contains(key))
+ if (!libObj.contains(key))
+ return false;
+ QJsonValue val = libObj.value(key);
+
+ if (!val.isString())
{
- QJsonValue val = libObj.value(key);
- if (!val.isString())
- {
- QLOG_WARN() << key << "is not a string in" << filename << "(skipping)";
- }
- else
- {
- variable = val.toString();
- }
+ QLOG_WARN() << key << "is not a string in" << filename << "(skipping)";
+ return false;
}
+
+ variable = val.toString();
+ return true;
};
readString("url", out->m_base_url);
@@ -54,7 +54,7 @@ RawLibraryPtr RawLibrary::fromJson(const QJsonObject &libObj, const QString &fil
OpSys opSys = OpSys_fromString(it.key());
if (opSys != Os_Other)
{
- out->m_native_suffixes[opSys] = it.value().toString();
+ out->m_native_classifiers[opSys] = it.value().toString();
}
}
}
@@ -134,13 +134,13 @@ RawLibraryPtr RawLibrary::fromJsonPlus(const QJsonObject &libObj, const QString
bool RawLibrary::isNative() const
{
- return m_native_suffixes.size() != 0;
+ return m_native_classifiers.size() != 0;
}
QJsonObject RawLibrary::toJson()
{
QJsonObject libRoot;
- libRoot.insert("name", m_name);
+ libRoot.insert("name", (QString)m_name);
if (m_absolute_url.size())
libRoot.insert("MMC-absoluteUrl", m_absolute_url);
if (m_hint.size())
@@ -154,8 +154,8 @@ QJsonObject RawLibrary::toJson()
if (isNative())
{
QJsonObject nativeList;
- auto iter = m_native_suffixes.begin();
- while (iter != m_native_suffixes.end())
+ auto iter = m_native_classifiers.begin();
+ while (iter != m_native_classifiers.end())
{
nativeList.insert(OpSys_toString(iter.key()), iter.value());
iter++;
@@ -188,18 +188,5 @@ QJsonObject RawLibrary::toJson()
QString RawLibrary::fullname()
{
- QStringList parts = m_name.split(':');
- return parts[0] + ":" + parts[1];
-}
-
-QString RawLibrary::group()
-{
- QStringList parts = m_name.split(':');
- return parts[0];
-}
-
-QString RawLibrary::version()
-{
- QStringList parts = m_name.split(':');
- return parts[2];
+ return m_name.artifactPrefix();
}
diff --git a/logic/minecraft/RawLibrary.h b/logic/minecraft/RawLibrary.h
index f5a28c61..6e8f7f10 100644
--- a/logic/minecraft/RawLibrary.h
+++ b/logic/minecraft/RawLibrary.h
@@ -8,6 +8,7 @@
#include "logic/minecraft/OneSixRule.h"
#include "logic/minecraft/OpSys.h"
+#include "GradleSpecifier.h"
#include "logic/net/URLConstants.h"
class RawLibrary;
@@ -23,15 +24,14 @@ public: /* methods */
QJsonObject toJson();
QString fullname();
- QString version();
- QString group();
public: /* data */
- QString m_name;
- QString m_base_url = "https://" + URLConstants::LIBRARY_BASE;
+ GradleSpecifier m_name;
+ QString m_base_url;
+
/// type hint - modifies how the library is treated
QString m_hint;
- /// absolute URL. takes precedence over m_download_path, if defined
+ /// DEPRECATED: absolute URL. takes precedence over m_download_path, if defined
QString m_absolute_url;
bool applyExcludes = false;
@@ -40,7 +40,7 @@ public: /* data */
/// Returns true if the library is native
bool isNative() const;
/// native suffixes per OS
- QMap<OpSys, QString> m_native_suffixes;
+ QMap<OpSys, QString> m_native_classifiers;
bool applyRules = false;
QList<std::shared_ptr<Rule>> m_rules;
diff --git a/logic/minecraft/VersionFile.cpp b/logic/minecraft/VersionFile.cpp
index 93f57116..600c71ae 100644
--- a/logic/minecraft/VersionFile.cpp
+++ b/logic/minecraft/VersionFile.cpp
@@ -17,13 +17,13 @@ using namespace MMCJson;
#define CURRENT_MINIMUM_LAUNCHER_VERSION 14
-int findLibrary(QList<OneSixLibraryPtr> haystack, const QString &needle)
+int findLibraryByName(QList<OneSixLibraryPtr> haystack, const GradleSpecifier &needle)
{
int retval = -1;
for (int i = 0; i < haystack.size(); ++i)
{
- QString chunk = haystack.at(i)->rawName();
- if (QRegExp(needle, Qt::CaseSensitive, QRegExp::WildcardUnix).indexIn(chunk) != -1)
+
+ if(haystack.at(i)->m_name.matchName(needle))
{
// only one is allowed.
if (retval != -1)
@@ -382,7 +382,7 @@ void VersionFile::applyTo(InstanceVersion *version)
case RawLibrary::Apply:
{
// QLOG_INFO() << "Applying lib " << lib->name;
- int index = findLibrary(version->libraries, lib->m_name);
+ int index = findLibraryByName(version->libraries, lib->m_name);
if (index >= 0)
{
auto library = version->libraries[index];
@@ -405,7 +405,7 @@ void VersionFile::applyTo(InstanceVersion *version)
if (lib->isNative())
{
// library->clearSuffixes();
- library->m_native_suffixes = lib->m_native_suffixes;
+ library->m_native_classifiers = lib->m_native_classifiers;
/*
for (auto native : lib->natives)
{
@@ -429,9 +429,7 @@ void VersionFile::applyTo(InstanceVersion *version)
case RawLibrary::Prepend:
{
// QLOG_INFO() << "Adding lib " << lib->name;
- const int startOfVersion = lib->m_name.lastIndexOf(':') + 1;
- const int index = findLibrary(
- version->libraries, QString(lib->m_name).replace(startOfVersion, INT_MAX, '*'));
+ const int index = findLibraryByName(version->libraries, lib->m_name);
if (index < 0)
{
if (lib->insertType == RawLibrary::Append)
@@ -446,8 +444,8 @@ void VersionFile::applyTo(InstanceVersion *version)
else
{
auto otherLib = version->libraries.at(index);
- const Util::Version ourVersion = lib->m_name.mid(startOfVersion, INT_MAX);
- const Util::Version otherVersion = otherLib->version();
+ const Util::Version ourVersion = lib->m_name.version();
+ const Util::Version otherVersion = otherLib->m_name.version();
// if the existing version is a hard dependency we can either use it or
// fail, but we can't change it
if (otherLib->dependType == OneSixLibrary::Hard)
@@ -497,16 +495,17 @@ void VersionFile::applyTo(InstanceVersion *version)
}
case RawLibrary::Replace:
{
- QString toReplace;
+ GradleSpecifier toReplace;
if (lib->insertData.isEmpty())
{
- const int startOfVersion = lib->m_name.lastIndexOf(':') + 1;
- toReplace = QString(lib->m_name).replace(startOfVersion, INT_MAX, '*');
+ toReplace = lib->m_name;
}
else
+ {
toReplace = lib->insertData;
+ }
// QLOG_INFO() << "Replacing lib " << toReplace << " with " << lib->name;
- int index = findLibrary(version->libraries, toReplace);
+ int index = findLibraryByName(version->libraries, toReplace);
if (index >= 0)
{
version->libraries.replace(index, OneSixLibrary::fromRawLibrary(lib));
@@ -521,7 +520,7 @@ void VersionFile::applyTo(InstanceVersion *version)
}
for (auto lib : removeLibs)
{
- int index = findLibrary(version->libraries, lib);
+ int index = findLibraryByName(version->libraries, lib);
if (index >= 0)
{
// QLOG_INFO() << "Removing lib " << lib;
diff --git a/resources/multimc/16x16/minecraft.png b/resources/multimc/16x16/minecraft.png
new file mode 100644
index 00000000..e9f2f2a5
--- /dev/null
+++ b/resources/multimc/16x16/minecraft.png
Binary files differ
diff --git a/resources/multimc/24x24/minecraft.png b/resources/multimc/24x24/minecraft.png
new file mode 100644
index 00000000..b31177c9
--- /dev/null
+++ b/resources/multimc/24x24/minecraft.png
Binary files differ
diff --git a/resources/multimc/256x256/minecraft.png b/resources/multimc/256x256/minecraft.png
new file mode 100644
index 00000000..77e3f03e
--- /dev/null
+++ b/resources/multimc/256x256/minecraft.png
Binary files differ
diff --git a/resources/multimc/32x32/minecraft.png b/resources/multimc/32x32/minecraft.png
new file mode 100644
index 00000000..816bec98
--- /dev/null
+++ b/resources/multimc/32x32/minecraft.png
Binary files differ
diff --git a/resources/multimc/48x48/minecraft.png b/resources/multimc/48x48/minecraft.png
new file mode 100644
index 00000000..38fc9f6c
--- /dev/null
+++ b/resources/multimc/48x48/minecraft.png
Binary files differ
diff --git a/resources/multimc/index.theme b/resources/multimc/index.theme
index 8e1241e9..5f7d3f3f 100644
--- a/resources/multimc/index.theme
+++ b/resources/multimc/index.theme
@@ -32,6 +32,9 @@ Size=48
[64x64]
Size=64
+[256x256]
+Size=256
+
[scalable]
Size=48
Type=Scalable
diff --git a/resources/multimc/multimc.qrc b/resources/multimc/multimc.qrc
index 0575bbf0..b0a1b3ab 100644
--- a/resources/multimc/multimc.qrc
+++ b/resources/multimc/multimc.qrc
@@ -11,6 +11,19 @@
<!-- ERROR console icon. Our own -->
<file>scalable/console_error.svg</file>
+ <!-- A proxy icon. Our own. SSSsss -->
+ <file>scalable/proxy.svg</file>
+
+ <!-- Java icon. From Oracle, fixed because it was derpy. -->
+ <file>scalable/java.svg</file>
+
+ <!-- Minecraft icon. Source: http://www.minecraftforum.net/forums/show-your-creation/fan-art/1574882-icon-better-minecraft-icon -->
+ <file>16x16/minecraft.png</file>
+ <file>24x24/minecraft.png</file>
+ <file>32x32/minecraft.png</file>
+ <file>48x48/minecraft.png</file>
+ <file>256x256/minecraft.png</file>
+
<!-- About dialog. GPLv2, http://openiconlibrary.sourceforge.net/gallery2/?./Icons/actions/help-contents.png -->
<file>16x16/about.png</file>
<file>22x22/about.png</file>
diff --git a/resources/multimc/scalable/java.svg b/resources/multimc/scalable/java.svg
new file mode 100644
index 00000000..fd15e5c6
--- /dev/null
+++ b/resources/multimc/scalable/java.svg
@@ -0,0 +1,773 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="160.00024"
+ height="159.99788"
+ id="svg12972"
+ version="1.1"
+ inkscape:version="0.48.5 r10040"
+ sodipodi:docname="java.svg">
+ <defs
+ id="defs12974">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3935">
+ <stop
+ style="stop-color:#000000;stop-opacity:0"
+ offset="0"
+ id="stop3937" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop3939" />
+ </linearGradient>
+ <linearGradient
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-126.08191,-126.08191,0,113.7417,390.27905)"
+ spreadMethod="pad"
+ id="linearGradient1722">
+ <stop
+ style="stop-opacity:1;stop-color:#dfe3e5"
+ offset="0"
+ id="stop1724" />
+ <stop
+ style="stop-opacity:1;stop-color:#bcc5ca"
+ offset="1"
+ id="stop1726" />
+ </linearGradient>
+ <linearGradient
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,68.061096,68.061096,0,113.7417,266.44751)"
+ spreadMethod="pad"
+ id="linearGradient1760">
+ <stop
+ style="stop-opacity:1;stop-color:#ffffff"
+ offset="0"
+ id="stop1762" />
+ <stop
+ style="stop-opacity:1;stop-color:#000000"
+ offset="1"
+ id="stop1764" />
+ </linearGradient>
+ <linearGradient
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-21.014618,-21.014618,0,113.7417,386.83423)"
+ spreadMethod="pad"
+ id="linearGradient1798">
+ <stop
+ style="stop-opacity:1;stop-color:#ffffff"
+ offset="0"
+ id="stop1800" />
+ <stop
+ style="stop-opacity:1;stop-color:#000000"
+ offset="1"
+ id="stop1802" />
+ </linearGradient>
+ <linearGradient
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-126.08191,-126.08191,0,113.7417,390.27905)"
+ spreadMethod="pad"
+ id="linearGradient1722-2">
+ <stop
+ style="stop-opacity:1;stop-color:#dfe3e5"
+ offset="0"
+ id="stop1724-7" />
+ <stop
+ style="stop-opacity:1;stop-color:#bcc5ca"
+ offset="1"
+ id="stop1726-8" />
+ </linearGradient>
+ <linearGradient
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,68.061096,68.061096,0,113.7417,266.44751)"
+ spreadMethod="pad"
+ id="linearGradient1760-4">
+ <stop
+ style="stop-opacity:1;stop-color:#ffffff"
+ offset="0"
+ id="stop1762-0" />
+ <stop
+ style="stop-color:#838383;stop-opacity:1;"
+ offset="1"
+ id="stop1764-8" />
+ </linearGradient>
+ <linearGradient
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-21.014618,-21.014618,0,113.7417,386.83423)"
+ spreadMethod="pad"
+ id="linearGradient1798-6">
+ <stop
+ style="stop-opacity:1;stop-color:#ffffff"
+ offset="0"
+ id="stop1800-8" />
+ <stop
+ style="stop-opacity:1;stop-color:#000000"
+ offset="1"
+ id="stop1802-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1722-2"
+ id="linearGradient3923"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-126.08191,-126.08191,0,113.7417,390.27905)"
+ spreadMethod="pad"
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1760-4"
+ id="linearGradient3933"
+ x1="113.341"
+ y1="267.14597"
+ x2="114.54707"
+ y2="417.25464"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3935"
+ id="linearGradient3941"
+ x1="112.53288"
+ y1="365.57138"
+ x2="112.52676"
+ y2="386.9866"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1760-4"
+ id="linearGradient3943"
+ gradientUnits="userSpaceOnUse"
+ x1="113.341"
+ y1="267.14597"
+ x2="114.54707"
+ y2="417.25464" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1760-4"
+ id="linearGradient3945"
+ gradientUnits="userSpaceOnUse"
+ x1="113.341"
+ y1="267.14597"
+ x2="114.54707"
+ y2="417.25464" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1760-4"
+ id="linearGradient3947"
+ gradientUnits="userSpaceOnUse"
+ x1="113.341"
+ y1="267.14597"
+ x2="114.54707"
+ y2="417.25464" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1760-4"
+ id="linearGradient3949"
+ gradientUnits="userSpaceOnUse"
+ x1="113.341"
+ y1="267.14597"
+ x2="114.54707"
+ y2="417.25464" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1760-4"
+ id="linearGradient3951"
+ gradientUnits="userSpaceOnUse"
+ x1="113.341"
+ y1="267.14597"
+ x2="114.54707"
+ y2="417.25464" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1760-4"
+ id="linearGradient3953"
+ gradientUnits="userSpaceOnUse"
+ x1="113.341"
+ y1="267.14597"
+ x2="114.54707"
+ y2="417.25464" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1760-4"
+ id="linearGradient3955"
+ gradientUnits="userSpaceOnUse"
+ x1="113.341"
+ y1="267.14597"
+ x2="114.54707"
+ y2="417.25464" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3935"
+ id="linearGradient3957"
+ gradientUnits="userSpaceOnUse"
+ x1="112.53288"
+ y1="365.57138"
+ x2="112.52676"
+ y2="386.9866" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3935"
+ id="linearGradient3961"
+ gradientUnits="userSpaceOnUse"
+ x1="112.53288"
+ y1="365.57138"
+ x2="112.52676"
+ y2="386.9866" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3935"
+ id="linearGradient3963"
+ gradientUnits="userSpaceOnUse"
+ x1="112.53288"
+ y1="365.57138"
+ x2="112.52676"
+ y2="386.9866" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3935"
+ id="linearGradient3965"
+ gradientUnits="userSpaceOnUse"
+ x1="112.53288"
+ y1="365.57138"
+ x2="112.52676"
+ y2="386.9866" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3935"
+ id="linearGradient3967"
+ gradientUnits="userSpaceOnUse"
+ x1="112.53288"
+ y1="365.57138"
+ x2="112.52676"
+ y2="386.9866" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3935"
+ id="linearGradient3969"
+ gradientUnits="userSpaceOnUse"
+ x1="112.53288"
+ y1="365.57138"
+ x2="112.52676"
+ y2="386.9866" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3935"
+ id="linearGradient3971"
+ gradientUnits="userSpaceOnUse"
+ x1="112.53288"
+ y1="365.57138"
+ x2="112.52676"
+ y2="386.9866" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3935"
+ id="linearGradient3973"
+ gradientUnits="userSpaceOnUse"
+ x1="112.53288"
+ y1="365.57138"
+ x2="112.52676"
+ y2="386.9866" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1760-4-8"
+ id="linearGradient3943-2"
+ gradientUnits="userSpaceOnUse"
+ x1="113.341"
+ y1="267.14597"
+ x2="114.54707"
+ y2="417.25464" />
+ <linearGradient
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,68.061096,68.061096,0,113.7417,266.44751)"
+ spreadMethod="pad"
+ id="linearGradient1760-4-8">
+ <stop
+ style="stop-opacity:1;stop-color:#ffffff"
+ offset="0"
+ id="stop1762-0-6" />
+ <stop
+ style="stop-opacity:1;stop-color:#000000"
+ offset="1"
+ id="stop1764-8-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1760-4"
+ id="linearGradient4033"
+ gradientUnits="userSpaceOnUse"
+ x1="113.341"
+ y1="267.14597"
+ x2="113.94098"
+ y2="387.35413" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.979899"
+ inkscape:cx="-0.08087368"
+ inkscape:cy="54.594259"
+ inkscape:document-units="px"
+ inkscape:current-layer="g1676-6"
+ showgrid="false"
+ showborder="true"
+ borderlayer="false"
+ inkscape:showpageshadow="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1613"
+ inkscape:window-height="1026"
+ inkscape:window-x="1677"
+ inkscape:window-y="-4"
+ inkscape:window-maximized="1">
+ <inkscape:grid
+ type="xygrid"
+ id="grid14007"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="-3.4602454px"
+ originy="2.8306126px"
+ spacingx="8px"
+ spacingy="8px" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata12977">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-269.17466,-423.7599)">
+ <g
+ transform="matrix(1.25,0,0,-1.25,203.53691,909.61217)"
+ id="g1674">
+ <g
+ id="g1676"
+ clip-path="url(#clipPath1678)">
+ <g
+ transform="translate(2.7683963,-2.2641865)"
+ id="g1674-5">
+ <g
+ id="g1676-6"
+ clip-path="url(#clipPath1678)">
+ <path
+ id="path3993"
+ style="fill:#ffffff;fill-opacity:1;stroke:none"
+ d="m 71.121479,387.39443 c -9.563,0 -17.336,-7.8193 -17.336,-17.42155 l 0,0 0,-85.75999 c 0,-9.61029 7.773,-17.42255 17.336,-17.42255 l 0,0 85.327991,0 c 9.562,0 17.336,7.81226 17.336,17.42255 l 0,0 0,85.75999 c 0,9.60225 -7.774,17.42155 -17.336,17.42155 l 0,0 z"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sccsccsccsccs" />
+ <g
+ id="g1682">
+ <g
+ id="g1684" />
+ <g
+ id="g1694">
+ <g
+ clip-path="url(#clipPath1686)"
+ id="g1696">
+ <g
+ id="g1698">
+ <g
+ clip-path="url(#clipPath1690)"
+ id="g1700">
+ <g
+ transform="translate(156.4058,390.9377)"
+ id="g1702">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 -85.328,0 c -11.735,0 -21.336,-9.6 -21.336,-21.334 l 0,-85.32 c 0,-11.742 9.601,-21.336 21.336,-21.336 l 85.328,0 c 11.734,0 21.336,9.594 21.336,21.336 l 0,85.32 C 21.336,-9.6 11.734,0 0,0 m 0,-1 c 11.211,0 20.336,-9.123 20.336,-20.334 l 0,-85.32 c 0,-11.219 -9.125,-20.336 -20.336,-20.336 l -85.328,0 c -11.215,0 -20.336,9.117 -20.336,20.336 l 0,85.32 c 0,11.211 9.121,20.334 20.336,20.334 L 0,-1"
+ style="fill:#b3b1b3;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1704" />
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g1706-5">
+ <g
+ id="g1708-7" />
+ <g
+ id="g1728-8">
+ <g
+ clip-path="url(#clipPath1710)"
+ id="g1730-3">
+ <g
+ id="g1732-3">
+ <g
+ clip-path="url(#clipPath1714)"
+ id="g1734-1">
+ <g
+ id="g1736-0">
+ <g
+ id="g1738-5">
+ <g
+ clip-path="url(#clipPath1718)"
+ id="g1740-7">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 71.078,390.946 c -11.735,0 -21.336,-9.6 -21.336,-21.334 l 0,0 0,-85.329 c 0,-11.742 9.601,-21.335 21.336,-21.335 l 0,0 85.328,0 c 11.734,0 21.336,9.593 21.336,21.335 l 0,0 0,85.329 c 0,11.734 -9.602,21.334 -21.336,21.334 l 0,0 -85.328,0 z m -17.336,-106.663 0,85.329 c 0,9.554 7.773,17.334 17.336,17.334 l 0,0 85.328,0 c 9.562,0 17.336,-7.78 17.336,-17.334 l 0,0 0,-85.329 c 0,-9.562 -7.774,-17.335 -17.336,-17.335 l 0,0 -85.328,0 c -9.563,0 -17.336,7.773 -17.336,17.335"
+ style="fill:url(#linearGradient3923);stroke:none"
+ id="path1742-8" />
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g1744-9">
+ <g
+ id="g1746-7" />
+ <g
+ id="g1766-3"
+ style="fill:url(#linearGradient4033);fill-opacity:1">
+ <g
+ style="opacity:0.69999701;fill:url(#linearGradient3955);fill-opacity:1"
+ clip-path="url(#clipPath1748)"
+ id="g1768-8">
+ <g
+ id="g1770-7"
+ style="fill:url(#linearGradient3953);fill-opacity:1">
+ <g
+ clip-path="url(#clipPath1752)"
+ id="g1772-5"
+ style="fill:url(#linearGradient3951);fill-opacity:1">
+ <g
+ id="g1774-4"
+ style="fill:url(#linearGradient3949);fill-opacity:1">
+ <g
+ id="g1776-9"
+ style="fill:url(#linearGradient3947);fill-opacity:1">
+ <g
+ clip-path="url(#clipPath1756)"
+ id="g1778-9"
+ style="fill:url(#linearGradient3945);fill-opacity:1">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 71.078,386.946 c -9.563,0 -17.336,-7.78 -17.336,-17.334 l 0,0 0,-85.329 c 0,-9.562 7.773,-17.335 17.336,-17.335 l 0,0 85.328,0 c 9.562,0 17.336,7.773 17.336,17.335 l 0,0 0,85.329 c 0,9.554 -7.774,17.334 -17.336,17.334 l 0,0 -85.328,0 z m -13.336,-102.663 0,85.329 c 0,7.351 5.984,13.336 13.336,13.336 l 0,0 85.328,0 c 7.351,0 13.336,-5.985 13.336,-13.336 l 0,0 0,-85.329 c 0,-7.351 -5.985,-13.335 -13.336,-13.335 l 0,0 -85.328,0 c -7.352,0 -13.336,5.984 -13.336,13.335"
+ style="fill:url(#linearGradient3943);fill-opacity:1;stroke:none"
+ id="path1780-1" />
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g1820-4"
+ transform="translate(99.772903,299.7866)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c -2.18,-0.91 -2.281,-0.98 -4.141,-2.281 -0.148,-0.223 -0.613,-2.258 1.102,-3.602 2.082,-1.633 7.559,-3.285 15.098,-3.285 4.445,0 11.136,0.598 17.898,3.434 l -0.129,0.882 c -3.148,-0.57 -6.539,-0.843 -10.34,-0.843 -5.386,0 -10.515,0.539 -16.183,1.187 -2.727,0.309 -4.086,0.895 -4.282,1.836 -0.148,0.692 0.414,1.289 0.852,1.641 -0.07,0.281 0.02,0.633 0.117,1 0,0.008 0,0.023 0.008,0.031 m 12.059,-9.969 c -6.692,0 -12.957,1.391 -15.59,3.457 -1.414,1.106 -1.586,2.551 -1.567,3.317 0.016,0.601 0.18,1.343 0.5,1.57 2.02,1.414 2.067,1.437 4.754,2.539 L 0.391,0.965 C 0.543,0.965 0.68,0.898 0.773,0.781 0.961,0.539 0.879,0.215 0.766,-0.23 0.719,-0.406 0.633,-0.734 0.648,-0.836 0.641,-0.766 0.543,-0.668 0.434,-0.668 l 0.308,-0.73 c -0.422,-0.243 -1.008,-0.766 -0.937,-1.11 0.039,-0.191 0.422,-0.844 3.593,-1.211 5.641,-0.64 10.743,-1.179 16.09,-1.179 3.918,0 7.383,0.296 10.598,0.906 l 0.469,-0.336 0.242,-1.594 -0.242,-0.426 C 23.57,-9.34 16.641,-9.969 12.059,-9.969"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1822-3" />
+ </g>
+ <g
+ id="g1824-2"
+ transform="translate(100.3159,298.73581)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 0,0 -3.941,-2.289 2.809,-3.063 8.175,-0.933 17.8,-1.976 26.808,-0.269 l 0.238,-1.598 c -13.5,-5.785 -29.367,-3.609 -33.687,-0.215 -2.016,1.586 -1.367,4.043 -1.078,4.243 2,1.398 2,1.398 4.672,2.5 C 0.359,1.84 -0.801,-0.223 0,0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1826-2" />
+ </g>
+ <g
+ id="g1828-6"
+ transform="translate(97.741699,311.24749)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c -0.293,-0.156 -0.641,-0.32 -1.016,-0.492 -2.539,-1.18 -4.589,-2.36 -3.949,-4.93 0.457,-1.84 6.442,-3.797 16.621,-3.797 7.43,0 15.282,1.086 22.149,3.059 l -0.121,0.84 c -4.723,-0.883 -9.606,-1.313 -14.914,-1.313 -6.184,0 -11.832,0.586 -16.372,1.055 -2.457,0.25 -3.785,0.871 -4.062,1.89 C -2,-2.477 -0.641,-1.289 -0.23,-0.965 -0.098,-0.594 -0.016,-0.223 0,0 m 11.656,-10.016 c -8.113,0 -16.64,1.36 -17.398,4.399 -0.852,3.422 2.304,4.883 4.39,5.851 0.383,0.18 0.739,0.344 1.032,0.5 C 0.094,0.961 0.461,0.898 0.656,0.617 0.992,0.133 0.645,-0.922 0.477,-1.352 L 0.344,-1.531 c -0.383,-0.285 -1.43,-1.25 -1.239,-1.946 0.102,-0.367 0.676,-1.031 3.372,-1.304 C 7,-5.25 12.629,-5.832 18.77,-5.832 c 5.41,0 10.371,0.449 15.171,1.371 l 0.473,-0.332 0.234,-1.598 -0.281,-0.441 c -7.023,-2.055 -15.09,-3.184 -22.711,-3.184"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1830-5" />
+ </g>
+ <g
+ id="g1832-4"
+ transform="translate(97.847199,310.0366)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 0,0 -4.426,-3.273 2.332,-3.969 8.734,-0.906 19.641,-1.969 31.578,0.328 l 0.238,-1.593 c -18.253,-5.344 -38.582,-3.18 -39.605,0.925 -0.922,3.7 3.383,4.899 5.219,5.903 C 0.613,2.063 0.246,0.641 0,0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1834-7" />
+ </g>
+ <g
+ id="g1836-0"
+ transform="translate(136.40581,358.5717)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c -0.09,0 -0.25,-0.031 -0.512,-0.18 -0.707,-0.402 -1.515,-0.84 -2.394,-1.312 -6.344,-3.43 -16.961,-9.168 -18.367,-16.887 -0.633,-3.465 0.656,-7.07 3.828,-10.726 2.808,-3.231 0.652,-6.844 -0.633,-9 l -0.242,-0.407 c -0.328,-0.562 -0.446,-0.922 -0.481,-1.148 1.52,0.879 6.508,4.047 7.524,8.23 0.461,1.907 0.035,3.801 -1.27,5.637 l -0.687,0.957 c -2.258,3.137 -4.207,5.84 -3.532,9.004 0.86,4.023 5.973,8.508 17.082,14.969 C 0.32,-0.574 0.273,-0.207 0.141,-0.059 0.109,-0.023 0.074,0 0,0 m -18.871,-40.613 -0.324,0.183 -0.11,-0.136 c -0.234,0.187 -0.679,0.804 0.293,2.461 l 0.246,0.41 c 1.25,2.097 3.145,5.269 0.719,8.066 -3.34,3.844 -4.691,7.68 -4.016,11.391 1.477,8.101 12.305,13.953 18.774,17.449 0.875,0.473 1.68,0.91 2.383,1.305 0.699,0.402 1.273,0.371 1.644,-0.043 0.469,-0.524 0.375,-1.508 0.364,-1.618 L 0.906,-1.449 c -10.879,-6.309 -16.086,-10.797 -16.89,-14.555 -0.602,-2.812 1.164,-5.262 3.398,-8.363 l 0.688,-0.961 c 1.445,-2.035 1.914,-4.152 1.398,-6.293 -1.281,-5.281 -8.082,-8.844 -8.371,-8.992"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1838-3" />
+ </g>
+ <g
+ id="g1840-7"
+ transform="translate(118.6597,329.2006)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 2.793,-3.211 0.277,-6.891 -0.918,-8.938 -0.937,-1.597 -0.391,-1.945 -0.391,-1.945 0,0 12.641,6.524 6.832,14.696 -5.421,7.617 -9.574,11.402 12.926,24.457 0,0 0.242,2.207 -1.414,1.269 C 8.871,24.93 -13.129,15.133 0,0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1842-9" />
+ </g>
+ <g
+ id="g1844-3"
+ transform="translate(90.905807,292.3256)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c -4.941,-0.07 -14.234,-4.152 -14.438,-6.926 -0.078,-1.09 1.547,-1.957 4.571,-2.449 10.109,-1.641 20.023,-2.469 29.476,-2.469 20.106,0 34.25,3.938 36.305,7.746 0.219,0.403 0.289,0.793 0.203,1.168 -0.676,-0.711 -2.32,-1.84 -6.316,-3.054 -6.61,-2 -21.028,-3.454 -34.289,-3.454 -10.922,0 -19.16,0.969 -23.196,2.719 -0.918,0.403 -1.355,0.91 -1.293,1.508 0.204,2.047 6.704,3.531 6.766,3.547 1.633,0.351 2.777,0.41 3.336,0.414 0.055,0.328 0,0.617 -0.16,0.836 C 0.773,-0.148 0.43,0 0,0 m 19.609,-12.648 0,0 c -9.492,0 -19.453,0.835 -29.601,2.484 -3.594,0.582 -5.36,1.691 -5.242,3.297 0.257,3.508 10.101,7.594 15.195,7.664 0.734,0 1.305,-0.262 1.652,-0.738 0.356,-0.497 0.43,-1.004 0.207,-1.696 l -0.41,-0.129 -0.238,0 c -0.512,0 -1.61,-0.195 -3.211,-0.539 -2.414,-0.519 -6.055,-2.011 -6.145,-2.914 -0.019,-0.199 0.286,-0.496 0.821,-0.726 3.933,-1.715 12.058,-2.676 22.875,-2.676 13.191,0 27.511,1.432 34.058,3.412 5.657,1.719 6.231,3.202 6.235,3.218 l 0.718,0.105 c 0.54,-0.817 0.571,-1.717 0.094,-2.592 -2.137,-3.961 -15.836,-8.17 -37.008,-8.17"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1846-0" />
+ </g>
+ <g
+ id="g1848-9"
+ transform="translate(147.09331,290.21631)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 0,0 -0.367,-1.629 -6.5,-3.492 -11.664,-3.531 -46.965,-5.203 -57.211,-0.75 -3.68,1.605 3.227,3.828 5.398,4.297 2.266,0.484 3.563,0.398 3.563,0.398 0.375,1.141 -0.242,2.07 -1.469,2.055 C -63.281,2.406 -78.988,-5.57 -66.117,-7.664 -24.926,-14.34 3.961,-6.043 0,0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1850-0" />
+ </g>
+ <g
+ id="g1852-7"
+ transform="translate(101.40581,322.55999)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 -0.133,0 c -2.879,0 -10.93,-1.609 -16.5,-4.305 -0.695,-0.336 -0.59,-0.871 -0.383,-1.672 0.055,-0.214 0.094,-0.351 0.102,-0.484 0.086,-1.477 7.898,-3.043 20.367,-3.043 9.969,0 19.508,1.014 26.188,2.764 1.078,0.742 2.308,1.913 3.187,2.8 C 30.172,-4.851 24.617,-6.55 19.008,-7.023 13.605,-7.476 7.953,-7.724 3.09,-7.724 c -3.746,0 -6.848,0.153 -8.981,0.434 -3.007,0.406 -4.371,1 -4.418,1.938 -0.105,2.059 7.961,4.188 10.801,4.872 0.059,0.234 0.094,0.355 -0.019,0.523 C 0.398,0.148 0.242,0 0,0 m 3.453,-10.281 c -2.14,0 -20.953,0.109 -21.164,3.82 -0.004,0.102 -0.043,0.231 -0.082,0.383 -0.168,0.664 -0.527,2.047 0.813,2.695 5.73,2.774 13.761,4.352 16.789,4.578 0.777,0.075 1.152,-0.25 1.324,-0.504 0.43,-0.628 0.086,-1.55 0.043,-1.656 L 0.898,-1.203 c -5.066,-1.203 -10.457,-3.141 -10.406,-4.11 0,-0.023 0.074,-0.695 3.727,-1.179 2.093,-0.281 5.164,-0.43 8.871,-0.43 4.84,0 10.473,0.25 15.848,0.699 7.609,0.641 15.132,3.586 15.207,3.614 l 0.441,-0.637 C 34.484,-3.359 32.035,-6.066 30.039,-7.43 L 29.914,-7.484 C 23.164,-9.262 13.52,-10.281 3.453,-10.281"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1854-4" />
+ </g>
+ <g
+ id="g1856-9"
+ transform="translate(102.2104,321.7436)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 0,0 -18.754,-4.457 -6.641,-6.074 5.114,-0.684 15.313,-0.528 24.809,0.269 7.762,0.653 15.316,3.645 15.316,3.645 0,0 -2.496,-2.774 -4.476,-4.125 -16.664,-4.383 -46.906,-3.141 -47.125,0.664 -0.031,0.547 -0.821,2.055 0.508,2.695 5.699,2.758 13.75,4.321 16.64,4.539 C 0.688,1.738 0,0 0,0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1858-7" />
+ </g>
+ <g
+ id="g1860-7"
+ transform="translate(135.56979,302.0444)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 -0.367,0.68 c 0.09,0.086 0.242,0.258 0.281,0.359 L 0.273,0.898 c 11.25,3.071 13.993,7.801 14.618,10.368 0.609,2.5 -0.219,5.004 -2.282,6.867 -2.695,2.445 -6.703,3.133 -10.48,1.812 -0.098,-0.039 -0.152,-0.078 -0.16,-0.101 -0.024,-0.125 0.164,-0.418 0.375,-0.656 0.328,0.109 0.984,0.304 2.019,0.523 3.262,0.687 6.711,-0.977 7.68,-3.695 C 12.742,14.051 12.992,8.766 0.234,2.133 L -0.133,2.844 C 12.066,9.184 11.918,13.98 11.289,15.75 10.379,18.301 7.078,19.461 4.527,18.93 3.066,18.621 2.391,18.355 2.383,18.352 L 1.961,18.43 c -0.152,0.14 -0.914,0.886 -0.773,1.578 0.046,0.219 0.203,0.523 0.675,0.687 4.051,1.43 8.371,0.672 11.285,-1.968 2.282,-2.071 3.204,-4.856 2.52,-7.649 C 14.992,8.301 12.055,3.168 0,0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1862-4" />
+ </g>
+ <g
+ id="g1864-5"
+ transform="translate(135.6245,304.5366)">
+ <path
+ inkscape:connector-curvature="0"
+ d="M 0,0 C 19.359,10.059 10.645,18.129 4.391,16.828 2.867,16.508 2.18,16.234 2.18,16.234 c 0,0 -1.321,1.211 -0.239,1.594 12.364,4.344 23.762,-13.133 -2.097,-19.937 0,0 0.297,0.269 0.39,0.511"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1866-7" />
+ </g>
+ <g
+ id="g1868-4"
+ transform="translate(124.9565,376.80999)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 1.715,-10.453 -5.746,-16.297 -12.973,-21.953 -3.843,-3.008 -7.468,-5.848 -9.785,-9.324 -4.574,-6.864 2.379,-14.461 10.973,-22.301 -0.016,0.066 -0.031,0.137 -0.043,0.203 -0.145,0.656 -0.27,1.227 -0.836,2.043 -0.41,0.598 -0.84,1.199 -1.277,1.809 -4.758,6.636 -10.149,14.16 2.75,24.351 8.101,6.399 12.39,12.633 12.746,18.531 C 1.738,-3.633 0.801,-1.359 0,0 m -11.215,-55.172 c -9.359,8.438 -17.332,16.649 -12.207,24.336 2.387,3.586 6.234,6.602 9.957,9.512 7.438,5.824 15.133,11.847 12.305,22.965 l 0.672,0.379 c 0.125,-0.129 3.164,-3.231 2.843,-8.684 -0.359,-6.145 -4.75,-12.582 -13.046,-19.133 -12.305,-9.719 -7.375,-16.601 -2.602,-23.262 0.438,-0.613 0.875,-1.218 1.289,-1.82 0.652,-0.945 0.801,-1.613 0.957,-2.324 0.098,-0.453 0.203,-0.922 0.465,-1.512 l -0.633,-0.457 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1870-4" />
+ </g>
+ <g
+ id="g1872-9"
+ transform="translate(124.18311,378.5444)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 0,0 10.723,-10.723 -10.168,-27.219 -13.789,-10.89 -6.187,-18.664 -1.391,-25.621 1.032,-1.496 0.711,-2.246 1.383,-3.769 -9.781,8.82 -16.961,16.586 -12.14,23.82 C -15.25,-22.18 4.332,-17.031 0,0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1874-2" />
+ </g>
+ <g
+ id="g1876-2"
+ transform="translate(89.905807,281.85381)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 0.625,-0.367 3.828,-1.914 14.234,-2.582 3.352,-0.215 6.875,-0.324 10.481,-0.324 16.652,0 36.281,2.457 36.89,9.375 -0.05,0.344 -0.144,0.57 -0.199,0.609 C 61.281,6.906 61.141,6.781 60.977,6.641 59.297,5.172 55.371,1.727 46.723,0.102 41.859,-0.813 35.746,-1.277 28.555,-1.277 17.664,-1.277 6.852,-0.199 0.363,0.813 0.199,0.805 0.16,0.789 0.141,0.762 0.016,0.617 -0.012,0.258 0,0 m 24.719,-4.094 -0.004,0 c -3.621,0 -7.164,0.305 -10.527,0.52 -12.211,0.781 -14.719,2.859 -14.821,2.945 l -0.14,0.295 c -0.016,0.105 -0.141,1.075 0.304,1.595 0.235,0.261 0.551,0.391 0.957,0.328 6.457,-1.007 17.223,-2.072 28.067,-2.072 7.14,0 13.203,0.464 18.019,1.367 8.434,1.59 12.246,4.927 13.871,6.357 0.172,0.148 0.321,0.278 0.45,0.383 0.187,0.156 0.378,0.923 0.574,0.923 0.492,0 0.828,-0.641 0.937,-0.641 l -0.031,0 0.031,-0.968 C 61.828,-0.547 42.559,-4.094 24.719,-4.094"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1878-6" />
+ </g>
+ <g
+ id="g1880-7"
+ transform="translate(104.1167,278.87331)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 18.582,-1.188 47.117,0.664 47.797,9.457 0,0 -0.149,1.434 -0.859,0.844 C 45.516,9.117 41.82,5.238 32.438,3.473 18.891,0.926 -2.184,2.379 -13.785,4.188 -14.828,4.348 -14.59,2.754 -14.59,2.754 -14.59,2.754 -12.219,0.785 0,0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1882-9" />
+ </g>
+ <g
+ id="g1884-1"
+ transform="translate(100.07761,300.3334)">
+ <path
+ inkscape:connector-curvature="0"
+ d="M 0,0 C 0,0 -3.941,-2.289 2.809,-3.063 10.984,-4 15.168,-3.867 24.18,-2.164 c 0,0 2.367,-1.484 5.675,-2.766 C 9.648,-13.594 -15.867,-4.434 0,0"
+ style="fill:#5382a1;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1886-9" />
+ </g>
+ <g
+ id="g1888-1"
+ transform="translate(97.608902,311.63031)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 0,0 -4.422,-3.273 2.336,-3.969 8.734,-0.902 15.633,-0.976 27.57,1.321 0,0 1.649,-1.672 4.242,-2.586 C 9.727,-12.379 -17.48,-5.797 0,0"
+ style="fill:#5382a1;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1890-8" />
+ </g>
+ <g
+ id="g1892-5"
+ transform="translate(118.4214,330.79831)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 4.98,-5.73 -1.309,-10.887 -1.309,-10.887 0,0 12.641,6.524 6.832,14.696 -5.421,7.617 -9.574,11.406 12.93,24.461 0,0 -35.328,-8.829 -18.453,-28.27"
+ style="fill:#f8981d;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1894-5" />
+ </g>
+ <g
+ id="g1896-7"
+ transform="translate(145.14011,291.9819)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 0,0 2.922,-2.406 -3.215,-4.27 -11.66,-3.531 -48.535,-4.597 -58.777,-0.14 -3.68,1.605 3.226,3.824 5.398,4.293 2.262,0.488 3.559,0.398 3.559,0.398 -4.098,2.883 -26.473,-5.664 -11.367,-8.113 C -23.211,-14.508 10.684,-4.824 0,0"
+ style="fill:#5382a1;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1898-7" />
+ </g>
+ <g
+ id="g1900-1"
+ transform="translate(101.9761,323.34131)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 0,0 -18.758,-4.457 -6.645,-6.078 5.114,-0.68 15.313,-0.524 24.809,0.273 7.766,0.649 15.555,2.047 15.555,2.047 0,0 -2.735,-1.176 -4.711,-2.527 -19.051,-5.012 -55.84,-2.676 -45.25,2.441 C -7.281,0.492 0,0 0,0"
+ style="fill:#5382a1;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1902-4" />
+ </g>
+ <g
+ id="g1904-9"
+ transform="translate(135.6245,304.5366)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 19.359,10.059 10.406,19.727 4.156,18.422 -1.527,-0.32 -2.215,-0.594 -2.215,-0.594 0,0 0.571,0.895 1.653,1.274 12.367,4.347 21.871,-12.813 -3.985,-19.614 0,0 0.297,0.27 0.391,0.512"
+ style="fill:#5382a1;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1906-4" />
+ </g>
+ <g
+ id="g1908-6"
+ transform="translate(123.94479,380.142)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 0,0 10.723,-10.723 -10.168,-27.223 -16.75,-13.226 -3.824,-20.769 -0.004,-29.39 -9.781,8.824 -16.961,16.59 -12.144,23.82 C -15.25,-22.18 4.332,-17.035 0,0"
+ style="fill:#f8981d;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1910-0" />
+ </g>
+ <g
+ id="g1912-6"
+ transform="translate(103.8784,277.2709)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0,0 c 18.582,-1.188 47.121,0.664 47.801,9.453 0,0 -1.301,-3.336 -15.36,-5.98 C 16.578,0.488 -2.988,0.836 -14.59,2.75 -14.59,2.75 -12.215,0.781 0,0"
+ style="fill:#5382a1;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path1914-4" />
+ </g>
+ <g
+ id="g3975">
+ <g
+ id="g3977" />
+ <g
+ style="fill:url(#linearGradient3933);fill-opacity:1"
+ id="g3979">
+ <g
+ id="g3981"
+ clip-path="url(#clipPath1748)"
+ style="opacity:0.69999701;fill:url(#linearGradient3955);fill-opacity:1">
+ <g
+ style="fill:url(#linearGradient3953);fill-opacity:1"
+ id="g3983">
+ <g
+ style="fill:url(#linearGradient3951);fill-opacity:1"
+ id="g3985"
+ clip-path="url(#clipPath1752)">
+ <g
+ style="fill:url(#linearGradient3949);fill-opacity:1"
+ id="g3987">
+ <g
+ style="fill:url(#linearGradient3947);fill-opacity:1"
+ id="g3989">
+ <g
+ style="fill:url(#linearGradient3945);fill-opacity:1"
+ id="g3991"
+ clip-path="url(#clipPath1756)" />
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/resources/multimc/scalable/proxy.svg b/resources/multimc/scalable/proxy.svg
new file mode 100644
index 00000000..55ee6f93
--- /dev/null
+++ b/resources/multimc/scalable/proxy.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="64"
+ height="64"
+ id="svg2">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient3931">
+ <stop
+ id="stop3933"
+ style="stop-color:#ffffff;stop-opacity:0"
+ offset="0" />
+ <stop
+ id="stop3939"
+ style="stop-color:#ffffff;stop-opacity:0.18039216"
+ offset="0.69999999" />
+ <stop
+ id="stop3935"
+ style="stop-color:#ffffff;stop-opacity:0.3611111"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3900">
+ <stop
+ id="stop3902"
+ style="stop-color:#f6f6f6;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3904"
+ style="stop-color:#494949;stop-opacity:1"
+ offset="0.75714284" />
+ <stop
+ id="stop3906"
+ style="stop-color:#2c2c2c;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3808">
+ <stop
+ id="stop3810"
+ style="stop-color:#333333;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3812"
+ style="stop-color:#c8c8c8;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3030">
+ <stop
+ id="stop3032"
+ style="stop-color:#36c536;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3038"
+ style="stop-color:#1f721f;stop-opacity:1"
+ offset="0.75714284" />
+ <stop
+ id="stop3034"
+ style="stop-color:#134513;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <radialGradient
+ cx="24"
+ cy="16"
+ r="16.375"
+ fx="24"
+ fy="16"
+ id="radialGradient3036"
+ xlink:href="#linearGradient3030"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1497507,1.7246237,-1.4656488,0.97709922,19.856365,-41.024557)" />
+ <linearGradient
+ x1="30"
+ y1="1033.8622"
+ x2="34"
+ y2="1033.8622"
+ id="linearGradient3824"
+ xlink:href="#linearGradient3808"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.5,0,0,1,-16,0)" />
+ <linearGradient
+ x1="32"
+ y1="1043.3622"
+ x2="32"
+ y2="1039.3622"
+ id="linearGradient3834"
+ xlink:href="#linearGradient3808"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.82142857,0,0,1.500001,6.7142857,-522.68214)" />
+ <radialGradient
+ cx="30.724609"
+ cy="1039.813"
+ r="3"
+ fx="30.724609"
+ fy="1039.813"
+ id="radialGradient3844"
+ xlink:href="#linearGradient3900"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.9033547,2.9862934,-4.666644,3.3333362,4792.8997,-2518.4369)" />
+ <radialGradient
+ cx="30.724609"
+ cy="1039.813"
+ r="3"
+ fx="30.724609"
+ fy="1039.813"
+ id="radialGradient3852"
+ xlink:href="#linearGradient3900"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.5191507,2.9862959,-4.0491019,3.333339,4186.8847,-2518.44)" />
+ <radialGradient
+ cx="30.724609"
+ cy="1039.813"
+ r="3"
+ fx="30.724609"
+ fy="1039.813"
+ id="radialGradient3857"
+ xlink:href="#linearGradient3900"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-2.5191507,2.9863064,4.0491022,3.3333507,-4122.8849,-2518.4524)" />
+ <radialGradient
+ cx="31.964285"
+ cy="25.25"
+ r="19.25"
+ fx="31.964285"
+ fy="25.25"
+ id="radialGradient3937"
+ xlink:href="#linearGradient3931"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.97517967,0.03814675,-0.04025373,1.0289295,1.809772,-1.9498045)" />
+ </defs>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="translate(0,-988.36218)"
+ id="layer1">
+ <rect
+ width="6"
+ height="13.000005"
+ rx="0.70710504"
+ ry="0.70710492"
+ x="29"
+ y="1027.3622"
+ id="rect3028"
+ style="color:#000000;fill:url(#linearGradient3824);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.75;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ width="46"
+ height="6.0000076"
+ rx="0.70710504"
+ ry="0.70710492"
+ x="10"
+ y="1036.3622"
+ id="rect2991"
+ style="color:#000000;fill:url(#linearGradient3834);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.75;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ width="32"
+ height="32"
+ rx="0.70710504"
+ ry="0.70710492"
+ x="16"
+ y="8"
+ transform="translate(0,988.36218)"
+ id="rect2997"
+ style="color:#000000;fill:url(#radialGradient3036);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.75;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ width="6"
+ height="6"
+ x="23"
+ y="1003.3622"
+ id="rect3001"
+ style="color:#000000;fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ width="6"
+ height="6"
+ x="35"
+ y="1003.3622"
+ id="rect3003"
+ style="color:#000000;fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ d="m 29,1009.3622 0,3 -3,0 0,9 3,0 0,-3 6,0 0,3 3,0 0,-9 -3,0 0,-3 -6,0 z"
+ id="rect3005"
+ style="color:#000000;fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ width="6"
+ height="2.9999955"
+ x="29"
+ y="1009.3622"
+ id="rect3011"
+ style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ width="3"
+ height="2.9999955"
+ x="26"
+ y="1012.3622"
+ id="rect3013"
+ style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ width="3"
+ height="2.9999955"
+ x="35"
+ y="1012.3622"
+ id="rect3015"
+ style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ d="m 35,1003.3622 0,6 3,0 0,-3 3,0 0,-3 -3,0 -3,0 z"
+ id="rect3017"
+ style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ d="m 23,1003.3622 0,3 0,3 3,0 0,-3 3,0 0,-3 -3,0 -3,0 z"
+ id="rect3021"
+ style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ width="14"
+ height="8.0000048"
+ rx="0.70710504"
+ ry="0.70710492"
+ x="25"
+ y="1035.3622"
+ id="rect3836"
+ style="color:#000000;fill:url(#radialGradient3844);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.76376289;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ d="m 51,1035.3622 5,0 6.073683,4 -6.073683,4 -5,0 c -0.59482,0 -1.073683,-0.4205 -1.073683,-0.9428 l 0,-6.1144 c 0,-0.5223 0.478876,-0.9428 1.073683,-0.9428 z"
+ id="rect3850"
+ style="color:#000000;fill:url(#radialGradient3852);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.71143585;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ d="m 13,1035.3622 -5,0 -6.0736829,4 6.0736829,4 5,0 c 0.59482,0 1.073683,-0.4205 1.073683,-0.9428 l 0,-6.1144 c 0,-0.5223 -0.478877,-0.9428 -1.073683,-0.9428 z"
+ id="path3855"
+ style="color:#000000;fill:url(#radialGradient3857);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.71143711;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ width="38"
+ height="38"
+ rx="0.70710504"
+ ry="0.70710492"
+ x="13"
+ y="5"
+ transform="translate(0,988.36218)"
+ id="rect3927"
+ style="color:#000000;fill:url(#radialGradient3937);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+</svg>
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 3b2b8b74..d56988e0 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -22,6 +22,7 @@ endmacro()
# Tests START #
add_unit_test(pathutils tst_pathutils.cpp)
+add_unit_test(gradlespecifier tst_gradlespecifier.cpp)
add_unit_test(userutils tst_userutils.cpp)
add_unit_test(inifile tst_inifile.cpp)
add_unit_test(UpdateChecker tst_UpdateChecker.cpp)
diff --git a/tests/tst_gradlespecifier.cpp b/tests/tst_gradlespecifier.cpp
new file mode 100644
index 00000000..69dd54f7
--- /dev/null
+++ b/tests/tst_gradlespecifier.cpp
@@ -0,0 +1,77 @@
+#include <QTest>
+#include "TestUtil.h"
+
+#include "logic/minecraft/GradleSpecifier.h"
+
+class GradleSpecifierTest : public QObject
+{
+ Q_OBJECT
+private
+slots:
+ void initTestCase()
+ {
+
+ }
+ void cleanupTestCase()
+ {
+
+ }
+
+ void test_Positive_data()
+ {
+ QTest::addColumn<QString>("through");
+
+ QTest::newRow("3 parter") << "org.gradle.test.classifiers:service:1.0";
+ QTest::newRow("classifier") << "org.gradle.test.classifiers:service:1.0:jdk15";
+ QTest::newRow("jarextension") << "org.gradle.test.classifiers:service:1.0@jar";
+ QTest::newRow("jarboth") << "org.gradle.test.classifiers:service:1.0:jdk15@jar";
+ QTest::newRow("packxz") << "org.gradle.test.classifiers:service:1.0:jdk15@jar.pack.xz";
+ }
+ void test_Positive()
+ {
+ QFETCH(QString, through);
+
+ QString converted = GradleSpecifier(through);
+
+ QCOMPARE(converted, through);
+ }
+
+ void test_Path_data()
+ {
+ QTest::addColumn<QString>("spec");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("3 parter") << "group.id:artifact:1.0" << "group/id/artifact/1.0/artifact-1.0.jar";
+ QTest::newRow("doom") << "id.software:doom:1.666:demons@wad" << "id/software/doom/1.666/doom-1.666-demons.wad";
+ }
+ void test_Path()
+ {
+ QFETCH(QString, spec);
+ QFETCH(QString, expected);
+
+ QString converted = GradleSpecifier(spec).toPath();
+
+ QCOMPARE(converted, expected);
+ }
+ void test_Negative_data()
+ {
+ QTest::addColumn<QString>("input");
+
+ QTest::newRow("too many :") << "org:gradle.test:class:::ifiers:service:1.0::";
+ QTest::newRow("nonsense") << "I like turtles";
+ QTest::newRow("empty string") << "";
+ QTest::newRow("missing version") << "herp.derp:artifact";
+ }
+ void test_Negative()
+ {
+ QFETCH(QString, input);
+
+ GradleSpecifier spec(input);
+ QVERIFY(!spec.valid());
+ QCOMPARE(spec.operator QString(), QString("INVALID"));
+ }
+};
+
+QTEST_GUILESS_MAIN_MULTIMC(GradleSpecifierTest)
+
+#include "tst_gradlespecifier.moc"