summaryrefslogtreecommitdiffstats
path: root/gui
diff options
context:
space:
mode:
Diffstat (limited to 'gui')
-rw-r--r--gui/ConsoleWindow.cpp122
-rw-r--r--gui/ConsoleWindow.h6
-rw-r--r--gui/MainWindow.cpp229
-rw-r--r--gui/MainWindow.h17
-rw-r--r--gui/dialogs/AboutDialog.cpp19
-rw-r--r--gui/dialogs/AboutDialog.ui150
-rw-r--r--gui/dialogs/InstanceSettings.ui18
-rw-r--r--gui/dialogs/SettingsDialog.cpp123
-rw-r--r--gui/dialogs/SettingsDialog.h19
-rw-r--r--gui/dialogs/SettingsDialog.ui333
-rw-r--r--gui/widgets/ModListView.cpp20
11 files changed, 895 insertions, 161 deletions
diff --git a/gui/ConsoleWindow.cpp b/gui/ConsoleWindow.cpp
index e640d261..54a74bde 100644
--- a/gui/ConsoleWindow.cpp
+++ b/gui/ConsoleWindow.cpp
@@ -19,12 +19,14 @@
#include <QScrollBar>
#include <QMessageBox>
+#include <QSystemTrayIcon>
#include <gui/Platform.h>
#include <gui/dialogs/CustomMessageBox.h>
#include <gui/dialogs/ProgressDialog.h>
#include "logic/net/PasteUpload.h"
+#include "logic/icons/IconList.h"
ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent)
: QMainWindow(parent), ui(new Ui::ConsoleWindow), proc(mcproc)
@@ -35,14 +37,28 @@ ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent)
SLOT(write(QString, MessageLevel::Enum)));
connect(mcproc, SIGNAL(ended(BaseInstance *, int, QProcess::ExitStatus)), this,
SLOT(onEnded(BaseInstance *, int, QProcess::ExitStatus)));
- connect(mcproc, SIGNAL(prelaunch_failed(BaseInstance*,int,QProcess::ExitStatus)), this,
+ connect(mcproc, SIGNAL(prelaunch_failed(BaseInstance *, int, QProcess::ExitStatus)), this,
SLOT(onEnded(BaseInstance *, int, QProcess::ExitStatus)));
- connect(mcproc, SIGNAL(launch_failed(BaseInstance*)), this,
- SLOT(onLaunchFailed(BaseInstance*)));
+ connect(mcproc, SIGNAL(launch_failed(BaseInstance *)), this,
+ SLOT(onLaunchFailed(BaseInstance *)));
- restoreState(QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowState").toByteArray()));
- restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowGeometry").toByteArray()));
+ restoreState(
+ QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowState").toByteArray()));
+ restoreGeometry(
+ QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowGeometry").toByteArray()));
+ QString iconKey = proc->instance()->iconKey();
+ QString name = proc->instance()->name();
+ auto icon = MMC->icons()->getIcon(iconKey);
+ setWindowIcon(icon);
+ m_trayIcon = new QSystemTrayIcon(icon, this);
+ QString consoleTitle = tr("Console window for ") + name;
+ m_trayIcon->setToolTip(consoleTitle);
+ setWindowTitle(consoleTitle);
+
+ connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
+ SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
+ m_trayIcon->show();
if (mcproc->instance()->settings().get("ShowConsole").toBool())
{
show();
@@ -55,13 +71,26 @@ ConsoleWindow::~ConsoleWindow()
delete ui;
}
+void ConsoleWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
+{
+ switch (reason)
+ {
+ case QSystemTrayIcon::Trigger:
+ {
+ toggleConsole();
+ }
+ default:
+ return;
+ }
+}
+
void ConsoleWindow::writeColor(QString text, const char *color)
{
// append a paragraph
QString newtext;
newtext += "<span style=\"";
{
- if(color)
+ if (color)
newtext += QString("color:") + color + ";";
newtext += "font-family: monospace;";
}
@@ -76,16 +105,17 @@ void ConsoleWindow::write(QString data, MessageLevel::Enum mode)
QScrollBar *bar = ui->text->verticalScrollBar();
int max_bar = bar->maximum();
int val_bar = bar->value();
- if(m_scroll_active)
- {
- if(m_last_scroll_value > val_bar)
- m_scroll_active = false;
- }
- else
+ if(isVisible())
{
- m_scroll_active = val_bar == max_bar;
+ if (m_scroll_active)
+ {
+ m_scroll_active = (max_bar - val_bar) <= 1;
+ }
+ else
+ {
+ m_scroll_active = val_bar == max_bar;
+ }
}
-
if (data.endsWith('\n'))
data = data.left(data.length() - 1);
QStringList paragraphs = data.split('\n');
@@ -114,11 +144,14 @@ void ConsoleWindow::write(QString data, MessageLevel::Enum mode)
else
while (iter.hasNext())
writeColor(iter.next());
- if(m_scroll_active)
+ if(isVisible())
{
- bar->setValue(bar->maximum());
+ if (m_scroll_active)
+ {
+ bar->setValue(bar->maximum());
+ }
+ m_last_scroll_value = bar->value();
}
- m_last_scroll_value = bar->value();
}
void ConsoleWindow::clear()
@@ -133,23 +166,50 @@ void ConsoleWindow::on_closeButton_clicked()
void ConsoleWindow::setMayClose(bool mayclose)
{
+ if(mayclose)
+ ui->closeButton->setText(tr("Close"));
+ else
+ ui->closeButton->setText(tr("Hide"));
m_mayclose = mayclose;
- if (mayclose)
- ui->closeButton->setEnabled(true);
+}
+
+void ConsoleWindow::toggleConsole()
+{
+ QScrollBar *bar = ui->text->verticalScrollBar();
+ if (isVisible())
+ {
+ int max_bar = bar->maximum();
+ int val_bar = m_last_scroll_value = bar->value();
+ m_scroll_active = (max_bar - val_bar) <= 1;
+ hide();
+ }
else
- ui->closeButton->setEnabled(false);
+ {
+ show();
+ if (m_scroll_active)
+ {
+ bar->setValue(bar->maximum());
+ }
+ else
+ {
+ bar->setValue(m_last_scroll_value);
+ }
+ }
}
void ConsoleWindow::closeEvent(QCloseEvent *event)
{
if (!m_mayclose)
- event->ignore();
+ {
+ toggleConsole();
+ }
else
{
MMC->settings()->set("ConsoleWindowState", saveState().toBase64());
MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
emit isClosing();
+ m_trayIcon->hide();
QMainWindow::closeEvent(event);
}
}
@@ -170,19 +230,26 @@ void ConsoleWindow::on_btnKillMinecraft_clicked()
void ConsoleWindow::onEnded(BaseInstance *instance, int code, QProcess::ExitStatus status)
{
+ bool peacefulExit = code == 0 && status != QProcess::CrashExit;
ui->btnKillMinecraft->setEnabled(false);
setMayClose(true);
if (instance->settings().get("AutoCloseConsole").toBool())
{
- if (code == 0 && status != QProcess::CrashExit)
+ if (peacefulExit)
{
this->close();
return;
}
}
- if(!isVisible())
+ /*
+ if(!peacefulExit)
+ {
+ m_trayIcon->showMessage(tr("Oh no!"), tr("Minecraft crashed!"), QSystemTrayIcon::Critical);
+ }
+ */
+ if (!isVisible())
show();
}
@@ -192,7 +259,7 @@ void ConsoleWindow::onLaunchFailed(BaseInstance *instance)
setMayClose(true);
- if(!isVisible())
+ if (!isVisible())
show();
}
@@ -200,10 +267,11 @@ void ConsoleWindow::on_btnPaste_clicked()
{
auto text = ui->text->toPlainText();
ProgressDialog dialog(this);
- PasteUpload* paste=new PasteUpload(this, text);
+ PasteUpload *paste = new PasteUpload(this, text);
dialog.exec(paste);
- if(!paste->successful())
+ if (!paste->successful())
{
- CustomMessageBox::selectable(this, "Upload failed", paste->failReason(), QMessageBox::Critical)->exec();
+ CustomMessageBox::selectable(this, "Upload failed", paste->failReason(),
+ QMessageBox::Critical)->exec();
}
}
diff --git a/gui/ConsoleWindow.h b/gui/ConsoleWindow.h
index 731c616c..9291320e 100644
--- a/gui/ConsoleWindow.h
+++ b/gui/ConsoleWindow.h
@@ -16,6 +16,7 @@
#pragma once
#include <QMainWindow>
+#include <QSystemTrayIcon>
#include "logic/MinecraftProcess.h"
namespace Ui
@@ -77,7 +78,8 @@ slots:
// failures)
void on_btnPaste_clicked();
-
+ void iconActivated(QSystemTrayIcon::ActivationReason);
+ void toggleConsole();
protected:
void closeEvent(QCloseEvent *);
@@ -87,4 +89,6 @@ private:
bool m_mayclose = true;
int m_last_scroll_value = 0;
bool m_scroll_active = true;
+ QSystemTrayIcon *m_trayIcon = nullptr;
+ int m_saved_offset = 0;
};
diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp
index 2b911b2c..d5cc1d44 100644
--- a/gui/MainWindow.cpp
+++ b/gui/MainWindow.cpp
@@ -77,6 +77,8 @@
#include "logic/news/NewsChecker.h"
+#include "logic/status/StatusChecker.h"
+
#include "logic/net/URLConstants.h"
#include "logic/BaseInstance.h"
@@ -92,13 +94,18 @@
#include "logic/assets/AssetsUtils.h"
#include "logic/assets/AssetsMigrateTask.h"
#include <logic/updater/UpdateChecker.h>
+#include <logic/updater/NotificationChecker.h>
#include <logic/tasks/ThreadTask.h>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
MultiMCPlatform::fixWM_CLASS(this);
ui->setupUi(this);
- setWindowTitle(QString("MultiMC %1").arg(MMC->version().toString()));
+
+ QString winTitle = QString("MultiMC 5 - Version %1").arg(MMC->version().toString());
+ if (!MMC->version().platform.isEmpty())
+ winTitle += " on " + MMC->version().platform;
+ setWindowTitle(winTitle);
// OSX magic.
// setUnifiedTitleAndToolBarOnMac(true);
@@ -165,6 +172,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
view->setFrameShape(QFrame::NoFrame);
view->setModel(proxymodel);
+ view->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(view, SIGNAL(customContextMenuRequested(const QPoint&)),
+ this, SLOT(showInstanceContextMenu(const QPoint&)));
+
ui->horizontalLayout->addWidget(view);
}
// The cat background
@@ -190,7 +201,27 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
connect(MMC->instances().get(), SIGNAL(dataIsInvalid()), SLOT(selectionBad()));
m_statusLeft = new QLabel(tr("No instance selected"), this);
+ m_statusRight = new QLabel(tr("No status available"), this);
+ m_statusRefresh = new QToolButton(this);
+ m_statusRefresh->setToolButtonStyle(Qt::ToolButtonIconOnly);
+ m_statusRefresh->setIcon(
+ QPixmap(":/icons/toolbar/refresh").scaled(16, 16, Qt::KeepAspectRatio));
+
statusBar()->addPermanentWidget(m_statusLeft, 1);
+ statusBar()->addPermanentWidget(m_statusRight, 0);
+ statusBar()->addPermanentWidget(m_statusRefresh, 0);
+
+ // Start status checker
+ {
+ connect(MMC->statusChecker().get(), &StatusChecker::statusLoaded, this, &MainWindow::updateStatusUI);
+ connect(MMC->statusChecker().get(), &StatusChecker::statusLoadingFailed, this, &MainWindow::updateStatusFailedUI);
+
+ connect(m_statusRefresh, &QAbstractButton::clicked, this, &MainWindow::reloadStatus);
+ connect(&statusTimer, &QTimer::timeout, this, &MainWindow::reloadStatus);
+ statusTimer.setSingleShot(true);
+
+ reloadStatus();
+ }
// Add "manage accounts" button, right align
QWidget *spacer = new QWidget();
@@ -226,17 +257,20 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
connect(MMC->accounts().get(), &MojangAccountList::listChanged, [this]
{ repopulateAccountsMenu(); });
- std::shared_ptr<MojangAccountList> accounts = MMC->accounts();
+ // Show initial account
+ activeAccountChanged();
+
+ auto accounts = MMC->accounts();
// TODO: Nicer way to iterate?
for (int i = 0; i < accounts->count(); i++)
{
- MojangAccountPtr account = accounts->at(i);
+ auto account = accounts->at(i);
if (account != nullptr)
{
auto job = new NetJob("Startup player skins: " + account->username());
- for (AccountProfile profile : account->profiles())
+ for (auto profile : account->profiles())
{
auto meta = MMC->metacache()->resolveEntry("skins", profile.name + ".png");
auto action = CacheDownload::make(
@@ -279,27 +313,13 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
// if automatic update checks are allowed, start one.
if (MMC->settings()->get("AutoUpdate").toBool())
on_actionCheckUpdate_triggered();
- }
- const QString currentInstanceId = MMC->settings()->get("SelectedInstance").toString();
- if (!currentInstanceId.isNull())
- {
- const QModelIndex index = MMC->instances()->getInstanceIndexById(currentInstanceId);
- if (index.isValid())
- {
- const QModelIndex mappedIndex = proxymodel->mapFromSource(index);
- view->setCurrentIndex(mappedIndex);
- }
- else
- {
- view->setCurrentIndex(proxymodel->index(0, 0));
- }
- }
- else
- {
- view->setCurrentIndex(proxymodel->index(0, 0));
+ connect(MMC->notificationChecker().get(), &NotificationChecker::notificationCheckFinished,
+ this, &MainWindow::notificationsChanged);
}
+ setSelectedInstanceById(MMC->settings()->get("SelectedInstance").toString());
+
// removing this looks stupid
view->setFocus();
}
@@ -311,6 +331,29 @@ MainWindow::~MainWindow()
delete drawer;
}
+void MainWindow::showInstanceContextMenu(const QPoint& pos)
+{
+ if(!view->indexAt(pos).isValid())
+ {
+ return;
+ }
+
+ QList<QAction *> actions = ui->instanceToolBar->actions();
+
+ // HACK: Filthy rename button hack because the instance view is getting rewritten anyway
+ QAction *actionRename;
+ actionRename = new QAction(tr("Rename"), this);
+ actionRename->setToolTip(ui->actionRenameInstance->toolTip());
+
+ connect(actionRename, SIGNAL(triggered(bool)), SLOT(on_actionRenameInstance_triggered()));
+
+ actions.replace(1, actionRename);
+
+ QMenu myMenu;
+ myMenu.addActions(actions);
+ myMenu.exec(view->mapToGlobal(pos));
+}
+
void MainWindow::repopulateAccountsMenu()
{
accountMenu->clear();
@@ -477,6 +520,63 @@ void MainWindow::updateNewsLabel()
}
}
+static QString convertStatus(const QString &status)
+{
+ if(status == "green") return "↑";
+ else if(status == "yellow") return "-";
+ else if(status == "red") return "↓";
+ else return "?";
+}
+
+void MainWindow::reloadStatus()
+{
+ MMC->statusChecker()->reloadStatus();
+ updateStatusUI();
+}
+
+static QString makeStatusString(const QMap<QString, QString> statuses)
+{
+ QString status = "";
+ status += "Web: " + convertStatus(statuses["minecraft.net"]);
+ status += " Account: " + convertStatus(statuses["account.mojang.com"]);
+ status += " Skins: " + convertStatus(statuses["skins.minecraft.net"]);
+ status += " Auth: " + convertStatus(statuses["authserver.mojang.com"]);
+ status += " Session: " + convertStatus(statuses["sessionserver.mojang.com"]);
+
+ return status;
+}
+
+void MainWindow::updateStatusUI()
+{
+ auto statusChecker = MMC->statusChecker();
+ auto statuses = statusChecker->getStatusEntries();
+
+ QString status = makeStatusString(statuses);
+ if(statusChecker->isLoadingStatus())
+ {
+ m_statusRefresh->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ m_statusRefresh->setText(tr("Loading..."));
+ }
+ else
+ {
+ m_statusRefresh->setToolButtonStyle(Qt::ToolButtonIconOnly);
+ m_statusRefresh->setText(tr(""));
+ }
+
+ m_statusRight->setText(status);
+
+ statusTimer.start(60 * 1000);
+}
+
+void MainWindow::updateStatusFailedUI()
+{
+ m_statusRight->setText(makeStatusString(QMap<QString, QString>()));
+ m_statusRefresh->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ m_statusRefresh->setText(tr("Failed."));
+
+ statusTimer.start(60 * 1000);
+}
+
void MainWindow::updateAvailable(QString repo, QString versionName, int versionId)
{
UpdateDialog dlg;
@@ -495,6 +595,63 @@ void MainWindow::updateAvailable(QString repo, QString versionName, int versionI
}
}
+QList<int> stringToIntList(const QString &string)
+{
+ QStringList split = string.split(',', QString::SkipEmptyParts);
+ QList<int> out;
+ for (int i = 0; i < split.size(); ++i)
+ {
+ out.append(split.at(i).toInt());
+ }
+ return out;
+}
+QString intListToString(const QList<int> &list)
+{
+ QStringList slist;
+ for (int i = 0; i < list.size(); ++i)
+ {
+ slist.append(QString::number(list.at(i)));
+ }
+ return slist.join(',');
+}
+void MainWindow::notificationsChanged()
+{
+ QList<NotificationChecker::NotificationEntry> entries =
+ MMC->notificationChecker()->notificationEntries();
+ QList<int> shownNotifications =
+ stringToIntList(MMC->settings()->get("ShownNotifications").toString());
+ for (auto it = entries.begin(); it != entries.end(); ++it)
+ {
+ NotificationChecker::NotificationEntry entry = *it;
+ if (!shownNotifications.contains(entry.id) && entry.applies())
+ {
+ QMessageBox::Icon icon;
+ switch (entry.type)
+ {
+ case NotificationChecker::NotificationEntry::Critical:
+ icon = QMessageBox::Critical;
+ break;
+ case NotificationChecker::NotificationEntry::Warning:
+ icon = QMessageBox::Warning;
+ break;
+ case NotificationChecker::NotificationEntry::Information:
+ icon = QMessageBox::Information;
+ break;
+ }
+
+ QMessageBox box(icon, tr("Notification"), entry.message, QMessageBox::Close, this);
+ QPushButton *dontShowAgainButton = box.addButton(tr("Don't show again"), QMessageBox::AcceptRole);
+ box.setDefaultButton(QMessageBox::Close);
+ box.exec();
+ if (box.clickedButton() == dontShowAgainButton)
+ {
+ shownNotifications.append(entry.id);
+ }
+ }
+ }
+ MMC->settings()->set("ShownNotifications", intListToString(shownNotifications));
+}
+
void MainWindow::downloadUpdates(QString repo, int versionId, bool installOnExit)
{
QLOG_INFO() << "Downloading updates.";
@@ -507,10 +664,14 @@ void MainWindow::downloadUpdates(QString repo, int versionId, bool installOnExit
// If the task succeeds, install the updates.
if (updateDlg.exec(&updateTask))
{
+ UpdateFlags baseFlags = None;
+ #ifdef MultiMC_UPDATER_DRY_RUN
+ baseFlags |= DryRun;
+ #endif
if (installOnExit)
- MMC->setUpdateOnExit(updateTask.updateFilesDir());
+ MMC->installUpdates(updateTask.updateFilesDir(), baseFlags | OnExit);
else
- MMC->installUpdates(updateTask.updateFilesDir(), true);
+ MMC->installUpdates(updateTask.updateFilesDir(), baseFlags | RestartOnFinish);
}
}
@@ -696,6 +857,20 @@ void MainWindow::updateInstanceToolIcon(QString new_icon)
ui->actionChangeInstIcon->setIcon(MMC->icons()->getIcon(m_currentInstIcon));
}
+void MainWindow::setSelectedInstanceById(const QString &id)
+{
+ QModelIndex selectionIndex = proxymodel->index(0, 0);
+ if (!id.isNull())
+ {
+ const QModelIndex index = MMC->instances()->getInstanceIndexById(id);
+ if (index.isValid())
+ {
+ selectionIndex = proxymodel->mapFromSource(index);
+ }
+ }
+ view->selectionModel()->setCurrentIndex(selectionIndex, QItemSelectionModel::ClearAndSelect);
+}
+
void MainWindow::on_actionChangeInstGroup_triggered()
{
if (!m_selectedInstance)
@@ -764,7 +939,7 @@ void MainWindow::on_actionManageAccounts_triggered()
void MainWindow::on_actionReportBug_triggered()
{
- openWebPage(QUrl("http://multimc.myjetbrains.com/youtrack/dashboard#newissue=yes"));
+ openWebPage(QUrl("https://github.com/MultiMC/MultiMC5/issues"));
}
void MainWindow::on_actionMoreNews_triggered()
@@ -1182,12 +1357,16 @@ void MainWindow::instanceChanged(const QModelIndex &current, const QModelIndex &
void MainWindow::selectionBad()
{
+ // start by reseting everything...
m_selectedInstance = nullptr;
statusBar()->clearMessage();
ui->instanceToolBar->setEnabled(false);
renameButton->setText(tr("Rename Instance"));
updateInstanceToolIcon("infinity");
+
+ // ...and then see if we can enable the previously selected instance
+ setSelectedInstanceById(MMC->settings()->get("SelectedInstance").toString());
}
void MainWindow::on_actionEditInstNotes_triggered()
diff --git a/gui/MainWindow.h b/gui/MainWindow.h
index f2315ee6..eb478776 100644
--- a/gui/MainWindow.h
+++ b/gui/MainWindow.h
@@ -17,6 +17,7 @@
#include <QMainWindow>
#include <QProcess>
+#include <QTimer>
#include "logic/lists/InstanceList.h"
#include "logic/BaseInstance.h"
@@ -145,6 +146,8 @@ slots:
// called when an icon is changed in the icon model.
void iconUpdated(QString);
+ void showInstanceContextMenu(const QPoint&);
+
public
slots:
void instanceActivated(QModelIndex);
@@ -157,6 +160,8 @@ slots:
void updateAvailable(QString repo, QString versionName, int versionId);
+ void notificationsChanged();
+
void activeAccountChanged();
void changeActiveAccount();
@@ -164,6 +169,12 @@ slots:
void repopulateAccountsMenu();
void updateNewsLabel();
+
+ void updateStatusUI();
+
+ void updateStatusFailedUI();
+
+ void reloadStatus();
/*!
* Runs the DownloadUpdateTask and installs updates.
@@ -175,6 +186,8 @@ protected:
void setCatBackground(bool enabled);
void updateInstanceToolIcon(QString new_icon);
+ void setSelectedInstanceById(const QString &id);
+
private:
Ui::MainWindow *ui;
KCategoryDrawer *drawer;
@@ -192,8 +205,12 @@ private:
Task *m_versionLoadTask;
QLabel *m_statusLeft;
+ QLabel *m_statusRight;
+ QToolButton *m_statusRefresh;
QMenu *accountMenu;
QToolButton *accountMenuButton;
QAction *manageAccountsAction;
+
+ QTimer statusTimer;
};
diff --git a/gui/dialogs/AboutDialog.cpp b/gui/dialogs/AboutDialog.cpp
index 58d61dd0..35c85815 100644
--- a/gui/dialogs/AboutDialog.cpp
+++ b/gui/dialogs/AboutDialog.cpp
@@ -24,8 +24,25 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia
MultiMCPlatform::fixWM_CLASS(this);
ui->setupUi(this);
+ ui->urlLabel->setOpenExternalLinks(true);
+
ui->icon->setPixmap(QIcon(":/icons/multimc/scalable/apps/multimc.svg").pixmap(64));
- ui->title->setText("MultiMC " + MMC->version().toString());
+ ui->title->setText("MultiMC 5 " + MMC->version().toString());
+
+ ui->versionLabel->setText(tr("Version") +": " + MMC->version().toString());
+ ui->vtypeLabel->setText(tr("Version Type") +": " + MMC->version().typeName());
+ ui->platformLabel->setText(tr("Platform") +": " + MMC->version().platform);
+
+ if (MMC->version().build >= 0)
+ ui->buildNumLabel->setText(tr("Build Number") +": " + QString::number(MMC->version().build));
+ else
+ ui->buildNumLabel->setVisible(false);
+
+ if (!MMC->version().channel.isEmpty())
+ ui->channelLabel->setText(tr("Channel") +": " + MMC->version().channel);
+ else
+ ui->channelLabel->setVisible(false);
+
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
MMC->connect(ui->aboutQt, SIGNAL(clicked()), SLOT(aboutQt()));
diff --git a/gui/dialogs/AboutDialog.ui b/gui/dialogs/AboutDialog.ui
index df9b1a53..64a355d3 100644
--- a/gui/dialogs/AboutDialog.ui
+++ b/gui/dialogs/AboutDialog.ui
@@ -86,7 +86,7 @@
</font>
</property>
<property name="text">
- <string>MultiMC</string>
+ <string>MultiMC 5</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -103,8 +103,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>685</width>
- <height>304</height>
+ <width>689</width>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -112,6 +112,56 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
+ <widget class="QLabel" name="versionLabel">
+ <property name="text">
+ <string>Version:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="vtypeLabel">
+ <property name="text">
+ <string>Version Type:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="platformLabel">
+ <property name="text">
+ <string>Platform:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="buildNumLabel">
+ <property name="text">
+ <string>Build Number:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="channelLabel">
+ <property name="text">
+ <string>Channel:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QLabel" name="aboutLabel">
<property name="enabled">
<bool>true</bool>
@@ -158,6 +208,19 @@
</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>
</layout>
</widget>
<widget class="QWidget" name="creditsPage">
@@ -165,8 +228,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>685</width>
- <height>304</height>
+ <width>689</width>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -182,19 +245,19 @@
<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:'MS Shell Dlg 2'; font-size:7.8pt; 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-size:10pt; 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;Andrew Okin &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:forkk@forkk.net&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;forkk@forkk.net&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&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:10pt;&quot;&gt;Petr Mrázek &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:peterix@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;peterix@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&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:10pt;&quot;&gt;Sky &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://www.twitter.com/drayshak&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@drayshak&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;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:10pt; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&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;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; 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-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Andrew Okin &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:forkk@forkk.net&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;forkk@forkk.net&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&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-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Petr Mrázek &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:peterix@gmail.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;peterix@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&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-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Sky &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://www.twitter.com/drayshak&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@drayshak&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;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-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;&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:'Ubuntu'; font-size:10pt; font-weight:600;&quot;&gt;With thanks to&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;Orochimarufan &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:orochimarufan.x3@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;orochimarufan.x3@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&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:10pt;&quot;&gt;TakSuyu &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:taksuyu@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;taksuyu@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&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:10pt;&quot;&gt;Kilobyte &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:stiepen22@gmx.de&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;stiepen22@gmx.de&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&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:10pt;&quot;&gt;Jan (02JanDal) &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:02jandal@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;02jandal@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&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:10pt;&quot;&gt;Robotbrain &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/skylordelros&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@skylordelros&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&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:10pt;&quot;&gt;Rootbear75 &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/rootbear75&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@rootbear75&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt; (build server)&lt;/span&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-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Orochimarufan &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:orochimarufan.x3@gmail.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;orochimarufan.x3@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&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-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;TakSuyu &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:taksuyu@gmail.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;taksuyu@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&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-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Kilobyte &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:stiepen22@gmx.de&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;stiepen22@gmx.de&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&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-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Jan (02JanDal) &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:02jandal@gmail.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;02jandal@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&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-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Robotbrain &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/skylordelros&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@skylordelros&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&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-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Rootbear75 &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/rootbear75&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@rootbear75&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt; (build server)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
@@ -218,8 +281,8 @@ p, li { white-space: pre-wrap; }
<rect>
<x>0</x>
<y>0</y>
- <width>684</width>
- <height>290</height>
+ <width>689</width>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -246,7 +309,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:7.8pt; 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;
@@ -367,7 +430,36 @@ 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; 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; * This file has been put into the public domain.&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; * You can do whatever you want with this file.&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>
+&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;&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;
+&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;Redistribution and use in source and binary forms, with or without&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;modification, are permitted provided that the following conditions are met:&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; * Redistributions of source code must retain the above copyright&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; notice, this list of conditions and the following disclaimer.&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; * Redistributions in binary form must reproduce the above copyright&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; notice, this list of conditions and the following disclaimer in the&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; documentation and/or other materials provided with the distribution.&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; * Neither the name of the &amp;lt;organization&amp;gt; nor the&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; names of its contributors may be used to endorse or promote products&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; derived from this software without specific prior written permission.&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; 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;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&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;ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&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;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&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;DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&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;DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&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, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&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;LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&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;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 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>
</property>
</widget>
</item>
@@ -378,8 +470,8 @@ p, li { white-space: pre-wrap; }
<rect>
<x>0</x>
<y>0</y>
- <width>684</width>
- <height>290</height>
+ <width>689</width>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -392,12 +484,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:'MS Shell Dlg 2'; font-size:7.8pt; 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/InstanceSettings.ui b/gui/dialogs/InstanceSettings.ui
index 9260caea..9c7e1757 100644
--- a/gui/dialogs/InstanceSettings.ui
+++ b/gui/dialogs/InstanceSettings.ui
@@ -168,6 +168,12 @@
<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>
@@ -198,6 +204,12 @@
</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>
@@ -214,6 +226,12 @@
</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>
diff --git a/gui/dialogs/SettingsDialog.cpp b/gui/dialogs/SettingsDialog.cpp
index 60a3e009..b90434b0 100644
--- a/gui/dialogs/SettingsDialog.cpp
+++ b/gui/dialogs/SettingsDialog.cpp
@@ -27,6 +27,8 @@
#include "logic/lists/JavaVersionList.h"
#include <logic/JavaChecker.h>
+#include "logic/updater/UpdateChecker.h"
+
#include <settingsobject.h>
#include <pathutils.h>
#include <QFileDialog>
@@ -48,6 +50,18 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Se
loadSettings(MMC->settings().get());
updateCheckboxStuff();
+
+ QObject::connect(MMC->updateChecker().get(), &UpdateChecker::channelListLoaded, this, &SettingsDialog::refreshUpdateChannelList);
+
+ if (MMC->updateChecker()->hasChannels())
+ {
+ refreshUpdateChannelList();
+ }
+ else
+ {
+ MMC->updateChecker()->updateChanList();
+ }
+ connect(ui->proxyGroup, SIGNAL(buttonClicked(int)), SLOT(proxyChanged(int)));
}
SettingsDialog::~SettingsDialog()
@@ -70,6 +84,8 @@ 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()
@@ -189,6 +205,9 @@ void SettingsDialog::on_buttonBox_accepted()
{
applySettings(MMC->settings().get());
+ // Apply proxy settings
+ MMC->updateProxySettings();
+
MMC->settings()->set("SettingsGeometry", saveGeometry().toBase64());
}
@@ -197,33 +216,80 @@ void SettingsDialog::on_buttonBox_rejected()
MMC->settings()->set("SettingsGeometry", saveGeometry().toBase64());
}
-void SettingsDialog::applySettings(SettingsObject *s)
+void SettingsDialog::proxyChanged(int)
{
- // Special cases
+ updateCheckboxStuff();
+}
- // Warn about dev builds.
- if (!ui->devBuildsCheckBox->isChecked())
- {
- s->set("UseDevBuilds", false);
- }
- else if (!s->get("UseDevBuilds").toBool())
+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++)
{
- auto response = CustomMessageBox::selectable(
- this, tr("Development builds"),
- tr("Development builds contain experimental features "
- "and may be unstable. Are you sure you want to enable them?"),
- QMessageBox::Question, QMessageBox::Yes | QMessageBox::No)->exec();
- if (response == QMessageBox::Yes)
+ 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)
{
- s->set("UseDevBuilds", true);
+ 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 < 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());
// Updates
s->set("AutoUpdate", ui->autoUpdateCheckBox->isChecked());
+ s->set("UpdateChannel", m_currentUpdateChannel);
// FTB
s->set("TrackFTBInstances", ui->trackFtbBox->isChecked());
@@ -258,6 +324,19 @@ void SettingsDialog::applySettings(SettingsObject *s)
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());
@@ -304,7 +383,7 @@ void SettingsDialog::loadSettings(SettingsObject *s)
// Updates
ui->autoUpdateCheckBox->setChecked(s->get("AutoUpdate").toBool());
- ui->devBuildsCheckBox->setChecked(s->get("UseDevBuilds").toBool());
+ m_currentUpdateChannel = s->get("UpdateChannel").toString();
// FTB
ui->trackFtbBox->setChecked(s->get("TrackFTBInstances").toBool());
@@ -345,6 +424,18 @@ void SettingsDialog::loadSettings(SettingsObject *s)
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());
diff --git a/gui/dialogs/SettingsDialog.h b/gui/dialogs/SettingsDialog.h
index 11fdb696..d7bbbeb3 100644
--- a/gui/dialogs/SettingsDialog.h
+++ b/gui/dialogs/SettingsDialog.h
@@ -74,7 +74,26 @@ slots:
void on_javaBrowseBtn_clicked();
void checkFinished(JavaCheckResult result);
+
+ /*!
+ * Updates the list of update channels in the combo box.
+ */
+ void refreshUpdateChannelList();
+
+ /*!
+ * Updates the channel description label.
+ */
+ void refreshUpdateChannelDesc();
+
+ void updateChannelSelectionChanged(int index);
+ void proxyChanged(int);
+
private:
Ui::SettingsDialog *ui;
std::shared_ptr<JavaChecker> checker;
+
+ /*!
+ * Stores the currently selected update channel.
+ */
+ QString m_currentUpdateChannel;
};
diff --git a/gui/dialogs/SettingsDialog.ui b/gui/dialogs/SettingsDialog.ui
index c1008c75..54e7db7a 100644
--- a/gui/dialogs/SettingsDialog.ui
+++ b/gui/dialogs/SettingsDialog.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>526</width>
- <height>701</height>
+ <width>545</width>
+ <height>609</height>
</rect>
</property>
<property name="sizePolicy">
@@ -35,74 +35,45 @@
<property name="currentIndex">
<number>0</number>
</property>
- <widget class="QWidget" name="generalTab">
+ <widget class="QWidget" name="featuresTab">
<attribute name="title">
- <string>General</string>
+ <string>Features</string>
</attribute>
- <layout class="QVBoxLayout" name="verticalLayout">
+ <layout class="QVBoxLayout" name="verticalLayout_9">
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,1">
- <item>
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Language (needs restart):</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="languageBox"/>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QGroupBox" name="sortingModeBox">
- <property name="enabled">
- <bool>true</bool>
- </property>
+ <widget class="QGroupBox" name="updateSettingsBox">
<property name="title">
- <string>Sorting Mode</string>
+ <string>Update Settings</string>
</property>
- <layout class="QHBoxLayout" name="sortingModeBoxLayout">
+ <layout class="QVBoxLayout" name="verticalLayout_7">
<item>
- <widget class="QRadioButton" name="sortLastLaunchedBtn">
+ <widget class="QCheckBox" name="autoUpdateCheckBox">
<property name="text">
- <string>By last launched</string>
+ <string>Check for updates when MultiMC starts?</string>
</property>
- <attribute name="buttonGroup">
- <string notr="true">sortingModeGroup</string>
- </attribute>
</widget>
</item>
<item>
- <widget class="QRadioButton" name="sortByNameBtn">
+ <widget class="QLabel" name="updateChannelLabel">
<property name="text">
- <string>By name</string>
+ <string>Update Channel:</string>
</property>
- <attribute name="buttonGroup">
- <string notr="true">sortingModeGroup</string>
- </attribute>
</widget>
</item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="updateSettingsBox">
- <property name="title">
- <string>Update Settings</string>
- </property>
- <layout class="QVBoxLayout" name="updateSettingsBoxLayout">
<item>
- <widget class="QCheckBox" name="devBuildsCheckBox">
- <property name="text">
- <string>Use development builds?</string>
+ <widget class="QComboBox" name="updateChannelComboBox">
+ <property name="enabled">
+ <bool>false</bool>
</property>
</widget>
</item>
<item>
- <widget class="QCheckBox" name="autoUpdateCheckBox">
+ <widget class="QLabel" name="updateChannelDescLabel">
<property name="text">
- <string>Check for updates when MultiMC starts?</string>
+ <string>No channel selected.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
</property>
</widget>
</item>
@@ -274,6 +245,78 @@
</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="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="editorsBox">
<property name="title">
<string>External Editors (leave empty for system default)</string>
@@ -433,6 +476,12 @@
<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>
@@ -463,6 +512,12 @@
</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>
@@ -486,6 +541,12 @@
</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>
@@ -643,6 +704,165 @@
</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>
</item>
<item>
@@ -661,14 +881,8 @@
<tabstop>buttonBox</tabstop>
<tabstop>sortLastLaunchedBtn</tabstop>
<tabstop>sortByNameBtn</tabstop>
- <tabstop>devBuildsCheckBox</tabstop>
- <tabstop>autoUpdateCheckBox</tabstop>
- <tabstop>instDirTextBox</tabstop>
- <tabstop>modsDirTextBox</tabstop>
- <tabstop>lwjglDirTextBox</tabstop>
- <tabstop>instDirBrowseBtn</tabstop>
- <tabstop>modsDirBrowseBtn</tabstop>
- <tabstop>lwjglDirBrowseBtn</tabstop>
+ <tabstop>jsonEditorTextBox</tabstop>
+ <tabstop>jsonEditorBrowseBtn</tabstop>
<tabstop>maximizedCheckBox</tabstop>
<tabstop>windowWidthSpinBox</tabstop>
<tabstop>windowHeightSpinBox</tabstop>
@@ -678,9 +892,13 @@
<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"/>
@@ -720,6 +938,7 @@
</connection>
</connections>
<buttongroups>
+ <buttongroup name="proxyGroup"/>
<buttongroup name="sortingModeGroup"/>
</buttongroups>
</ui>
diff --git a/gui/widgets/ModListView.cpp b/gui/widgets/ModListView.cpp
index 9d5950c3..358e6331 100644
--- a/gui/widgets/ModListView.cpp
+++ b/gui/widgets/ModListView.cpp
@@ -44,9 +44,19 @@ void ModListView::setModel ( QAbstractItemModel* model )
QTreeView::setModel ( model );
auto head = header();
head->setStretchLastSection(false);
- head->setSectionResizeMode(0, QHeaderView::ResizeToContents);
- head->setSectionResizeMode(1, QHeaderView::Stretch);
- for(int i = 2; i < head->count(); i++)
- head->setSectionResizeMode(i, QHeaderView::ResizeToContents);
- dropIndicatorPosition();
+ // HACK: this is true for the checkbox column of mod lists
+ auto string = model->headerData(0,head->orientation()).toString();
+ if(!string.size())
+ {
+ head->setSectionResizeMode(0, QHeaderView::ResizeToContents);
+ head->setSectionResizeMode(1, QHeaderView::Stretch);
+ for(int i = 2; i < head->count(); i++)
+ head->setSectionResizeMode(i, QHeaderView::ResizeToContents);
+ }
+ else
+ {
+ head->setSectionResizeMode(0, QHeaderView::Stretch);
+ for(int i = 1; i < head->count(); i++)
+ head->setSectionResizeMode(i, QHeaderView::ResizeToContents);
+ }
}