Merge branch 'release-0.1'

Release MultiMC version 0.1.
This commit is contained in:
Forkk 2014-01-08 21:45:13 -06:00
commit 06b5fa5dcc
26 changed files with 713 additions and 269 deletions

View File

@ -38,9 +38,7 @@ ELSEIF(MINGW)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall")
ENDIF() ENDIF()
################################ INCLUDE LIBRARIES ################################ ################################ 3rd Party Libs ################################
######## 3rd Party Libs ########
# Find the required Qt parts # Find the required Qt parts
find_package(Qt5Core REQUIRED) find_package(Qt5Core REQUIRED)
@ -75,41 +73,6 @@ query_qmake(QT_HOST_DATA QT_DATA_DIR)
set(QT_MKSPECS_DIR ${QT_DATA_DIR}/mkspecs) set(QT_MKSPECS_DIR ${QT_DATA_DIR}/mkspecs)
######## Included Libs ########
# Add quazip
add_subdirectory(depends/quazip)
include_directories(depends/quazip)
# Add the java launcher and checker
add_subdirectory(depends/launcher)
add_subdirectory(depends/javacheck)
# Add xz decompression
add_subdirectory(depends/xz-embedded)
include_directories(${XZ_INCLUDE_DIR})
# Add pack200 decompression
add_subdirectory(depends/pack200)
include_directories(${PACK200_INCLUDE_DIR})
######## MultiMC Libs ########
# Add the util library.
add_subdirectory(depends/util)
include_directories(${LIBUTIL_INCLUDE_DIR})
# Add the settings library.
add_subdirectory(depends/settings)
include_directories(${LIBSETTINGS_INCLUDE_DIR})
# Add the group view library.
add_subdirectory(depends/groupview)
include_directories(${LIBGROUPVIEW_INCLUDE_DIR})
# Add the updater
add_subdirectory(mmc_updater)
################################ SET UP BUILD OPTIONS ################################ ################################ SET UP BUILD OPTIONS ################################
######## Check endianness ######## ######## Check endianness ########
@ -127,13 +90,17 @@ SET(MultiMC_NEWS_RSS_URL "http://multimc.org/rss.xml" CACHE STRING "URL to fetch
######## Set version numbers ######## ######## Set version numbers ########
SET(MultiMC_VERSION_MAJOR 0) SET(MultiMC_VERSION_MAJOR 0)
SET(MultiMC_VERSION_MINOR 0) SET(MultiMC_VERSION_MINOR 1)
SET(MultiMC_VERSION_HOTFIX 0)
# Build number # Build number
SET(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.") SET(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
# Build type # Version type
SET(MultiMC_VERSION_BUILD_TYPE "custombuild" CACHE STRING "Build type. If this is set, it is appended to the end of the version string with a dash (<version string>-<build type>. It is not used for anything other than indicating in the version string what type of build this is (eg 'lin64').") SET(MultiMC_VERSION_TYPE "Custom" CACHE STRING "MultiMC's version type. This should be one of 'Custom', 'Release', 'ReleaseCandidate', or 'Development', depending on what type of version this is.")
# Build platform.
SET(MultiMC_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used by the notification system and to display in the about dialog.")
# Version channel # Version channel
SET(MultiMC_VERSION_CHANNEL "" CACHE STRING "The current build's channel. Included in the version string.") SET(MultiMC_VERSION_CHANNEL "" CACHE STRING "The current build's channel. Included in the version string.")
@ -147,19 +114,29 @@ SET(MultiMC_UPDATER false CACHE BOOL "Whether or not the update system is enable
# Notification URL # Notification URL
SET(MultiMC_NOTIFICATION_URL "" CACHE STRING "URL for checking for notifications.") SET(MultiMC_NOTIFICATION_URL "" CACHE STRING "URL for checking for notifications.")
SET(MultiMC_RELEASE_VERSION_NAME "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}")
IF (MultiMC_VERSION_HOTFIX GREATER 0)
SET(MultiMC_RELEASE_VERSION_NAME "${MultiMC_RELEASE_VERSION_NAME}.${MultiMC_VERSION_HOTFIX}")
ENDIF()
# Build a version string to display in the configure logs. # Build a version string to display in the configure logs.
SET(MultiMC_VERSION_STRING "5.${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}") IF (MultiMC_VERSION_TYPE STREQUAL "Custom")
IF (MultiMC_VERSION_BUILD GREATER -1) MESSAGE(STATUS "Version Type: Custom")
SET(MultiMC_VERSION_STRING "${MultiMC_VERSION_STRING}.${MultiMC_VERSION_BUILD}") SET(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}")
ENDIF () ELSEIF (MultiMC_VERSION_TYPE STREQUAL "Release")
IF (NOT MultiMC_VERSION_CHANNEL STREQUAL "") MESSAGE(STATUS "Version Type: Stable Release")
SET(MultiMC_VERSION_STRING "${MultiMC_VERSION_STRING}-${MultiMC_VERSION_CHANNEL}") SET(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}")
ENDIF () ELSEIF (MultiMC_VERSION_TYPE STREQUAL "ReleaseCandidate")
IF (NOT MultiMC_VERSION_BUILD_TYPE STREQUAL "") MESSAGE(STATUS "Version Type: Release Candidate")
SET(MultiMC_VERSION_STRING "${MultiMC_VERSION_STRING}-${MultiMC_VERSION_BUILD_TYPE}") SET(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}-rc${MultiMC_VERSION_BUILD}")
ELSEIF (MultiMC_VERSION_TYPE STREQUAL "Development")
MESSAGE(STATUS "Version Type: Development")
SET(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}-dev${MultiMC_VERSION_BUILD}")
ELSE ()
MESSAGE(ERROR "Invalid build type.")
ENDIF () ENDIF ()
MESSAGE(STATUS "MultiMC 5 version ${MultiMC_VERSION_STRING}") MESSAGE(STATUS "MultiMC 5 Version: ${MultiMC_VERSION_STRING}")
# If the update system is enabled, make sure MultiMC_CHANLIST_URL and MultiMC_VERSION_CHANNEL are set. # If the update system is enabled, make sure MultiMC_CHANLIST_URL and MultiMC_VERSION_CHANNEL are set.
IF (MultiMC_UPDATER) IF (MultiMC_UPDATER)
@ -209,6 +186,72 @@ ADD_DEFINITIONS(-DLIBSETTINGS_STATIC)
ADD_DEFINITIONS(-DLIBUTIL_STATIC) ADD_DEFINITIONS(-DLIBUTIL_STATIC)
ADD_DEFINITIONS(-DLIBGROUPVIEW_STATIC) ADD_DEFINITIONS(-DLIBGROUPVIEW_STATIC)
######## Packaging/install paths setup ########
IF(UNIX AND APPLE)
SET(BINARY_DEST_DIR MultiMC.app/Contents/MacOS)
SET(PLUGIN_DEST_DIR MultiMC.app/Contents/MacOS)
SET(QTCONF_DEST_DIR MultiMC.app/Contents/Resources)
SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app")
SET(MACOSX_BUNDLE_BUNDLE_NAME "MultiMC")
SET(MACOSX_BUNDLE_INFO_STRING "MultiMC Minecraft launcher and management utility.")
SET(MACOSX_BUNDLE_GUI_IDENTIFIER "org.multimc.MultiMC5")
SET(MACOSX_BUNDLE_BUNDLE_VERSION "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
SET(MACOSX_BUNDLE_SHORT_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
SET(MACOSX_BUNDLE_LONG_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
SET(MACOSX_BUNDLE_ICON_FILE MultiMC.icns)
SET(MACOSX_BUNDLE_COPYRIGHT "Copyright 2013 MultiMC Contributors")
ELSEIF(UNIX)
SET(BINARY_DEST_DIR bin)
SET(PLUGIN_DEST_DIR plugins)
SET(QTCONF_DEST_DIR .)
SET(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC")
ELSEIF(WIN32)
SET(BINARY_DEST_DIR .)
SET(PLUGIN_DEST_DIR .)
SET(QTCONF_DEST_DIR .)
SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.exe")
ENDIF()
# directories to look for dependencies
SET(DIRS "${QT_LIBS_DIR}")
################################ Included Libs ################################
# Add quazip
add_subdirectory(depends/quazip)
include_directories(depends/quazip)
# Add the java launcher and checker
add_subdirectory(depends/launcher)
add_subdirectory(depends/javacheck)
# Add xz decompression
add_subdirectory(depends/xz-embedded)
include_directories(${XZ_INCLUDE_DIR})
# Add pack200 decompression
add_subdirectory(depends/pack200)
include_directories(${PACK200_INCLUDE_DIR})
######## MultiMC Libs ########
# Add the util library.
add_subdirectory(depends/util)
include_directories(${LIBUTIL_INCLUDE_DIR})
# Add the settings library.
add_subdirectory(depends/settings)
include_directories(${LIBSETTINGS_INCLUDE_DIR})
# Add the group view library.
add_subdirectory(depends/groupview)
include_directories(${LIBGROUPVIEW_INCLUDE_DIR})
# Add the updater
add_subdirectory(mmc_updater)
################################ FILES ################################ ################################ FILES ################################
######## Sources and headers ######## ######## Sources and headers ########
@ -516,8 +559,8 @@ IF(MultiMC_CODE_COVERAGE)
ENDIF(MultiMC_CODE_COVERAGE) ENDIF(MultiMC_CODE_COVERAGE)
# Tell CMake that MultiMCLauncher.jar is generated. # Tell CMake that MultiMCLauncher.jar is generated.
SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/depends/launcher/MultiMCLauncher.jar GENERATED) #SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/depends/launcher/MultiMCLauncher.jar GENERATED)
SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/depends/javacheck/JavaCheck.jar GENERATED) #SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/depends/javacheck/JavaCheck.jar GENERATED)
# Qt 5 stuff # Qt 5 stuff
QT5_WRAP_UI(MULTIMC_UI ${MULTIMC_UIS}) QT5_WRAP_UI(MULTIMC_UI ${MULTIMC_UIS})
@ -540,34 +583,6 @@ ADD_DEPENDENCIES(MultiMC_common MultiMCLauncher JavaCheck)
################################ INSTALLATION AND PACKAGING ################################ ################################ INSTALLATION AND PACKAGING ################################
######## Packaging/install paths setup ########
IF(UNIX AND APPLE)
SET(PLUGIN_DEST_DIR MultiMC.app/Contents/MacOS)
SET(QTCONF_DEST_DIR MultiMC.app/Contents/Resources)
SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app")
SET(MACOSX_BUNDLE_BUNDLE_NAME "MultiMC")
SET(MACOSX_BUNDLE_INFO_STRING "MultiMC Minecraft launcher and management utility.")
SET(MACOSX_BUNDLE_GUI_IDENTIFIER "org.multimc.MultiMC5")
SET(MACOSX_BUNDLE_BUNDLE_VERSION "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
SET(MACOSX_BUNDLE_SHORT_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
SET(MACOSX_BUNDLE_LONG_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
SET(MACOSX_BUNDLE_ICON_FILE MultiMC.icns)
SET(MACOSX_BUNDLE_COPYRIGHT "Copyright 2013 MultiMC Contributors")
ELSEIF(UNIX)
SET(PLUGIN_DEST_DIR plugins)
SET(QTCONF_DEST_DIR .)
SET(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC")
ELSEIF(WIN32)
SET(PLUGIN_DEST_DIR .)
SET(QTCONF_DEST_DIR .)
SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.exe")
ENDIF()
# directories to look for dependencies
SET(DIRS "${QT_LIBS_DIR}")
######## Install ######## ######## Install ########
#### Executable #### #### Executable ####

View File

@ -38,8 +38,8 @@
using namespace Util::Commandline; using namespace Util::Commandline;
MultiMC::MultiMC(int &argc, char **argv, bool root_override) MultiMC::MultiMC(int &argc, char **argv, bool root_override)
: QApplication(argc, argv), m_version{VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, : QApplication(argc, argv), m_version{VERSION_MAJOR, VERSION_MINOR, VERSION_HOTFIX,
VERSION_CHANNEL, VERSION_BUILD_TYPE} VERSION_BUILD, MultiMCVersion::VERSION_TYPE, VERSION_CHANNEL, BUILD_PLATFORM}
{ {
setOrganizationName("MultiMC"); setOrganizationName("MultiMC");
setApplicationName("MultiMC5"); setApplicationName("MultiMC5");
@ -198,56 +198,12 @@ MultiMC::MultiMC(int &argc, char **argv, bool root_override)
// init the http meta cache // init the http meta cache
initHttpMetaCache(); initHttpMetaCache();
// set up a basic autodetected proxy (system default)
QNetworkProxyFactory::setUseSystemConfiguration(true);
QLOG_INFO() << "Detecting system proxy settings...";
auto proxies = QNetworkProxyFactory::systemProxyForQuery();
if (proxies.size() == 1 && proxies[0].type() == QNetworkProxy::NoProxy)
{
QLOG_INFO() << "No proxy found.";
}
else
for (auto proxy : proxies)
{
QString proxyDesc;
if (proxy.type() == QNetworkProxy::NoProxy)
{
QLOG_INFO() << "Using no proxy is an option!";
continue;
}
switch (proxy.type())
{
case QNetworkProxy::DefaultProxy:
proxyDesc = "Default proxy: ";
break;
case QNetworkProxy::Socks5Proxy:
proxyDesc = "Socks5 proxy: ";
break;
case QNetworkProxy::HttpProxy:
proxyDesc = "HTTP proxy: ";
break;
case QNetworkProxy::HttpCachingProxy:
proxyDesc = "HTTP caching: ";
break;
case QNetworkProxy::FtpCachingProxy:
proxyDesc = "FTP caching: ";
break;
default:
proxyDesc = "DERP proxy: ";
break;
}
proxyDesc += QString("%3@%1:%2 pass %4")
.arg(proxy.hostName())
.arg(proxy.port())
.arg(proxy.user())
.arg(proxy.password());
QLOG_INFO() << proxyDesc;
}
// create the global network manager // create the global network manager
m_qnam.reset(new QNetworkAccessManager(this)); m_qnam.reset(new QNetworkAccessManager(this));
// init proxy settings
updateProxySettings();
// launch instance, if that's what should be done // launch instance, if that's what should be done
// WARNING: disabled until further notice // WARNING: disabled until further notice
/* /*
@ -424,6 +380,13 @@ void MultiMC::initGlobalSettings()
m_settings->registerSetting({"MinecraftWinWidth", "MCWindowWidth"}, 854); m_settings->registerSetting({"MinecraftWinWidth", "MCWindowWidth"}, 854);
m_settings->registerSetting({"MinecraftWinHeight", "MCWindowHeight"}, 480); m_settings->registerSetting({"MinecraftWinHeight", "MCWindowHeight"}, 480);
// Proxy Settings
m_settings->registerSetting("ProxyType", "Default");
m_settings->registerSetting({"ProxyAddr", "ProxyHostName"}, "127.0.0.1");
m_settings->registerSetting("ProxyPort", 8080);
m_settings->registerSetting({"ProxyUser", "ProxyUsername"}, "");
m_settings->registerSetting({"ProxyPass", "ProxyPassword"}, "");
// Memory // Memory
m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512); m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512);
m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, 1024); m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, 1024);
@ -467,6 +430,74 @@ void MultiMC::initHttpMetaCache()
m_metacache->Load(); m_metacache->Load();
} }
void MultiMC::updateProxySettings()
{
QString proxyTypeStr = settings()->get("ProxyType").toString();
// Get the proxy settings from the settings object.
QString addr = settings()->get("ProxyAddr").toString();
int port = settings()->get("ProxyPort").value<qint16>();
QString user = settings()->get("ProxyUser").toString();
QString pass = settings()->get("ProxyPass").toString();
// Set the application proxy settings.
if (proxyTypeStr == "SOCKS5")
{
QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, addr, port, user, pass));
}
else if (proxyTypeStr == "HTTP")
{
QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, addr, port, user, pass));
}
else if (proxyTypeStr == "None")
{
// If we have no proxy set, set no proxy and return.
QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::NoProxy));
}
else
{
// If we have "Default" selected, set Qt to use the system proxy settings.
QNetworkProxyFactory::setUseSystemConfiguration(true);
}
QLOG_INFO() << "Detecting proxy settings...";
QNetworkProxy proxy = QNetworkProxy::applicationProxy();
if (m_qnam.get()) m_qnam->setProxy(proxy);
QString proxyDesc;
if (proxy.type() == QNetworkProxy::NoProxy)
{
QLOG_INFO() << "Using no proxy is an option!";
return;
}
switch (proxy.type())
{
case QNetworkProxy::DefaultProxy:
proxyDesc = "Default proxy: ";
break;
case QNetworkProxy::Socks5Proxy:
proxyDesc = "Socks5 proxy: ";
break;
case QNetworkProxy::HttpProxy:
proxyDesc = "HTTP proxy: ";
break;
case QNetworkProxy::HttpCachingProxy:
proxyDesc = "HTTP caching: ";
break;
case QNetworkProxy::FtpCachingProxy:
proxyDesc = "FTP caching: ";
break;
default:
proxyDesc = "DERP proxy: ";
break;
}
proxyDesc += QString("%3@%1:%2 pass %4")
.arg(proxy.hostName())
.arg(proxy.port())
.arg(proxy.user())
.arg(proxy.password());
QLOG_INFO() << proxyDesc;
}
std::shared_ptr<IconList> MultiMC::icons() std::shared_ptr<IconList> MultiMC::icons()
{ {
if (!m_icons) if (!m_icons)

View File

@ -123,6 +123,11 @@ public:
void installUpdates(const QString updateFilesDir, UpdateFlags flags = None); void installUpdates(const QString updateFilesDir, UpdateFlags flags = None);
/*!
* Updates the application proxy settings from the settings object.
*/
void updateProxySettings();
/*! /*!
* Opens a json file using either a system default editor, or, if note empty, the editor * Opens a json file using either a system default editor, or, if note empty, the editor
* specified in the settings * specified in the settings

View File

@ -18,58 +18,79 @@
#include <QString> #include <QString>
/*! /*!
* \brief The Version class represents a MultiMC version number. * \brief The Version class represents a MultiMC version.
*/ */
struct MultiMCVersion struct MultiMCVersion
{ {
enum Type
{
//! Version type for stable release builds.
Release,
//! Version type for release candidates.
ReleaseCandidate,
//! Version type for development builds.
Development,
//! Version type for custom builds. This is the default when no version type is specified.
Custom
};
/*! /*!
* \brief Converts the Version to a string. * \brief Converts the Version to a string.
* \return The version number in string format (major.minor.revision.build). * \return The version number in string format (major.minor.revision.build).
*/ */
QString toString() const QString toString() const
{ {
QString vstr = QString("5.%1.%2").arg( QString vstr = QString("%1.%2").arg(
QString::number(major), QString::number(major),
QString::number(minor)); QString::number(minor));
if (build >= 0) vstr += "." + QString::number(build); if (hotfix > 0) vstr += "." + QString::number(hotfix);
if (!channel.isEmpty()) vstr += "-" + channel;
if (!buildType.isEmpty()) vstr += "-" + buildType; // If the build is a development build or release candidate, add that info to the end.
if (type == Development) vstr += "-dev" + QString::number(build);
else if (type == ReleaseCandidate) vstr += "-rc" + QString::number(build);
return vstr; return vstr;
} }
/*! QString typeName() const
* \brief The major version number. {
* This is no longer going to always be 5 for MultiMC 5. Doing so is useless. switch (type)
* Instead, we'll be starting major off at 1 and incrementing it with every major feature. {
*/ case Release:
return "Stable Release";
case ReleaseCandidate:
return "Release Candidate";
case Development:
return "Development";
case Custom:
default:
return "Custom";
}
}
//! The major version number.
int major; int major;
/*! //! The minor version number.
* \brief The minor version number.
* This number is incremented for major features and bug fixes.
*/
int minor; int minor;
/*! //! The hotfix number.
* \brief The build number. int hotfix;
* This number is automatically set by Buildbot it is set to the build number of the buildbot
* build that this build came from. //! The build number.
* If this build didn't come from buildbot and no build number was given to CMake, this will default
* to -1, causing it to not show in this version's string representation.
*/
int build; int build;
/*! //! The build type.
* \brief This build's channel. Type type;
*/
//! The build channel.
QString channel; QString channel;
/*! //! A short string identifying the platform that this version is for. For example, lin64 or win32.
* \brief The build type. QString platform;
* This indicates the type of build that this is. For example, lin64 or custombuild.
*/
QString buildType;
}; };

17
changelog.yaml Normal file
View File

@ -0,0 +1,17 @@
#
# This is MultiMC's changelog. It is formatted in YAML.
#
# Each key below represents a release version name. Each release key has several string entries under it, each containing information about a single change. Each of these entries may contain Markdown for formatting.
#
0.0:
- Initial release.
0.1:
- Reworked the version numbering system to support our [new Git workflow](http://nvie.com/posts/a-successful-git-branching-model/).
- Added a tray icon for the console window.
- Fixed instances getting deselected after FTB instances are loaded (or whenever the model is reset).
- Implemented proxy settings.
- Fixed sorting of Java installations in the Java list.
- Jar files are now distributed separately, rather than being extracted from the binary at runtime.
- Added additional information to the about dialog.

View File

@ -1,13 +1,17 @@
#pragma once #pragma once
// Minor and major version, used to communicate changes to users. // Version information
#define VERSION_MAJOR @MultiMC_VERSION_MAJOR@ #define VERSION_MAJOR @MultiMC_VERSION_MAJOR@
#define VERSION_MINOR @MultiMC_VERSION_MINOR@ #define VERSION_MINOR @MultiMC_VERSION_MINOR@
#define VERSION_HOTFIX @MultiMC_VERSION_HOTFIX@
// Build number, channel, and type -- number and channel are used by the updater, type is purely visual
#define VERSION_BUILD @MultiMC_VERSION_BUILD@ #define VERSION_BUILD @MultiMC_VERSION_BUILD@
#define VERSION_TYPE @MultiMC_VERSION_TYPE@
// The version channel. This is used by the updater to determine what channel the current version came from.
#define VERSION_CHANNEL "@MultiMC_VERSION_CHANNEL@" #define VERSION_CHANNEL "@MultiMC_VERSION_CHANNEL@"
#define VERSION_BUILD_TYPE "@MultiMC_VERSION_BUILD_TYPE@"
// A short string identifying this build's platform. For example, "lin64" or "win32".
#define BUILD_PLATFORM "@MultiMC_BUILD_PLATFORM@"
// URL for the updater's channel // URL for the updater's channel
#define CHANLIST_URL "@MultiMC_CHANLIST_URL@" #define CHANLIST_URL "@MultiMC_CHANLIST_URL@"

View File

@ -5,10 +5,11 @@ find_package(Java 1.6 REQUIRED COMPONENTS Development)
include(UseJava) include(UseJava)
set(CMAKE_JAVA_JAR_ENTRY_POINT JavaCheck) set(CMAKE_JAVA_JAR_ENTRY_POINT JavaCheck)
set(CMAKE_JAVA_COMPILE_FLAGS -target 1.6 -source 1.6 -Xlint:deprecation -Xlint:unchecked) set(CMAKE_JAVA_COMPILE_FLAGS -target 1.6 -source 1.6 -Xlint:deprecation -Xlint:unchecked)
#set(CMAKE_JAVA_TARGET_OUTPUT_DIR "${PROJECT_SOURCE_DIR}/../../resources")
set(SRC set(SRC
JavaCheck.java JavaCheck.java
) )
add_jar(JavaCheck ${SRC}) add_jar(JavaCheck ${SRC})
INSTALL_JAR(JavaCheck "${BINARY_DEST_DIR}/jars")

View File

@ -5,7 +5,6 @@ find_package(Java 1.6 REQUIRED COMPONENTS Development)
include(UseJava) include(UseJava)
set(CMAKE_JAVA_JAR_ENTRY_POINT MultiMCLauncher) set(CMAKE_JAVA_JAR_ENTRY_POINT MultiMCLauncher)
set(CMAKE_JAVA_COMPILE_FLAGS -target 1.6 -source 1.6 -Xlint:deprecation -Xlint:unchecked) set(CMAKE_JAVA_COMPILE_FLAGS -target 1.6 -source 1.6 -Xlint:deprecation -Xlint:unchecked)
#set(CMAKE_JAVA_TARGET_OUTPUT_DIR "${PROJECT_SOURCE_DIR}/../../resources")
set(SRC set(SRC
MultiMCLauncher.java MultiMCLauncher.java
@ -19,3 +18,5 @@ set(SRC
) )
add_jar(MultiMCLauncher ${SRC}) add_jar(MultiMCLauncher ${SRC})
INSTALL_JAR(MultiMCLauncher "${BINARY_DEST_DIR}/jars")

View File

@ -1,6 +1,8 @@
<RCC> <RCC>
<!--
<qresource prefix="/java"> <qresource prefix="/java">
<file alias="launcher.jar">@MMC_BIN@/depends/launcher/MultiMCLauncher.jar</file> <file alias="launcher.jar">@MMC_BIN@/depends/launcher/MultiMCLauncher.jar</file>
<file alias="checker.jar">@MMC_BIN@/depends/javacheck/JavaCheck.jar</file> <file alias="checker.jar">@MMC_BIN@/depends/javacheck/JavaCheck.jar</file>
</qresource> </qresource>
-->
</RCC> </RCC>

View File

@ -19,12 +19,14 @@
#include <QScrollBar> #include <QScrollBar>
#include <QMessageBox> #include <QMessageBox>
#include <QSystemTrayIcon>
#include <gui/Platform.h> #include <gui/Platform.h>
#include <gui/dialogs/CustomMessageBox.h> #include <gui/dialogs/CustomMessageBox.h>
#include <gui/dialogs/ProgressDialog.h> #include <gui/dialogs/ProgressDialog.h>
#include "logic/net/PasteUpload.h" #include "logic/net/PasteUpload.h"
#include "logic/icons/IconList.h"
ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent) ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent)
: QMainWindow(parent), ui(new Ui::ConsoleWindow), proc(mcproc) : QMainWindow(parent), ui(new Ui::ConsoleWindow), proc(mcproc)
@ -35,14 +37,28 @@ ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent)
SLOT(write(QString, MessageLevel::Enum))); SLOT(write(QString, MessageLevel::Enum)));
connect(mcproc, SIGNAL(ended(BaseInstance *, int, QProcess::ExitStatus)), this, connect(mcproc, SIGNAL(ended(BaseInstance *, int, QProcess::ExitStatus)), this,
SLOT(onEnded(BaseInstance *, int, QProcess::ExitStatus))); SLOT(onEnded(BaseInstance *, int, QProcess::ExitStatus)));
connect(mcproc, SIGNAL(prelaunch_failed(BaseInstance*,int,QProcess::ExitStatus)), this, connect(mcproc, SIGNAL(prelaunch_failed(BaseInstance *, int, QProcess::ExitStatus)), this,
SLOT(onEnded(BaseInstance *, int, QProcess::ExitStatus))); SLOT(onEnded(BaseInstance *, int, QProcess::ExitStatus)));
connect(mcproc, SIGNAL(launch_failed(BaseInstance*)), this, connect(mcproc, SIGNAL(launch_failed(BaseInstance *)), this,
SLOT(onLaunchFailed(BaseInstance*))); SLOT(onLaunchFailed(BaseInstance *)));
restoreState(QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowState").toByteArray())); restoreState(
restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowGeometry").toByteArray())); QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowState").toByteArray()));
restoreGeometry(
QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowGeometry").toByteArray()));
QString iconKey = proc->instance()->iconKey();
QString name = proc->instance()->name();
auto icon = MMC->icons()->getIcon(iconKey);
setWindowIcon(icon);
m_trayIcon = new QSystemTrayIcon(icon, this);
QString consoleTitle = tr("Console window for ") + name;
m_trayIcon->setToolTip(consoleTitle);
setWindowTitle(consoleTitle);
connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
m_trayIcon->show();
if (mcproc->instance()->settings().get("ShowConsole").toBool()) if (mcproc->instance()->settings().get("ShowConsole").toBool())
{ {
show(); show();
@ -55,13 +71,26 @@ ConsoleWindow::~ConsoleWindow()
delete ui; delete ui;
} }
void ConsoleWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
switch (reason)
{
case QSystemTrayIcon::Trigger:
{
toggleConsole();
}
default:
return;
}
}
void ConsoleWindow::writeColor(QString text, const char *color) void ConsoleWindow::writeColor(QString text, const char *color)
{ {
// append a paragraph // append a paragraph
QString newtext; QString newtext;
newtext += "<span style=\""; newtext += "<span style=\"";
{ {
if(color) if (color)
newtext += QString("color:") + color + ";"; newtext += QString("color:") + color + ";";
newtext += "font-family: monospace;"; newtext += "font-family: monospace;";
} }
@ -76,16 +105,17 @@ void ConsoleWindow::write(QString data, MessageLevel::Enum mode)
QScrollBar *bar = ui->text->verticalScrollBar(); QScrollBar *bar = ui->text->verticalScrollBar();
int max_bar = bar->maximum(); int max_bar = bar->maximum();
int val_bar = bar->value(); int val_bar = bar->value();
if(m_scroll_active) if(isVisible())
{ {
if(m_last_scroll_value > val_bar) if (m_scroll_active)
m_scroll_active = false; {
m_scroll_active = (max_bar - val_bar) <= 1;
} }
else else
{ {
m_scroll_active = val_bar == max_bar; m_scroll_active = val_bar == max_bar;
} }
}
if (data.endsWith('\n')) if (data.endsWith('\n'))
data = data.left(data.length() - 1); data = data.left(data.length() - 1);
QStringList paragraphs = data.split('\n'); QStringList paragraphs = data.split('\n');
@ -114,11 +144,14 @@ void ConsoleWindow::write(QString data, MessageLevel::Enum mode)
else else
while (iter.hasNext()) while (iter.hasNext())
writeColor(iter.next()); writeColor(iter.next());
if(m_scroll_active) if(isVisible())
{
if (m_scroll_active)
{ {
bar->setValue(bar->maximum()); bar->setValue(bar->maximum());
} }
m_last_scroll_value = bar->value(); m_last_scroll_value = bar->value();
}
} }
void ConsoleWindow::clear() void ConsoleWindow::clear()
@ -134,22 +167,45 @@ void ConsoleWindow::on_closeButton_clicked()
void ConsoleWindow::setMayClose(bool mayclose) void ConsoleWindow::setMayClose(bool mayclose)
{ {
m_mayclose = mayclose; m_mayclose = mayclose;
if (mayclose) }
ui->closeButton->setEnabled(true);
void ConsoleWindow::toggleConsole()
{
QScrollBar *bar = ui->text->verticalScrollBar();
if (isVisible())
{
int max_bar = bar->maximum();
int val_bar = m_last_scroll_value = bar->value();
m_scroll_active = (max_bar - val_bar) <= 1;
hide();
}
else else
ui->closeButton->setEnabled(false); {
show();
if (m_scroll_active)
{
bar->setValue(bar->maximum());
}
else
{
bar->setValue(m_last_scroll_value);
}
}
} }
void ConsoleWindow::closeEvent(QCloseEvent *event) void ConsoleWindow::closeEvent(QCloseEvent *event)
{ {
if (!m_mayclose) if (!m_mayclose)
event->ignore(); {
toggleConsole();
}
else else
{ {
MMC->settings()->set("ConsoleWindowState", saveState().toBase64()); MMC->settings()->set("ConsoleWindowState", saveState().toBase64());
MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64()); MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
emit isClosing(); emit isClosing();
m_trayIcon->hide();
QMainWindow::closeEvent(event); QMainWindow::closeEvent(event);
} }
} }
@ -170,19 +226,26 @@ void ConsoleWindow::on_btnKillMinecraft_clicked()
void ConsoleWindow::onEnded(BaseInstance *instance, int code, QProcess::ExitStatus status) void ConsoleWindow::onEnded(BaseInstance *instance, int code, QProcess::ExitStatus status)
{ {
bool peacefulExit = code == 0 && status != QProcess::CrashExit;
ui->btnKillMinecraft->setEnabled(false); ui->btnKillMinecraft->setEnabled(false);
setMayClose(true); setMayClose(true);
if (instance->settings().get("AutoCloseConsole").toBool()) if (instance->settings().get("AutoCloseConsole").toBool())
{ {
if (code == 0 && status != QProcess::CrashExit) if (peacefulExit)
{ {
this->close(); this->close();
return; return;
} }
} }
if(!isVisible()) /*
if(!peacefulExit)
{
m_trayIcon->showMessage(tr("Oh no!"), tr("Minecraft crashed!"), QSystemTrayIcon::Critical);
}
*/
if (!isVisible())
show(); show();
} }
@ -192,7 +255,7 @@ void ConsoleWindow::onLaunchFailed(BaseInstance *instance)
setMayClose(true); setMayClose(true);
if(!isVisible()) if (!isVisible())
show(); show();
} }
@ -200,10 +263,11 @@ void ConsoleWindow::on_btnPaste_clicked()
{ {
auto text = ui->text->toPlainText(); auto text = ui->text->toPlainText();
ProgressDialog dialog(this); ProgressDialog dialog(this);
PasteUpload* paste=new PasteUpload(this, text); PasteUpload *paste = new PasteUpload(this, text);
dialog.exec(paste); dialog.exec(paste);
if(!paste->successful()) if (!paste->successful())
{ {
CustomMessageBox::selectable(this, "Upload failed", paste->failReason(), QMessageBox::Critical)->exec(); CustomMessageBox::selectable(this, "Upload failed", paste->failReason(),
QMessageBox::Critical)->exec();
} }
} }

View File

@ -16,6 +16,7 @@
#pragma once #pragma once
#include <QMainWindow> #include <QMainWindow>
#include <QSystemTrayIcon>
#include "logic/MinecraftProcess.h" #include "logic/MinecraftProcess.h"
namespace Ui namespace Ui
@ -77,7 +78,8 @@ slots:
// failures) // failures)
void on_btnPaste_clicked(); void on_btnPaste_clicked();
void iconActivated(QSystemTrayIcon::ActivationReason);
void toggleConsole();
protected: protected:
void closeEvent(QCloseEvent *); void closeEvent(QCloseEvent *);
@ -87,4 +89,6 @@ private:
bool m_mayclose = true; bool m_mayclose = true;
int m_last_scroll_value = 0; int m_last_scroll_value = 0;
bool m_scroll_active = true; bool m_scroll_active = true;
QSystemTrayIcon *m_trayIcon = nullptr;
int m_saved_offset = 0;
}; };

