diff options
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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string> +</style></head><body style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style="-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;"><br /></p></body></html></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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'DejaVu Sans Mono'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'DejaVu Sans Mono'; font-size:11pt; font-weight:400; font-style:normal;"> <p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">MultiMC</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Copyright 2012-2014 MultiMC Contributors</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></p> @@ -422,7 +422,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> */</span></p> <p style="-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;"><br /></p> <p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">Java IconLoader class</span></p> -<p style="-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;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Copyright (c) 2011, Chris Molini</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">All rights reserved.</span></p> <p style="-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;"><br /></p> @@ -447,8 +447,13 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span></p> +<p align="center" style="-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;"><br /></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">ColumnResizer</span></p> <p style="-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;"><br /></p> -<p style="-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;"><br /></p></body></html></string> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">/*</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Copyright 2011 Aurélien Gâteau &lt;agateau@kde.org&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * License: LGPL v2.1 or later (see COPYING)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> */</span></p></body></html></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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;">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.</span></p> -<p style="-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;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;">Part of the reason for using the Apache license is we don't want people using the &quot;MultiMC&quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &quot;MultiMC&quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).</span></p> -<p style="-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;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;">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 </span><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:600;">without</span><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;"> implying that you have our blessing.</span></p></body></html></string> +</style></head><body style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">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.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Part of the reason for using the Apache license is we don't want people using the &quot;MultiMC&quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &quot;MultiMC&quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">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 <span style=" font-weight:600;">without</span> implying that you have our blessing.</p></body></html></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><html><head/><body><p>Welcome! If you're new here, you can click the &quot;Add&quot; button to add your Mojang or Minecraft account.</p></body></html></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>&Add</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="rmAccountBtn"> - <property name="text"> - <string>&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><html><head/><body><p>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).</p></body></html></string> - </property> - <property name="text"> - <string>&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>&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><html><head/><body><p><a href="http://www.ej-technologies.com/products/jprofiler/overview.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.ej-technologies.com/products/jprofiler/overview.html</span></a></p></body></html></string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="groupBox_3"> - <property name="title"> - <string>JVisualVM</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_11"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <item> - <widget class="QLineEdit" name="jvisualvmPathEdit"/> - </item> - <item> - <widget class="QPushButton" name="jvisualvmPathBtn"> - <property name="text"> - <string>...</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QPushButton" name="jvisualvmCheckBtn"> - <property name="text"> - <string>Check</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="jvisualvmLink"> - <property name="text"> - <string><html><head/><body><p><a href="http://visualvm.java.net/"><span style=" text-decoration: underline; color:#0000ff;">http://visualvm.java.net/</span></a></p></body></html></string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="groupBox_4"> - <property name="title"> - <string>MCEdit</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_12"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <item> - <widget class="QLineEdit" name="mceditPathEdit"/> - </item> - <item> - <widget class="QPushButton" name="mceditPathBtn"> - <property name="text"> - <string>...</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QPushButton" name="mceditCheckBtn"> - <property name="text"> - <string>Check</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="mceditLink"> - <property name="text"> - <string><html><head/><body><p><a href="http://www.mcedit.net/"><span style=" text-decoration: underline; color:#0000ff;">http://www.mcedit.net/</span></a></p></body></html></string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacer_3"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </widget> - </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>&Remove</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="moveJarUpBtn"> - <property name="text"> - <string>Move &Up</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="moveJarDownBtn"> - <property name="text"> - <string>Move &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>&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>&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>&Remove</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="moveJarUpBtn"> + <property name="text"> + <string>Move &Up</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="moveJarDownBtn"> + <property name="text"> + <string>Move &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>&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>&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>&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>&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>&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>&Add</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="rmModBtn"> + <property name="text"> + <string>&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>&View Folder</string> + </property> + </widget> + </item> + </layout> </item> - <item> - <widget class="QPushButton" name="rmModBtn"> - <property name="text"> - <string>&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>&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>&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>&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>&Upload</string> - </property> - </widget> - </item> <item> - <widget class="QPushButton" name="deleteBtn"> - <property name="text"> - <string>&Delete</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="renameBtn"> - <property name="text"> - <string>&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>&View Folder</string> - </property> - </widget> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QPushButton" name="uploadBtn"> + <property name="text"> + <string>&Upload</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="deleteBtn"> + <property name="text"> + <string>&Delete</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="renameBtn"> + <property name="text"> + <string>&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>&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><html><head/><body><p>Welcome! If you're new here, you can click the &quot;Add&quot; button to add your Mojang or Minecraft account.</p></body></html></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>&Add</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="rmAccountBtn"> + <property name="text"> + <string>&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><html><head/><body><p>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).</p></body></html></string> + </property> + <property name="text"> + <string>&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>&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><html><head/><body><p><a href="http://www.ej-technologies.com/products/jprofiler/overview.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.ej-technologies.com/products/jprofiler/overview.html</span></a></p></body></html></string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="title"> + <string>JVisualVM</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_11"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QLineEdit" name="jvisualvmPathEdit"/> + </item> + <item> + <widget class="QPushButton" name="jvisualvmPathBtn"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QPushButton" name="jvisualvmCheckBtn"> + <property name="text"> + <string>Check</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="jvisualvmLink"> + <property name="text"> + <string><html><head/><body><p><a href="http://visualvm.java.net/"><span style=" text-decoration: underline; color:#0000ff;">http://visualvm.java.net/</span></a></p></body></html></string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_4"> + <property name="title"> + <string>MCEdit</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_12"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <item> + <widget class="QLineEdit" name="mceditPathEdit"/> + </item> + <item> + <widget class="QPushButton" name="mceditPathBtn"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QPushButton" name="mceditCheckBtn"> + <property name="text"> + <string>Check</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="mceditLink"> + <property name="text"> + <string><html><head/><body><p><a href="http://www.mcedit.net/"><span style=" text-decoration: underline; color:#0000ff;">http://www.mcedit.net/</span></a></p></body></html></string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <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 Binary files differnew file mode 100644 index 00000000..e9f2f2a5 --- /dev/null +++ b/resources/multimc/16x16/minecraft.png diff --git a/resources/multimc/24x24/minecraft.png b/resources/multimc/24x24/minecraft.png Binary files differnew file mode 100644 index 00000000..b31177c9 --- /dev/null +++ b/resources/multimc/24x24/minecraft.png diff --git a/resources/multimc/256x256/minecraft.png b/resources/multimc/256x256/minecraft.png Binary files differnew file mode 100644 index 00000000..77e3f03e --- /dev/null +++ b/resources/multimc/256x256/minecraft.png diff --git a/resources/multimc/32x32/minecraft.png b/resources/multimc/32x32/minecraft.png Binary files differnew file mode 100644 index 00000000..816bec98 --- /dev/null +++ b/resources/multimc/32x32/minecraft.png diff --git a/resources/multimc/48x48/minecraft.png b/resources/multimc/48x48/minecraft.png Binary files differnew file mode 100644 index 00000000..38fc9f6c --- /dev/null +++ b/resources/multimc/48x48/minecraft.png 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" |