View File

@ -99,7 +99,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
{ {
MultiMCPlatform::fixWM_CLASS(this); MultiMCPlatform::fixWM_CLASS(this);
ui->setupUi(this); ui->setupUi(this);
setWindowTitle(QString("MultiMC %1").arg(MMC->version().toString()));
QString winTitle = QString("MultiMC 5 - Version %1").arg(MMC->version().toString());
if (!MMC->version().platform.isEmpty())
winTitle += " on " + MMC->version().platform;
setWindowTitle(winTitle);
// OSX magic. // OSX magic.
// setUnifiedTitleAndToolBarOnMac(true); // setUnifiedTitleAndToolBarOnMac(true);
@ -289,24 +293,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
this, &MainWindow::notificationsChanged); this, &MainWindow::notificationsChanged);
} }
const QString currentInstanceId = MMC->settings()->get("SelectedInstance").toString(); setSelectedInstanceById(MMC->settings()->get("SelectedInstance").toString());
if (!currentInstanceId.isNull())
{
const QModelIndex index = MMC->instances()->getInstanceIndexById(currentInstanceId);
if (index.isValid())
{
const QModelIndex mappedIndex = proxymodel->mapFromSource(index);
view->setCurrentIndex(mappedIndex);
}
else
{
view->setCurrentIndex(proxymodel->index(0, 0));
}
}
else
{
view->setCurrentIndex(proxymodel->index(0, 0));
}
// removing this looks stupid // removing this looks stupid
view->setFocus(); view->setFocus();
@ -788,6 +775,20 @@ void MainWindow::updateInstanceToolIcon(QString new_icon)
ui->actionChangeInstIcon->setIcon(MMC->icons()->getIcon(m_currentInstIcon)); ui->actionChangeInstIcon->setIcon(MMC->icons()->getIcon(m_currentInstIcon));
} }
void MainWindow::setSelectedInstanceById(const QString &id)
{
QModelIndex selectionIndex = proxymodel->index(0, 0);
if (!id.isNull())
{
const QModelIndex index = MMC->instances()->getInstanceIndexById(id);
if (index.isValid())
{
selectionIndex = proxymodel->mapFromSource(index);
}
}
view->selectionModel()->setCurrentIndex(selectionIndex, QItemSelectionModel::ClearAndSelect);
}
void MainWindow::on_actionChangeInstGroup_triggered() void MainWindow::on_actionChangeInstGroup_triggered()
{ {
if (!m_selectedInstance) if (!m_selectedInstance)
@ -1274,12 +1275,16 @@ void MainWindow::instanceChanged(const QModelIndex &current, const QModelIndex &
void MainWindow::selectionBad() void MainWindow::selectionBad()
{ {
// start by reseting everything...
m_selectedInstance = nullptr; m_selectedInstance = nullptr;
statusBar()->clearMessage(); statusBar()->clearMessage();
ui->instanceToolBar->setEnabled(false); ui->instanceToolBar->setEnabled(false);
renameButton->setText(tr("Rename Instance")); renameButton->setText(tr("Rename Instance"));
updateInstanceToolIcon("infinity"); updateInstanceToolIcon("infinity");
// ...and then see if we can enable the previously selected instance
setSelectedInstanceById(MMC->settings()->get("SelectedInstance").toString());
} }
void MainWindow::on_actionEditInstNotes_triggered() void MainWindow::on_actionEditInstNotes_triggered()

View File

@ -179,6 +179,8 @@ protected:
void setCatBackground(bool enabled); void setCatBackground(bool enabled);
void updateInstanceToolIcon(QString new_icon); void updateInstanceToolIcon(QString new_icon);
void setSelectedInstanceById(const QString &id);
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
KCategoryDrawer *drawer; KCategoryDrawer *drawer;

View File

@ -25,7 +25,22 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia
ui->setupUi(this); ui->setupUi(this);
ui->icon->setPixmap(QIcon(":/icons/multimc/scalable/apps/multimc.svg").pixmap(64)); ui->icon->setPixmap(QIcon(":/icons/multimc/scalable/apps/multimc.svg").pixmap(64));
ui->title->setText("MultiMC " + MMC->version().toString()); ui->title->setText("MultiMC 5 " + MMC->version().toString());
ui->versionLabel->setText(tr("Version") +": " + MMC->version().toString());
ui->vtypeLabel->setText(tr("Version Type") +": " + MMC->version().typeName());
ui->platformLabel->setText(tr("Platform") +": " + MMC->version().platform);
if (MMC->version().build >= 0)
ui->buildNumLabel->setText(tr("Build Number") +": " + QString::number(MMC->version().build));
else
ui->buildNumLabel->setVisible(false);
if (!MMC->version().channel.isEmpty())
ui->channelLabel->setText(tr("Channel") +": " + MMC->version().channel);
else
ui->channelLabel->setVisible(false);
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close())); connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
MMC->connect(ui->aboutQt, SIGNAL(clicked()), SLOT(aboutQt())); MMC->connect(ui->aboutQt, SIGNAL(clicked()), SLOT(aboutQt()));

View File

@ -86,7 +86,7 @@
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>MultiMC</string> <string>MultiMC 5</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignCenter</set> <set>Qt::AlignCenter</set>
@ -103,14 +103,64 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>685</width> <width>689</width>
<height>304</height> <height>331</height>
</rect> </rect>
</property> </property>
<attribute name="label"> <attribute name="label">
<string>About</string> <string>About</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="versionLabel">
<property name="text">
<string>Version:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="vtypeLabel">
<property name="text">
<string>Version Type:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="platformLabel">
<property name="text">
<string>Platform:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="buildNumLabel">
<property name="text">
<string>Build Number:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="channelLabel">
<property name="text">
<string>Channel:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="aboutLabel"> <widget class="QLabel" name="aboutLabel">
<property name="enabled"> <property name="enabled">
@ -158,6 +208,19 @@
</property> </property>
</widget> </widget>
</item> </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> </layout>
</widget> </widget>
<widget class="QWidget" name="creditsPage"> <widget class="QWidget" name="creditsPage">
@ -165,8 +228,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>685</width> <width>689</width>
<height>304</height> <height>331</height>
</rect> </rect>
</property> </property>
<attribute name="label"> <attribute name="label">
@ -182,19 +245,19 @@
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt; &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Andrew Okin &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:forkk@forkk.net&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;forkk@forkk.net&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Andrew Okin &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:forkk@forkk.net&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;forkk@forkk.net&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Petr Mrázek &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:peterix@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;peterix@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Petr Mrázek &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:peterix@gmail.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;peterix@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Sky &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://www.twitter.com/drayshak&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@drayshak&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Sky &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://www.twitter.com/drayshak&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@drayshak&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Ubuntu'; font-size:10pt; font-weight:600;&quot;&gt;With thanks to&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Ubuntu'; font-size:10pt; font-weight:600;&quot;&gt;With thanks to&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Orochimarufan &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:orochimarufan.x3@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;orochimarufan.x3@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Orochimarufan &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:orochimarufan.x3@gmail.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;orochimarufan.x3@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;TakSuyu &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:taksuyu@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;taksuyu@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;TakSuyu &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:taksuyu@gmail.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;taksuyu@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Kilobyte &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:stiepen22@gmx.de&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;stiepen22@gmx.de&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Kilobyte &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:stiepen22@gmx.de&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;stiepen22@gmx.de&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Jan (02JanDal) &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:02jandal@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;02jandal@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Jan (02JanDal) &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:02jandal@gmail.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;02jandal@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Robotbrain &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/skylordelros&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@skylordelros&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Robotbrain &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/skylordelros&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@skylordelros&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Rootbear75 &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/rootbear75&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@rootbear75&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt; (build server)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Rootbear75 &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/rootbear75&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@rootbear75&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt; (build server)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="textInteractionFlags"> <property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
@ -218,8 +281,8 @@ p, li { white-space: pre-wrap; }
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>684</width> <width>689</width>
<height>290</height> <height>331</height>
</rect> </rect>
</property> </property>
<attribute name="label"> <attribute name="label">
@ -246,7 +309,7 @@ p, li { white-space: pre-wrap; }
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt; &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans Mono'; font-size:7.8pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans Mono'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt; &lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Copyright 2012-2014 MultiMC Contributors&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Copyright 2012-2014 MultiMC Contributors&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;);&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;);&lt;/span&gt;&lt;/p&gt;
@ -378,8 +441,8 @@ p, li { white-space: pre-wrap; }
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>684</width> <width>689</width>
<height>290</height> <height>331</height>
</rect> </rect>
</property> </property>
<attribute name="label"> <attribute name="label">
@ -392,7 +455,7 @@ p, li { white-space: pre-wrap; }
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt; &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;Part of the reason for using the Apache license is we don't want people using the &amp;quot;MultiMC&amp;quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &amp;quot;MultiMC&amp;quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;Part of the reason for using the Apache license is we don't want people using the &amp;quot;MultiMC&amp;quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &amp;quot;MultiMC&amp;quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).&lt;/span&gt;&lt;/p&gt;

View File

@ -61,6 +61,7 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Se
{ {
MMC->updateChecker()->updateChanList(); MMC->updateChecker()->updateChanList();
} }
connect(ui->proxyGroup, SIGNAL(buttonClicked(int)), SLOT(proxyChanged(int)));
} }
SettingsDialog::~SettingsDialog() SettingsDialog::~SettingsDialog()
@ -83,6 +84,8 @@ void SettingsDialog::updateCheckboxStuff()
{ {
ui->windowWidthSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked()); ui->windowWidthSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
ui->windowHeightSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked()); ui->windowHeightSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
ui->proxyAddrBox->setEnabled(!ui->proxyNoneBtn->isChecked() && !ui->proxyDefaultBtn->isChecked());
ui->proxyAuthBox->setEnabled(!ui->proxyNoneBtn->isChecked() && !ui->proxyDefaultBtn->isChecked());
} }
void SettingsDialog::on_ftbLauncherBrowseBtn_clicked() void SettingsDialog::on_ftbLauncherBrowseBtn_clicked()
@ -202,6 +205,9 @@ void SettingsDialog::on_buttonBox_accepted()
{ {
applySettings(MMC->settings().get()); applySettings(MMC->settings().get());
// Apply proxy settings
MMC->updateProxySettings();
MMC->settings()->set("SettingsGeometry", saveGeometry().toBase64()); MMC->settings()->set("SettingsGeometry", saveGeometry().toBase64());
} }
@ -210,6 +216,11 @@ void SettingsDialog::on_buttonBox_rejected()
MMC->settings()->set("SettingsGeometry", saveGeometry().toBase64()); MMC->settings()->set("SettingsGeometry", saveGeometry().toBase64());
} }
void SettingsDialog::proxyChanged(int)
{
updateCheckboxStuff();
}
void SettingsDialog::refreshUpdateChannelList() void SettingsDialog::refreshUpdateChannelList()
{ {
// Stop listening for selection changes. It's going to change a lot while we update it and we don't need to update the // Stop listening for selection changes. It's going to change a lot while we update it and we don't need to update the
@ -310,6 +321,19 @@ void SettingsDialog::applySettings(SettingsObject *s)
s->set("MinecraftWinWidth", ui->windowWidthSpinBox->value()); s->set("MinecraftWinWidth", ui->windowWidthSpinBox->value());
s->set("MinecraftWinHeight", ui->windowHeightSpinBox->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 // Memory
s->set("MinMemAlloc", ui->minMemSpinBox->value()); s->set("MinMemAlloc", ui->minMemSpinBox->value());
s->set("MaxMemAlloc", ui->maxMemSpinBox->value()); s->set("MaxMemAlloc", ui->maxMemSpinBox->value());
@ -384,6 +408,18 @@ void SettingsDialog::loadSettings(SettingsObject *s)
ui->sortByNameBtn->setChecked(true); 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 // Java Settings
ui->javaPathTextBox->setText(s->get("JavaPath").toString()); ui->javaPathTextBox->setText(s->get("JavaPath").toString());
ui->jvmArgsTextBox->setText(s->get("JvmArgs").toString()); ui->jvmArgsTextBox->setText(s->get("JvmArgs").toString());
@ -447,4 +483,3 @@ void SettingsDialog::checkFinished(JavaCheckResult result)
"or set the path to the java executable.")); "or set the path to the java executable."));
} }
} }

View File

@ -86,6 +86,7 @@ slots:
void refreshUpdateChannelDesc(); void refreshUpdateChannelDesc();
void updateChannelSelectionChanged(int index); void updateChannelSelectionChanged(int index);
void proxyChanged(int);
private: private:
Ui::SettingsDialog *ui; Ui::SettingsDialog *ui;

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>526</width> <width>526</width>
<height>639</height> <height>723</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -106,6 +106,9 @@
<property name="text"> <property name="text">
<string>No channel selected.</string> <string>No channel selected.</string>
</property> </property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -424,6 +427,165 @@
</item> </item>
</layout> </layout>
</widget> </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="javaTab"> <widget class="QWidget" name="javaTab">
<attribute name="title"> <attribute name="title">
<string>Java</string> <string>Java</string>
@ -736,6 +898,7 @@
</connection> </connection>
</connections> </connections>
<buttongroups> <buttongroups>
<buttongroup name="proxyGroup"/>
<buttongroup name="sortingModeGroup"/> <buttongroup name="sortingModeGroup"/>
</buttongroups> </buttongroups>
</ui> </ui>

View File

@ -1,26 +1,20 @@
#include "JavaChecker.h" #include "JavaChecker.h"
#include "MultiMC.h"
#include <pathutils.h>
#include <QFile> #include <QFile>
#include <QProcess> #include <QProcess>
#include <QMap> #include <QMap>
#include <QTemporaryFile> #include <QTemporaryFile>
#define CHECKER_FILE "JavaChecker.jar"
JavaChecker::JavaChecker(QObject *parent) : QObject(parent) JavaChecker::JavaChecker(QObject *parent) : QObject(parent)
{ {
} }
void JavaChecker::performCheck() void JavaChecker::performCheck()
{ {
checkerJar.setFileTemplate("checker_XXXXXX.jar"); QString checkerJar = PathCombine(MMC->bin(), "jars", "JavaCheck.jar");
checkerJar.open();
QFile inner(":/java/checker.jar");
inner.open(QIODevice::ReadOnly);
checkerJar.write(inner.readAll());
inner.close();
checkerJar.close();
QStringList args = {"-jar", checkerJar.fileName()}; QStringList args = {"-jar", checkerJar};
process.reset(new QProcess()); process.reset(new QProcess());
process->setArguments(args); process->setArguments(args);
@ -42,11 +36,11 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
killTimer.stop(); killTimer.stop();
QProcessPtr _process; QProcessPtr _process;
_process.swap(process); _process.swap(process);
checkerJar.remove();
JavaCheckResult result; JavaCheckResult result;
{ {
result.path = path; result.path = path;
result.id = id;
} }
if (status == QProcess::CrashExit || exitcode == 1) if (status == QProcess::CrashExit || exitcode == 1)
@ -99,11 +93,11 @@ void JavaChecker::error(QProcess::ProcessError err)
if(err == QProcess::FailedToStart) if(err == QProcess::FailedToStart)
{ {
killTimer.stop(); killTimer.stop();
checkerJar.remove();
JavaCheckResult result; JavaCheckResult result;
{ {
result.path = path; result.path = path;
result.id = id;
} }
emit checkFinished(result); emit checkFinished(result);

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include <QProcess> #include <QProcess>
#include <QTimer> #include <QTimer>
#include <QTemporaryFile>
#include <memory> #include <memory>
class JavaChecker; class JavaChecker;
@ -15,6 +14,7 @@ struct JavaCheckResult
QString javaVersion; QString javaVersion;
bool valid = false; bool valid = false;
bool is_64bit = false; bool is_64bit = false;
int id;
}; };
typedef std::shared_ptr<QProcess> QProcessPtr; typedef std::shared_ptr<QProcess> QProcessPtr;
@ -27,13 +27,13 @@ public:
void performCheck(); void performCheck();
QString path; QString path;
int id;
signals: signals:
void checkFinished(JavaCheckResult result); void checkFinished(JavaCheckResult result);
private: private:
QProcessPtr process; QProcessPtr process;
QTimer killTimer; QTimer killTimer;
QTemporaryFile checkerJar;
public public
slots: slots:
void timeout(); void timeout();

View File

@ -26,10 +26,7 @@ void JavaCheckerJob::partFinished(JavaCheckResult result)
<< javacheckers.size(); << javacheckers.size();
emit progress(num_finished, javacheckers.size()); emit progress(num_finished, javacheckers.size());
javaresults.append(result); javaresults.replace(result.id, result);
int result_size = javacheckers.size();
emit progress(num_finished, result_size);
if (num_finished == javacheckers.size()) if (num_finished == javacheckers.size())
{ {
@ -43,6 +40,7 @@ void JavaCheckerJob::start()
m_running = true; m_running = true;
for (auto iter : javacheckers) for (auto iter : javacheckers)
{ {
javaresults.append(JavaCheckResult());
connect(iter.get(), SIGNAL(checkFinished(JavaCheckResult)), SLOT(partFinished(JavaCheckResult))); connect(iter.get(), SIGNAL(checkFinished(JavaCheckResult)), SLOT(partFinished(JavaCheckResult)));
iter->performCheck(); iter->performCheck();
} }

View File

@ -31,8 +31,6 @@
#include "gui/dialogs/LegacyModEditDialog.h" #include "gui/dialogs/LegacyModEditDialog.h"
#define LAUNCHER_FILE "MultiMCLauncher.jar"
LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings, LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings,
QObject *parent) QObject *parent)
: BaseInstance(new LegacyInstancePrivate(), rootDir, settings, parent) : BaseInstance(new LegacyInstancePrivate(), rootDir, settings, parent)
@ -61,7 +59,7 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account)
pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG"); pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG");
// extract the legacy launcher // extract the legacy launcher
QFile(":/java/launcher.jar").copy(PathCombine(minecraftRoot(), LAUNCHER_FILE)); QString launcherJar = PathCombine(MMC->bin(), "jars", "MultiMCLauncher.jar");
// set the process arguments // set the process arguments
{ {
@ -104,7 +102,7 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account)
"minecraft.exe.heapdump"); "minecraft.exe.heapdump");
#endif #endif
args << "-jar" << LAUNCHER_FILE; args << "-jar" << launcherJar;
args << account->currentProfile()->name; args << account->currentProfile()->name;
args << account->sessionId(); args << account->sessionId();
args << windowTitle; args << windowTitle;

View File

@ -182,13 +182,17 @@ void JavaListLoadTask::executeTask()
connect(m_job.get(), SIGNAL(progress(int, int)), this, SLOT(checkerProgress(int, int))); connect(m_job.get(), SIGNAL(progress(int, int)), this, SLOT(checkerProgress(int, int)));
QLOG_DEBUG() << "Probing the following Java paths: "; QLOG_DEBUG() << "Probing the following Java paths: ";
int id = 0;
for(QString candidate : candidate_paths) for(QString candidate : candidate_paths)
{ {
QLOG_DEBUG() << " " << candidate; QLOG_DEBUG() << " " << candidate;
auto candidate_checker = new JavaChecker(); auto candidate_checker = new JavaChecker();
candidate_checker->path = candidate; candidate_checker->path = candidate;
candidate_checker->id = id;
m_job->addJavaCheckerAction(JavaCheckerPtr(candidate_checker)); m_job->addJavaCheckerAction(JavaCheckerPtr(candidate_checker));
id++;
} }
m_job->start(); m_job->start();

View File

@ -5,8 +5,8 @@
#include <QJsonArray> #include <QJsonArray>
#include "MultiMC.h" #include "MultiMC.h"
#include "MultiMCVersion.h"
#include "logic/net/CacheDownload.h" #include "logic/net/CacheDownload.h"
#include "config.h"
NotificationChecker::NotificationChecker(QObject *parent) NotificationChecker::NotificationChecker(QObject *parent)
: QObject(parent), m_notificationsUrl(QUrl(NOTIFICATION_URL)) : QObject(parent), m_notificationsUrl(QUrl(NOTIFICATION_URL))
@ -66,7 +66,7 @@ void NotificationChecker::downloadSucceeded(int)
entry.id = obj.value("id").toDouble(); entry.id = obj.value("id").toDouble();
entry.message = obj.value("message").toString(); entry.message = obj.value("message").toString();
entry.channel = obj.value("channel").toString(); entry.channel = obj.value("channel").toString();
entry.buildtype = obj.value("buildtype").toString(); entry.platform = obj.value("platform").toString();
entry.from = obj.value("from").toString(); entry.from = obj.value("from").toString();
entry.to = obj.value("to").toString(); entry.to = obj.value("to").toString();
const QString type = obj.value("type").toString("critical"); const QString type = obj.value("type").toString("critical");
@ -93,13 +93,14 @@ void NotificationChecker::downloadSucceeded(int)
bool NotificationChecker::NotificationEntry::applies() const bool NotificationChecker::NotificationEntry::applies() const
{ {
bool channelApplies = channel.isEmpty() || channel == VERSION_CHANNEL; MultiMCVersion version = MMC->version();
bool buildtypeApplies = buildtype.isEmpty() || buildtype == VERSION_BUILD_TYPE; bool channelApplies = channel.isEmpty() || channel == version.channel;
bool platformApplies = platform.isEmpty() || platform == version.platform;
bool fromApplies = bool fromApplies =
from.isEmpty() || from == FULL_VERSION_STR || !versionLessThan(FULL_VERSION_STR, from); from.isEmpty() || from == FULL_VERSION_STR || !versionLessThan(FULL_VERSION_STR, from);
bool toApplies = bool toApplies =
to.isEmpty() || to == FULL_VERSION_STR || !versionLessThan(to, FULL_VERSION_STR); to.isEmpty() || to == FULL_VERSION_STR || !versionLessThan(to, FULL_VERSION_STR);
return channelApplies && buildtypeApplies && fromApplies && toApplies; return channelApplies && platformApplies && fromApplies && toApplies;
} }
bool NotificationChecker::NotificationEntry::versionLessThan(const QString &v1, bool NotificationChecker::NotificationEntry::versionLessThan(const QString &v1,

View File

@ -26,7 +26,7 @@ public:
Information Information
} type; } type;
QString channel; QString channel;
QString buildtype; QString platform;
QString from; QString from;
QString to; QString to;
bool applies() const; bool applies() const;

View File

@ -142,8 +142,6 @@ void UpdateChecker::updateCheckFinished(bool notifyNoUpdate)
if (newestVersion.value("Id").toVariant().toInt() < if (newestVersion.value("Id").toVariant().toInt() <
version.value("Id").toVariant().toInt()) version.value("Id").toVariant().toInt())
{ {
QLOG_DEBUG() << "Found newer version with ID"
<< version.value("Id").toVariant().toInt();
newestVersion = version; newestVersion = version;
} }
} }
@ -153,6 +151,7 @@ void UpdateChecker::updateCheckFinished(bool notifyNoUpdate)
int newBuildNumber = newestVersion.value("Id").toVariant().toInt(); int newBuildNumber = newestVersion.value("Id").toVariant().toInt();
if (newBuildNumber != MMC->version().build) if (newBuildNumber != MMC->version().build)
{ {
QLOG_DEBUG() << "Found newer version with ID" << newBuildNumber;
// Update! // Update!
emit updateAvailable(m_repoUrl, newestVersion.value("Name").toVariant().toString(), emit updateAvailable(m_repoUrl, newestVersion.value("Name").toVariant().toString(),
newBuildNumber); newBuildNumber);
@ -262,3 +261,4 @@ void UpdateChecker::chanListDownloadFailed()
QLOG_ERROR() << "Failed to download channel list."; QLOG_ERROR() << "Failed to download channel list.";
emit channelListLoaded(); emit channelListLoaded();
} }