summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore14
-rw-r--r--CMakeLists.txt201
-rw-r--r--MultiMC.cpp166
-rw-r--r--MultiMC.h12
-rw-r--r--MultiMCVersion.h79
-rw-r--r--changelog.yaml19
-rw-r--r--config.h.in12
-rw-r--r--depends/javacheck/.gitignore6
-rw-r--r--depends/javacheck/CMakeLists.txt5
-rw-r--r--depends/launcher/.gitignore6
-rw-r--r--depends/launcher/CMakeLists.txt24
-rw-r--r--depends/launcher/MultiMCLauncher.java331
-rw-r--r--depends/launcher/net/minecraft/Launcher.java44
-rw-r--r--depends/launcher/org/multimc/EntryPoint.java135
-rw-r--r--depends/launcher/org/multimc/IconLoader.java132
-rw-r--r--depends/launcher/org/multimc/Launcher.java22
-rw-r--r--depends/launcher/org/multimc/NotFoundException.java21
-rw-r--r--depends/launcher/org/multimc/ParamBucket.java86
-rw-r--r--depends/launcher/org/multimc/ParseException.java22
-rw-r--r--depends/launcher/org/multimc/Utils.java179
-rw-r--r--depends/launcher/org/multimc/legacy/LegacyFrame.java (renamed from depends/launcher/MCFrame.java)58
-rw-r--r--depends/launcher/org/multimc/legacy/LegacyLauncher.java178
-rw-r--r--depends/launcher/org/multimc/onesix/OneSixLauncher.java210
-rw-r--r--generated.qrc.in6
-rw-r--r--gui/ConsoleWindow.cpp125
-rw-r--r--gui/ConsoleWindow.h6
-rw-r--r--gui/MainWindow.cpp133
-rw-r--r--gui/MainWindow.h13
-rw-r--r--gui/dialogs/AboutDialog.cpp19
-rw-r--r--gui/dialogs/AboutDialog.ui150
-rw-r--r--gui/dialogs/InstanceSettings.ui18
-rw-r--r--gui/dialogs/ModEditDialogCommon.cpp4
-rw-r--r--gui/dialogs/SettingsDialog.cpp57
-rw-r--r--gui/dialogs/SettingsDialog.h1
-rw-r--r--gui/dialogs/SettingsDialog.ui343
-rw-r--r--install_prereqs.cmake.in2
-rw-r--r--logic/BaseInstance.cpp13
-rw-r--r--logic/BaseInstance.h7
-rw-r--r--logic/BaseVersion.h9
-rw-r--r--logic/JavaChecker.cpp31
-rw-r--r--logic/JavaChecker.h4
-rw-r--r--logic/JavaCheckerJob.cpp6
-rw-r--r--logic/LegacyFTBInstance.cpp5
-rw-r--r--logic/LegacyFTBInstance.h1
-rw-r--r--logic/LegacyInstance.cpp59
-rw-r--r--logic/MinecraftProcess.cpp256
-rw-r--r--logic/MinecraftProcess.h32
-rw-r--r--logic/NagUtils.cpp18
-rw-r--r--logic/OneSixFTBInstance.cpp5
-rw-r--r--logic/OneSixFTBInstance.h2
-rw-r--r--logic/OneSixInstance.cpp121
-rw-r--r--logic/OneSixLibrary.cpp87
-rw-r--r--logic/OneSixLibrary.h3
-rw-r--r--logic/OneSixUpdate.cpp151
-rw-r--r--logic/OneSixUpdate.h8
-rw-r--r--logic/auth/MojangAccount.cpp6
-rw-r--r--logic/lists/ForgeVersionList.cpp12
-rw-r--r--logic/lists/ForgeVersionList.h21
-rw-r--r--logic/lists/InstanceList.cpp73
-rw-r--r--logic/lists/JavaVersionList.cpp4
-rw-r--r--logic/net/CacheDownload.cpp125
-rw-r--r--logic/net/CacheDownload.h15
-rw-r--r--logic/net/URLConstants.h2
-rw-r--r--logic/status/StatusChecker.cpp137
-rw-r--r--logic/status/StatusChecker.h57
-rw-r--r--logic/updater/NotificationChecker.cpp13
-rw-r--r--logic/updater/NotificationChecker.h2
-rw-r--r--logic/updater/UpdateChecker.cpp4
-rw-r--r--main.cpp1
-rw-r--r--translations/mmc_de.ts1828
70 files changed, 4446 insertions, 1511 deletions
diff --git a/.gitignore b/.gitignore
index 54bd5039..2ef0d673 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,17 +1,23 @@
Thumbs.db
.kdev4
-MultiMC5.kdev4
-MultiMC.pro.user
-CMakeLists.txt.user
.user
.directory
-build
resources/CMakeFiles
resources/MultiMCLauncher.jar
*~
*.swp
html/
+# Project Files
+MultiMC5.kdev4
+MultiMC.pro.user
+CMakeLists.txt.user
+CMakeLists.txt.user.*
+
+# Build dirs
+build
+/build-*
+
# Ctags File
tags
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1a9bd32c..c0a4439b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -25,6 +25,8 @@ IF(UNIX)
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
ENDIF()
+set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/jars)
+
######## Set compiler flags ########
IF(APPLE)
message(STATUS "Using APPLE CMAKE_CXX_FLAGS")
@@ -38,9 +40,7 @@ ELSEIF(MINGW)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall")
ENDIF()
-################################ INCLUDE LIBRARIES ################################
-
-######## 3rd Party Libs ########
+################################ 3rd Party Libs ################################
# Find the required Qt parts
find_package(Qt5Core REQUIRED)
@@ -75,41 +75,6 @@ query_qmake(QT_HOST_DATA QT_DATA_DIR)
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 ################################
######## Check endianness ########
@@ -127,13 +92,17 @@ SET(MultiMC_NEWS_RSS_URL "http://multimc.org/rss.xml" CACHE STRING "URL to fetch
######## Set version numbers ########
SET(MultiMC_VERSION_MAJOR 0)
-SET(MultiMC_VERSION_MINOR 0)
+SET(MultiMC_VERSION_MINOR 1)
+SET(MultiMC_VERSION_HOTFIX 1)
# Build number
SET(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
-# Build 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').")
+# Version type
+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
SET(MultiMC_VERSION_CHANNEL "" CACHE STRING "The current build's channel. Included in the version string.")
@@ -147,19 +116,29 @@ SET(MultiMC_UPDATER false CACHE BOOL "Whether or not the update system is enable
# Notification URL
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.
-SET(MultiMC_VERSION_STRING "5.${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}")
-IF (MultiMC_VERSION_BUILD GREATER -1)
- SET(MultiMC_VERSION_STRING "${MultiMC_VERSION_STRING}.${MultiMC_VERSION_BUILD}")
-ENDIF ()
-IF (NOT MultiMC_VERSION_CHANNEL STREQUAL "")
- SET(MultiMC_VERSION_STRING "${MultiMC_VERSION_STRING}-${MultiMC_VERSION_CHANNEL}")
-ENDIF ()
-IF (NOT MultiMC_VERSION_BUILD_TYPE STREQUAL "")
- SET(MultiMC_VERSION_STRING "${MultiMC_VERSION_STRING}-${MultiMC_VERSION_BUILD_TYPE}")
+IF (MultiMC_VERSION_TYPE STREQUAL "Custom")
+ MESSAGE(STATUS "Version Type: Custom")
+ SET(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}")
+ELSEIF (MultiMC_VERSION_TYPE STREQUAL "Release")
+ MESSAGE(STATUS "Version Type: Stable Release")
+ SET(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}")
+ELSEIF (MultiMC_VERSION_TYPE STREQUAL "ReleaseCandidate")
+ MESSAGE(STATUS "Version Type: Release Candidate")
+ 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 ()
-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 (MultiMC_UPDATER)
@@ -209,6 +188,72 @@ ADD_DEFINITIONS(-DLIBSETTINGS_STATIC)
ADD_DEFINITIONS(-DLIBUTIL_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 ################################
######## Sources and headers ########
@@ -237,7 +282,6 @@ gui/dialogs/SettingsDialog.h
gui/dialogs/SettingsDialog.cpp
gui/dialogs/CopyInstanceDialog.h
gui/dialogs/CopyInstanceDialog.cpp
-gui/dialogs/dialogs/
gui/dialogs/NewInstanceDialog.cpp
gui/dialogs/ProgressDialog.h
gui/dialogs/ProgressDialog.cpp
@@ -348,6 +392,10 @@ logic/news/NewsChecker.cpp
logic/news/NewsEntry.h
logic/news/NewsEntry.cpp
+# Status system
+logic/status/StatusChecker.h
+logic/status/StatusChecker.cpp
+
# legacy instances
logic/LegacyInstance.h
logic/LegacyInstance.cpp
@@ -489,13 +537,6 @@ ENDIF()
################################ COMPILE ################################
-# ICNS file for OS X
-IF(APPLE)
- SET(MACOSX_BUNDLE_ICON_FILE MultiMC.icns)
- SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/MultiMC.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
- SET(MULTIMC_SOURCES ${MULTIMC_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/MultiMC.icns)
-ENDIF(APPLE)
-
# Link additional libraries
IF(WIN32)
SET(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS}
@@ -516,17 +557,15 @@ IF(MultiMC_CODE_COVERAGE)
ENDIF(MultiMC_CODE_COVERAGE)
# 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/javacheck/JavaCheck.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)
# Qt 5 stuff
QT5_WRAP_UI(MULTIMC_UI ${MULTIMC_UIS})
-CONFIGURE_FILE(generated.qrc.in generated.qrc)
-QT5_ADD_RESOURCES(GENERATED_QRC ${CMAKE_CURRENT_BINARY_DIR}/generated.qrc)
QT5_ADD_RESOURCES(GRAPHICS_QRC graphics.qrc)
# Add common library
-ADD_LIBRARY(MultiMC_common STATIC ${MULTIMC_SOURCES} ${MULTIMC_UI} ${GENERATED_QRC} ${GRAPHICS_QRC})
+ADD_LIBRARY(MultiMC_common STATIC ${MULTIMC_SOURCES} ${MULTIMC_UI} ${GRAPHICS_QRC})
# Add executable
ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32 main.cpp ${MULTIMC_RCS})
@@ -536,38 +575,9 @@ TARGET_LINK_LIBRARIES(MultiMC MultiMC_common)
TARGET_LINK_LIBRARIES(MultiMC_common xz-embedded unpack200 quazip libUtil libSettings libGroupView ${MultiMC_LINK_ADDITIONAL_LIBS})
QT5_USE_MODULES(MultiMC Core Widgets Network Xml Concurrent ${MultiMC_QT_ADDITIONAL_MODULES})
QT5_USE_MODULES(MultiMC_common Core Widgets Network Xml Concurrent ${MultiMC_QT_ADDITIONAL_MODULES})
-ADD_DEPENDENCIES(MultiMC_common MultiMCLauncher JavaCheck)
################################ 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 ########
#### Executable ####
@@ -652,6 +662,11 @@ FILE(WRITE \"\${CMAKE_INSTALL_PREFIX}/${QTCONF_DEST_DIR}/qt.conf\" \"\")
COMPONENT Runtime
)
+# ICNS file for OS X
+IF(APPLE)
+ INSTALL(FILES MultiMC.icns DESTINATION MultiMC.app/Contents/Resources)
+ENDIF()
+
CONFIGURE_FILE(
"${CMAKE_CURRENT_SOURCE_DIR}/install_prereqs.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/install_prereqs.cmake"
diff --git a/MultiMC.cpp b/MultiMC.cpp
index 297d08fd..e4a30f22 100644
--- a/MultiMC.cpp
+++ b/MultiMC.cpp
@@ -20,8 +20,11 @@
#include "logic/news/NewsChecker.h"
+#include "logic/status/StatusChecker.h"
+
#include "logic/InstanceLauncher.h"
#include "logic/net/HttpMetaCache.h"
+#include "logic/net/URLConstants.h"
#include "logic/JavaUtils.h"
@@ -38,14 +41,12 @@
using namespace Util::Commandline;
MultiMC::MultiMC(int &argc, char **argv, bool root_override)
- : QApplication(argc, argv), m_version{VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD,
- VERSION_CHANNEL, VERSION_BUILD_TYPE}
+ : QApplication(argc, argv), m_version{VERSION_MAJOR, VERSION_MINOR, VERSION_HOTFIX,
+ VERSION_BUILD, MultiMCVersion::VERSION_TYPE, VERSION_CHANNEL, BUILD_PLATFORM}
{
setOrganizationName("MultiMC");
setApplicationName("MultiMC5");
- initTranslations();
-
setAttribute(Qt::AA_UseHighDpiPixmaps);
// Don't quit on hiding the last window
this->setQuitOnLastWindowClosed(false);
@@ -172,6 +173,9 @@ MultiMC::MultiMC(int &argc, char **argv, bool root_override)
// load settings
initGlobalSettings();
+ // load translations
+ initTranslations();
+
// initialize the updater
m_updateChecker.reset(new UpdateChecker());
@@ -181,6 +185,9 @@ MultiMC::MultiMC(int &argc, char **argv, bool root_override)
// initialize the news checker
m_newsChecker.reset(new NewsChecker(NEWS_RSS_URL));
+ // initialize the status checker
+ m_statusChecker.reset(new StatusChecker());
+
// and instances
auto InstDirSetting = m_settings->getSetting("InstanceDir");
m_instances.reset(new InstanceList(InstDirSetting->get().toString(), this));
@@ -198,56 +205,12 @@ MultiMC::MultiMC(int &argc, char **argv, bool root_override)
// init the http meta cache
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
m_qnam.reset(new QNetworkAccessManager(this));
+ // init proxy settings
+ updateProxySettings();
+
// launch instance, if that's what should be done
// WARNING: disabled until further notice
/*
@@ -278,18 +241,20 @@ MultiMC::~MultiMC()
void MultiMC::initTranslations()
{
+ QLocale locale(m_settings->get("Language").toString());
+ QLocale::setDefault(locale);
+ QLOG_INFO() << "Your language is" << locale.bcp47Name();
m_qt_translator.reset(new QTranslator());
- if (m_qt_translator->load("qt_" + QLocale::system().name(),
+ if (m_qt_translator->load("qt_" + locale.bcp47Name(),
QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
{
- std::cout << "Loading Qt Language File for "
- << QLocale::system().name().toLocal8Bit().constData() << "...";
+ QLOG_DEBUG() << "Loading Qt Language File for"
+ << locale.bcp47Name().toLocal8Bit().constData() << "...";
if (!installTranslator(m_qt_translator.get()))
{
- std::cout << " failed.";
+ QLOG_ERROR() << "Loading Qt Language File failed.";
m_qt_translator.reset();
}
- std::cout << std::endl;
}
else
{
@@ -297,17 +262,15 @@ void MultiMC::initTranslations()
}
m_mmc_translator.reset(new QTranslator());
- if (m_mmc_translator->load("mmc_" + QLocale::system().name(),
- QDir("translations").absolutePath()))
+ if (m_mmc_translator->load("mmc_" + locale.bcp47Name(), MMC->root() + "/translations"))
{
- std::cout << "Loading MMC Language File for "
- << QLocale::system().name().toLocal8Bit().constData() << "...";
+ QLOG_DEBUG() << "Loading MMC Language File for"
+ << locale.bcp47Name().toLocal8Bit().constData() << "...";
if (!installTranslator(m_mmc_translator.get()))
{
- std::cout << " failed.";
+ QLOG_ERROR() << "Loading MMC Language File failed.";
m_mmc_translator.reset();
}
- std::cout << std::endl;
}
else
{
@@ -410,9 +373,13 @@ void MultiMC::initGlobalSettings()
// Editors
m_settings->registerSetting("JsonEditor", QString());
+ // Language
+ m_settings->registerSetting("Language", QLocale(QLocale::system().language()).bcp47Name());
+
// Console
m_settings->registerSetting("ShowConsole", true);
m_settings->registerSetting("AutoCloseConsole", true);
+ m_settings->registerSetting("LogPrePostOutput", true);
// Console Colors
// m_settings->registerSetting("SysMessageColor", QColor(Qt::blue));
@@ -424,6 +391,13 @@ void MultiMC::initGlobalSettings()
m_settings->registerSetting({"MinecraftWinWidth", "MCWindowWidth"}, 854);
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
m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512);
m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, 1024);
@@ -467,6 +441,74 @@ void MultiMC::initHttpMetaCache()
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()
{
if (!m_icons)
diff --git a/MultiMC.h b/MultiMC.h
index d02099f3..638a442f 100644
--- a/MultiMC.h
+++ b/MultiMC.h
@@ -21,6 +21,7 @@ class JavaVersionList;
class UpdateChecker;
class NotificationChecker;
class NewsChecker;
+class StatusChecker;
#if defined(MMC)
#undef MMC
@@ -113,6 +114,11 @@ public:
return m_newsChecker;
}
+ std::shared_ptr<StatusChecker> statusChecker()
+ {
+ return m_statusChecker;
+ }
+
std::shared_ptr<LWJGLVersionList> lwjgllist();
std::shared_ptr<ForgeVersionList> forgelist();
@@ -124,6 +130,11 @@ public:
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
* specified in the settings
*/
@@ -178,6 +189,7 @@ private:
std::shared_ptr<UpdateChecker> m_updateChecker;
std::shared_ptr<NotificationChecker> m_notificationChecker;
std::shared_ptr<NewsChecker> m_newsChecker;
+ std::shared_ptr<StatusChecker> m_statusChecker;
std::shared_ptr<MojangAccountList> m_accounts;
std::shared_ptr<IconList> m_icons;
std::shared_ptr<QNetworkAccessManager> m_qnam;
diff --git a/MultiMCVersion.h b/MultiMCVersion.h
index 75e017df..811b9076 100644
--- a/MultiMCVersion.h
+++ b/MultiMCVersion.h
@@ -18,58 +18,79 @@
#include <QString>
/*!
- * \brief The Version class represents a MultiMC version number.
+ * \brief The Version class represents a MultiMC version.
*/
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.
* \return The version number in string format (major.minor.revision.build).
*/
QString toString() const
{
- QString vstr = QString("5.%1.%2").arg(
+ QString vstr = QString("%1.%2").arg(
QString::number(major),
QString::number(minor));
- if (build >= 0) vstr += "." + QString::number(build);
- if (!channel.isEmpty()) vstr += "-" + channel;
- if (!buildType.isEmpty()) vstr += "-" + buildType;
+ if (hotfix > 0) vstr += "." + QString::number(hotfix);
+
+ // 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;
}
- /*!
- * \brief The major version number.
- * This is no longer going to always be 5 for MultiMC 5. Doing so is useless.
- * Instead, we'll be starting major off at 1 and incrementing it with every major feature.
- */
+ QString typeName() const
+ {
+ switch (type)
+ {
+ 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;
- /*!
- * \brief The minor version number.
- * This number is incremented for major features and bug fixes.
- */
+ //! The minor version number.
int minor;
- /*!
- * \brief The build number.
- * This number is automatically set by Buildbot it is set to the build number of the buildbot
- * build that this build came from.
- * 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.
- */
+ //! The hotfix number.
+ int hotfix;
+
+ //! The build number.
int build;
- /*!
- * \brief This build's channel.
- */
+ //! The build type.
+ Type type;
+
+ //! The build channel.
QString channel;
- /*!
- * \brief The build type.
- * This indicates the type of build that this is. For example, lin64 or custombuild.
- */
- QString buildType;
+ //! A short string identifying the platform that this version is for. For example, lin64 or win32.
+ QString platform;
};
diff --git a/changelog.yaml b/changelog.yaml
new file mode 100644
index 00000000..82dccd69
--- /dev/null
+++ b/changelog.yaml
@@ -0,0 +1,19 @@
+#
+# 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.
+0.1.1:
+ - Hotfix - Changed the issue tracker URL to [GitHub issues](https://github.com/MultiMC/MultiMC5/issues).
+
diff --git a/config.h.in b/config.h.in
index 8df1fc75..16e9f54e 100644
--- a/config.h.in
+++ b/config.h.in
@@ -1,13 +1,17 @@
#pragma once
-// Minor and major version, used to communicate changes to users.
+// Version information
#define VERSION_MAJOR @MultiMC_VERSION_MAJOR@
#define VERSION_MINOR @MultiMC_VERSION_MINOR@
-
-// Build number, channel, and type -- number and channel are used by the updater, type is purely visual
+#define VERSION_HOTFIX @MultiMC_VERSION_HOTFIX@
#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_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
#define CHANLIST_URL "@MultiMC_CHANLIST_URL@"
diff --git a/depends/javacheck/.gitignore b/depends/javacheck/.gitignore
new file mode 100644
index 00000000..cc1c52bf
--- /dev/null
+++ b/depends/javacheck/.gitignore
@@ -0,0 +1,6 @@
+.idea
+*.iml
+out
+.classpath
+.idea
+.project
diff --git a/depends/javacheck/CMakeLists.txt b/depends/javacheck/CMakeLists.txt
index e72c9552..10b9a716 100644
--- a/depends/javacheck/CMakeLists.txt
+++ b/depends/javacheck/CMakeLists.txt
@@ -5,10 +5,11 @@ find_package(Java 1.6 REQUIRED COMPONENTS Development)
include(UseJava)
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_TARGET_OUTPUT_DIR "${PROJECT_SOURCE_DIR}/../../resources")
set(SRC
JavaCheck.java
)
-add_jar(JavaCheck ${SRC}) \ No newline at end of file
+add_jar(JavaCheck ${SRC})
+
+INSTALL_JAR(JavaCheck "${BINARY_DEST_DIR}/jars")
diff --git a/depends/launcher/.gitignore b/depends/launcher/.gitignore
new file mode 100644
index 00000000..cc1c52bf
--- /dev/null
+++ b/depends/launcher/.gitignore
@@ -0,0 +1,6 @@
+.idea
+*.iml
+out
+.classpath
+.idea
+.project
diff --git a/depends/launcher/CMakeLists.txt b/depends/launcher/CMakeLists.txt
index e91d5bd6..6af5f738 100644
--- a/depends/launcher/CMakeLists.txt
+++ b/depends/launcher/CMakeLists.txt
@@ -3,19 +3,33 @@ project(launcher Java)
find_package(Java 1.6 REQUIRED COMPONENTS Development)
include(UseJava)
-set(CMAKE_JAVA_JAR_ENTRY_POINT MultiMCLauncher)
+set(CMAKE_JAVA_JAR_ENTRY_POINT org.multimc.EntryPoint)
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
- MultiMCLauncher.java
+ # OSX things
org/simplericity/macify/eawt/Application.java
org/simplericity/macify/eawt/ApplicationAdapter.java
org/simplericity/macify/eawt/ApplicationEvent.java
org/simplericity/macify/eawt/ApplicationListener.java
org/simplericity/macify/eawt/DefaultApplication.java
+
+ # legacy applet wrapper thing.
+ # The launcher has to be there for silly FML/Forge relauncher.
net/minecraft/Launcher.java
- MCFrame.java
+ org/multimc/legacy/LegacyLauncher.java
+ org/multimc/legacy/LegacyFrame.java
+
+ # onesix launcher
+ org/multimc/onesix/OneSixLauncher.java
+
+ # generic launcher
+ org/multimc/EntryPoint.java
+ org/multimc/Launcher.java
+ org/multimc/ParseException.java
+ org/multimc/Utils.java
+ org/multimc/IconLoader.java
)
+add_jar(NewLaunch ${SRC})
-add_jar(MultiMCLauncher ${SRC})
+INSTALL_JAR(NewLaunch "${BINARY_DEST_DIR}/jars")
diff --git a/depends/launcher/MultiMCLauncher.java b/depends/launcher/MultiMCLauncher.java
deleted file mode 100644
index 09a019ce..00000000
--- a/depends/launcher/MultiMCLauncher.java
+++ /dev/null
@@ -1,331 +0,0 @@
-//
-// Copyright 2012 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.
-//
-
-import java.applet.Applet;
-import java.awt.Dimension;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Modifier;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipFile;
-
-import javax.imageio.ImageIO;
-import java.awt.image.BufferedImage;
-import org.simplericity.macify.eawt.Application;
-import org.simplericity.macify.eawt.DefaultApplication;
-
-public class MultiMCLauncher
-{
- /**
- * @param args
- * The arguments you want to launch Minecraft with. New path,
- * Username, Session ID.
- */
- public static void main(String[] args)
- {
- if (args.length < 3)
- {
- System.out.println("Not enough arguments.");
- System.exit(-1);
- }
-
- // Set the OSX application icon first, if we are on OSX.
- Application application = new DefaultApplication();
- if(application.isMac())
- {
- try
- {
- BufferedImage image = ImageIO.read(new File("icon.png"));
- application.setApplicationIconImage(image);
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
- }
-
- String userName = args[0];
- String sessionId = args[1];
- String windowtitle = args[2];
- String windowParams = args[3];
- String lwjgl = args[4];
- String cwd = System.getProperty("user.dir");
-
- Dimension winSize = new Dimension(854, 480);
- boolean maximize = false;
- boolean compatMode = false;
-
-
- String[] dimStrings = windowParams.split("x");
-
- if (windowParams.equalsIgnoreCase("compatmode"))
- {
- compatMode = true;
- }
- else if (windowParams.equalsIgnoreCase("max"))
- {
- maximize = true;
- }
- else if (dimStrings.length == 2)
- {
- try
- {
- winSize = new Dimension(Integer.parseInt(dimStrings[0]),
- Integer.parseInt(dimStrings[1]));
- }
- catch (NumberFormatException e)
- {
- System.out.println("Invalid Window size argument, " +
- "using default.");
- }
- }
- else
- {
- System.out.println("Invalid Window size argument, " +
- "using default.");
- }
-
- try
- {
- File binDir = new File(cwd, "bin");
- File lwjglDir;
- if(lwjgl.equalsIgnoreCase("Mojang"))
- lwjglDir = binDir;
- else
- lwjglDir = new File(lwjgl);
-
- System.out.println("Loading jars...");
- String[] lwjglJars = new String[] {
- "lwjgl.jar", "lwjgl_util.jar", "jinput.jar"
- };
-
- URL[] urls = new URL[4];
- try
- {
- File f = new File(binDir, "minecraft.jar");
- urls[0] = f.toURI().toURL();
- System.out.println("Loading URL: " + urls[0].toString());
-
- for (int i = 1; i < urls.length; i++)
- {
- File jar = new File(lwjglDir, lwjglJars[i-1]);
- urls[i] = jar.toURI().toURL();
- System.out.println("Loading URL: " + urls[i].toString());
- }
- }
- catch (MalformedURLException e)
- {
- System.err.println("MalformedURLException, " + e.toString());
- System.exit(5);
- }
-
- System.out.println("Loading natives...");
- String nativesDir = new File(lwjglDir, "natives").toString();
-
- System.setProperty("org.lwjgl.librarypath", nativesDir);
- System.setProperty("net.java.games.input.librarypath", nativesDir);
-
- URLClassLoader cl =
- new URLClassLoader(urls, MultiMCLauncher.class.getClassLoader());
-
- // Get the Minecraft Class.
- Class<?> mc = null;
- try
- {
- mc = cl.loadClass("net.minecraft.client.Minecraft");
-
- Field f = getMCPathField(mc);
-
- if (f == null)
- {
- System.err.println("Could not find Minecraft path field. Launch failed.");
- System.exit(-1);
- }
-
- f.setAccessible(true);
- f.set(null, new File(cwd));
- // And set it.
- System.out.println("Fixed Minecraft Path: Field was " + f.toString());
- }
- catch (ClassNotFoundException e)
- {
- System.err.println("Can't find main class. Searching...");
-
- // Look for any class that looks like the main class.
- File mcJar = new File(new File(cwd, "bin"), "minecraft.jar");
- ZipFile zip = null;
- try
- {
- zip = new ZipFile(mcJar);
- } catch (ZipException e1)
- {
- e1.printStackTrace();
- System.err.println("Search failed.");
- System.exit(-1);
- } catch (IOException e1)
- {
- e1.printStackTrace();
- System.err.println("Search failed.");
- System.exit(-1);
- }
-
- Enumeration<? extends ZipEntry> entries = zip.entries();
- ArrayList<String> classes = new ArrayList<String>();
-
- while (entries.hasMoreElements())
- {
- ZipEntry entry = entries.nextElement();
- if (entry.getName().endsWith(".class"))
- {
- String entryName = entry.getName().substring(0, entry.getName().lastIndexOf('.'));
- entryName = entryName.replace('/', '.');
- System.out.println("Found class: " + entryName);
- classes.add(entryName);
- }
- }
-
- for (String clsName : classes)
- {
- try
- {
- Class<?> cls = cl.loadClass(clsName);
- if (!Runnable.class.isAssignableFrom(cls))
- {
- continue;
- }
- else
- {
- System.out.println("Found class implementing runnable: " +
- cls.getName());
- }
-
- if (getMCPathField(cls) == null)
- {
- continue;
- }
- else
- {
- System.out.println("Found class implementing runnable " +
- "with mcpath field: " + cls.getName());
- }
-
- mc = cls;
- break;
- }
- catch (ClassNotFoundException e1)
- {
- // Ignore
- continue;
- }
- }
-
- if (mc == null)
- {
- System.err.println("Failed to find Minecraft main class.");
- System.exit(-1);
- }
- else
- {
- System.out.println("Found main class: " + mc.getName());
- }
- }
-
- System.setProperty("minecraft.applet.TargetDirectory", cwd);
-
- String[] mcArgs = new String[2];
- mcArgs[0] = userName;
- mcArgs[1] = sessionId;
-
- if (compatMode)
- {
- System.out.println("Launching in compatibility mode...");
- mc.getMethod("main", String[].class).invoke(null, (Object) mcArgs);
- }
- else
- {
- System.out.println("Launching with applet wrapper...");
- try
- {
- Class<?> MCAppletClass = cl.loadClass(
- "net.minecraft.client.MinecraftApplet");
- Applet mcappl = (Applet) MCAppletClass.newInstance();
- MCFrame mcWindow = new MCFrame(windowtitle);
- mcWindow.start(mcappl, userName, sessionId, winSize, maximize);
- } catch (InstantiationException e)
- {
- System.out.println("Applet wrapper failed! Falling back " +
- "to compatibility mode.");
- mc.getMethod("main", String[].class).invoke(null, (Object) mcArgs);
- }
- }
- } catch (ClassNotFoundException e)
- {
- e.printStackTrace();
- System.exit(1);
- } catch (IllegalArgumentException e)
- {
- e.printStackTrace();
- System.exit(2);
- } catch (IllegalAccessException e)
- {
- e.printStackTrace();
- System.exit(2);
- } catch (InvocationTargetException e)
- {
- e.printStackTrace();
- System.exit(3);
- } catch (NoSuchMethodException e)
- {
- e.printStackTrace();
- System.exit(3);
- } catch (SecurityException e)
- {
- e.printStackTrace();
- System.exit(4);
- }
- }
-
- public static Field getMCPathField(Class<?> mc)
- {
- Field[] fields = mc.getDeclaredFields();
-
- for (int i = 0; i < fields.length; i++)
- {
- Field f = fields[i];
- if (f.getType() != File.class)
- {
- // Has to be File
- continue;
- }
- if (f.getModifiers() != (Modifier.PRIVATE + Modifier.STATIC))
- {
- // And Private Static.
- continue;
- }
- return f;
- }
- return null;
- }
-}
diff --git a/depends/launcher/net/minecraft/Launcher.java b/depends/launcher/net/minecraft/Launcher.java
index 8cef35ad..c9b137e1 100644
--- a/depends/launcher/net/minecraft/Launcher.java
+++ b/depends/launcher/net/minecraft/Launcher.java
@@ -1,18 +1,18 @@
-//
-// Copyright 2012 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.
-//
+/*
+ * Copyright 2012-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.
+ */
package net.minecraft;
@@ -38,7 +38,7 @@ public class Launcher extends Applet implements AppletStub
this.setLayout(new BorderLayout());
this.add(applet, "Center");
- this.wrappedApplet = applet;
+ this.wrappedApplet = applet;
this.documentBase = documentBase;
}
@@ -46,17 +46,17 @@ public class Launcher extends Applet implements AppletStub
{
params.put(name, value);
}
-
+
public void replace(Applet applet)
{
this.wrappedApplet = applet;
-
+
applet.setStub(this);
applet.setSize(getWidth(), getHeight());
-
+
this.setLayout(new BorderLayout());
this.add(applet, "Center");
-
+
applet.init();
active = true;
applet.start();
@@ -99,7 +99,7 @@ public class Launcher extends Applet implements AppletStub
{
wrappedApplet.resize(d);
}
-
+
@Override
public void init()
{
@@ -127,7 +127,7 @@ public class Launcher extends Applet implements AppletStub
{
wrappedApplet.destroy();
}
-
+
@Override
public URL getCodeBase() {
return wrappedApplet.getCodeBase();
diff --git a/depends/launcher/org/multimc/EntryPoint.java b/depends/launcher/org/multimc/EntryPoint.java
new file mode 100644
index 00000000..83f232f1
--- /dev/null
+++ b/depends/launcher/org/multimc/EntryPoint.java
@@ -0,0 +1,135 @@
+package org.multimc;/*
+ * Copyright 2012-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.
+ */
+
+import org.multimc.legacy.LegacyLauncher;
+import org.multimc.onesix.OneSixLauncher;
+import org.simplericity.macify.eawt.Application;
+import org.simplericity.macify.eawt.DefaultApplication;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
+
+public class EntryPoint
+{
+ private enum Action
+ {
+ Proceed,
+ Launch
+ }
+
+ public static void main(String[] args)
+ {
+ // Set the OSX application icon first, if we are on OSX.
+ Application application = new DefaultApplication();
+ if(application.isMac())
+ {
+ try
+ {
+ BufferedImage image = ImageIO.read(new File("icon.png"));
+ application.setApplicationIconImage(image);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ EntryPoint listener = new EntryPoint();
+ int retCode = listener.listen();
+ if (retCode != 0)
+ {
+ System.out.println("Exiting with " + retCode);
+ System.exit(retCode);
+ }
+ }
+
+ private Action parseLine(String inData) throws ParseException
+ {
+ String[] pair = inData.split(" ", 2);
+ if(pair.length != 2)
+ throw new ParseException();
+
+ String command = pair[0];
+ String param = pair[1];
+
+ if(command.equals("launch"))
+ {
+ if(param.equals("legacy"))
+ {
+ m_launcher = new LegacyLauncher();
+ Utils.log("Using legacy launcher.");
+ Utils.log();
+ return Action.Launch;
+ }
+ if(param.equals("onesix"))
+ {
+ m_launcher = new OneSixLauncher();
+ Utils.log("Using onesix launcher.");
+ Utils.log();
+ return Action.Launch;
+ }
+ else
+ throw new ParseException();
+ }
+
+ m_params.add(command, param);
+ //System.out.println(command + " : " + param);
+ return Action.Proceed;
+ }
+
+ public int listen()
+ {
+ BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));
+ boolean isListening = true;
+ // Main loop
+ while (isListening)
+ {
+ String inData="";
+ try
+ {
+ // Read from the pipe one line at a time
+ inData = buffer.readLine();
+ if (inData != null)
+ {
+ if(parseLine(inData) == Action.Launch)
+ {
+ isListening = false;
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ return 1;
+ }
+ catch (ParseException e)
+ {
+ e.printStackTrace();
+ return 1;
+ }
+ }
+ if(m_launcher != null)
+ {
+ return m_launcher.launch(m_params);
+ }
+ System.err.println("No valid launcher implementation specified.");
+ return 1;
+ }
+
+ private ParamBucket m_params = new ParamBucket();
+ private org.multimc.Launcher m_launcher;
+}
diff --git a/depends/launcher/org/multimc/IconLoader.java b/depends/launcher/org/multimc/IconLoader.java
new file mode 100644
index 00000000..f1638f3a
--- /dev/null
+++ b/depends/launcher/org/multimc/IconLoader.java
@@ -0,0 +1,132 @@
+package org.multimc;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/*****************************************************************************
+ * A convenience class for loading icons from images.
+ *
+ * Icons loaded from this class are formatted to fit within the required
+ * dimension (16x16, 32x32, or 128x128). If the source image is larger than the
+ * target dimension, it is shrunk down to the minimum size that will fit. If it
+ * is smaller, then it is only scaled up if the new scale can be a per-pixel
+ * linear scale (i.e., x2, x3, x4, etc). In both cases, the image's width/height
+ * ratio is kept the same as the source image.
+ *
+ * @author Chris Molini
+ *****************************************************************************/
+public class IconLoader
+{
+ /*************************************************************************
+ * Loads an icon in ByteBuffer form.
+ *
+ * @param filepath
+ * The location of the Image to use as an icon.
+ *
+ * @return An array of ByteBuffers containing the pixel data for the icon in
+ * various sizes (as recommended by the OS).
+ *************************************************************************/
+ public static ByteBuffer[] load(String filepath)
+ {
+ BufferedImage image;
+ try {
+ image = ImageIO.read ( new File( filepath ) );
+ } catch ( IOException e ) {
+ e.printStackTrace();
+ return new ByteBuffer[0];
+ }
+ ByteBuffer[] buffers;
+ buffers = new ByteBuffer[1];
+ buffers[0] = loadInstance(image, 128);
+ return buffers;
+ }
+
+ /*************************************************************************
+ * Copies the supplied image into a square icon at the indicated size.
+ *
+ * @param image
+ * The image to place onto the icon.
+ * @param dimension
+ * The desired size of the icon.
+ *
+ * @return A ByteBuffer of pixel data at the indicated size.
+ *************************************************************************/
+ private static ByteBuffer loadInstance(BufferedImage image, int dimension)
+ {
+ BufferedImage scaledIcon = new BufferedImage(dimension, dimension,
+ BufferedImage.TYPE_INT_ARGB_PRE);
+ Graphics2D g = scaledIcon.createGraphics();
+ double ratio = getIconRatio(image, scaledIcon);
+ double width = image.getWidth() * ratio;
+ double height = image.getHeight() * ratio;
+ g.drawImage(image, (int) ((scaledIcon.getWidth() - width) / 2),
+ (int) ((scaledIcon.getHeight() - height) / 2), (int) (width),
+ (int) (height), null);
+ g.dispose();
+
+ return convertToByteBuffer(scaledIcon);
+ }
+
+ /*************************************************************************
+ * Gets the width/height ratio of the icon. This is meant to simplify
+ * scaling the icon to a new dimension.
+ *
+ * @param src
+ * The base image that will be placed onto the icon.
+ * @param icon
+ * The icon that will have the image placed on it.
+ *
+ * @return The amount to scale the source image to fit it onto the icon
+ * appropriately.
+ *************************************************************************/
+ private static double getIconRatio(BufferedImage src, BufferedImage icon)
+ {
+ double ratio = 1;
+ if (src.getWidth() > icon.getWidth())
+ ratio = (double) (icon.getWidth()) / src.getWidth();
+ else
+ ratio = (int) (icon.getWidth() / src.getWidth());
+ if (src.getHeight() > icon.getHeight())
+ {
+ double r2 = (double) (icon.getHeight()) / src.getHeight();
+ if (r2 < ratio)
+ ratio = r2;
+ }
+ else
+ {
+ double r2 = (int) (icon.getHeight() / src.getHeight());
+ if (r2 < ratio)
+ ratio = r2;
+ }
+ return ratio;
+ }
+
+ /*************************************************************************
+ * Converts a BufferedImage into a ByteBuffer of pixel data.
+ *
+ * @param image
+ * The image to convert.
+ *
+ * @return A ByteBuffer that contains the pixel data of the supplied image.
+ *************************************************************************/
+ public static ByteBuffer convertToByteBuffer(BufferedImage image)
+ {
+ byte[] buffer = new byte[image.getWidth() * image.getHeight() * 4];
+ int counter = 0;
+ for (int i = 0; i < image.getHeight(); i++)
+ for (int j = 0; j < image.getWidth(); j++)
+ {
+ int colorSpace = image.getRGB(j, i);
+ buffer[counter + 0] = (byte) ((colorSpace << 8) >> 24);
+ buffer[counter + 1] = (byte) ((colorSpace << 16) >> 24);
+ buffer[counter + 2] = (byte) ((colorSpace << 24) >> 24);
+ buffer[counter + 3] = (byte) (colorSpace >> 24);
+ counter += 4;
+ }
+ return ByteBuffer.wrap(buffer);
+ }
+} \ No newline at end of file
diff --git a/depends/launcher/org/multimc/Launcher.java b/depends/launcher/org/multimc/Launcher.java
new file mode 100644
index 00000000..1aa2b21f
--- /dev/null
+++ b/depends/launcher/org/multimc/Launcher.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2012-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.
+ */
+
+package org.multimc;
+
+public interface Launcher
+{
+ abstract int launch(ParamBucket params);
+}
diff --git a/depends/launcher/org/multimc/NotFoundException.java b/depends/launcher/org/multimc/NotFoundException.java
new file mode 100644
index 00000000..fe154a2f
--- /dev/null
+++ b/depends/launcher/org/multimc/NotFoundException.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2012-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.
+ */
+
+package org.multimc;
+
+public class NotFoundException extends Exception
+{
+}
diff --git a/depends/launcher/org/multimc/ParamBucket.java b/depends/launcher/org/multimc/ParamBucket.java
new file mode 100644
index 00000000..2e197d9f
--- /dev/null
+++ b/depends/launcher/org/multimc/ParamBucket.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012-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.
+ */
+
+package org.multimc;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class ParamBucket
+{
+ public void add(String key, String value)
+ {
+ List<String> coll = null;
+ if(!m_params.containsKey(key))
+ {
+ coll = new ArrayList<String>();
+ m_params.put(key, coll);
+ }
+ else
+ {
+ coll = m_params.get(key);
+ }
+ coll.add(value);
+ }
+
+ public List<String> all(String key) throws NotFoundException
+ {
+ if(!m_params.containsKey(key))
+ throw new NotFoundException();
+ return m_params.get(key);
+ }
+
+ public List<String> allSafe(String key, List<String> def)
+ {
+ if(!m_params.containsKey(key) || m_params.get(key).size() < 1)
+ {
+ return def;
+ }
+ return m_params.get(key);
+ }
+
+ public List<String> allSafe(String key)
+ {
+ return allSafe(key, new ArrayList<String>());
+ }
+
+ public String first(String key) throws NotFoundException
+ {
+ List<String> list = all(key);
+ if(list.size() < 1)
+ {
+ throw new NotFoundException();
+ }
+ return list.get(0);
+ }
+
+ public String firstSafe(String key, String def)
+ {
+ if(!m_params.containsKey(key) || m_params.get(key).size() < 1)
+ {
+ return def;
+ }
+ return m_params.get(key).get(0);
+ }
+
+ public String firstSafe(String key)
+ {
+ return firstSafe(key, "");
+ }
+
+ private HashMap<String, List<String>> m_params = new HashMap<String, List<String>>();
+}
diff --git a/depends/launcher/org/multimc/ParseException.java b/depends/launcher/org/multimc/ParseException.java
new file mode 100644
index 00000000..d9e8e53e
--- /dev/null
+++ b/depends/launcher/org/multimc/ParseException.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2012-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.
+ */
+
+package org.multimc;
+
+public class ParseException extends java.lang.Exception
+{
+
+}
diff --git a/depends/launcher/org/multimc/Utils.java b/depends/launcher/org/multimc/Utils.java
new file mode 100644
index 00000000..df0ef861
--- /dev/null
+++ b/depends/launcher/org/multimc/Utils.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2012-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.
+ */
+
+package org.multimc;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+import java.util.List;
+
+public class Utils
+{
+ /**
+ * Combine two parts of a path.
+ * @param path1
+ * @param path2
+ * @return the paths, combined
+ */
+ public static String combine (String path1, String path2)
+ {
+ File file1 = new File(path1);
+ File file2 = new File(file1, path2);
+ return file2.getPath();
+ }
+
+ /**
+ * Join a list of strings into a string using a separator!
+ * @param strings the string list to join
+ * @param separator the glue
+ * @return the result.
+ */
+ public static String join (List<String> strings, String separator)
+ {
+ StringBuilder sb = new StringBuilder();
+ String sep = "";
+ for(String s: strings)
+ {
+ sb.append(sep).append(s);
+ sep = separator;
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Adds the specified library to the classpath
+ *
+ * @param s the path to add
+ * @throws Exception
+ */
+ public static void addToClassPath(String s) throws Exception
+ {
+ File f = new File(s);
+ URL u = f.toURI().toURL();
+ URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
+ Class urlClass = URLClassLoader.class;
+ Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});
+ method.setAccessible(true);
+ method.invoke(urlClassLoader, new Object[]{u});
+ }
+
+ /**
+ * Adds many libraries to the classpath
+ *
+ * @param jars the paths to add
+ */
+ public static boolean addToClassPath(List<String> jars)
+ {
+ boolean pure = true;
+ // initialize the class path
+ for (String jar : jars)
+ {
+ try
+ {
+ Utils.addToClassPath(jar);
+ } catch (Exception e)
+ {
+ System.err.println("Unable to load: " + jar);
+ e.printStackTrace(System.err);
+ pure = false;
+ }
+ }
+ return pure;
+ }
+
+ /**
+ * Adds the specified path to the java library path
+ *
+ * @param pathToAdd the path to add
+ * @throws Exception
+ */
+ @Deprecated public static void addLibraryPath(String pathToAdd) throws Exception
+ {
+ final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
+ usrPathsField.setAccessible(true);
+
+ //get array of paths
+ final String[] paths = (String[]) usrPathsField.get(null);
+
+ //check if the path to add is already present
+ for (String path : paths)
+ {
+ if (path.equals(pathToAdd))
+ {
+ return;
+ }
+ }
+
+ //add the new path
+ final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
+ newPaths[newPaths.length - 1] = pathToAdd;
+ usrPathsField.set(null, newPaths);
+ }
+
+ /**
+ * Finds a field that looks like a Minecraft base folder in a supplied class
+ *
+ * @param mc the class to scan
+ */
+ public static Field getMCPathField(Class<?> mc)
+ {
+ Field[] fields = mc.getDeclaredFields();
+
+ for (Field f : fields)
+ {
+ if (f.getType() != File.class)
+ {
+ // Has to be File
+ continue;
+ }
+ if (f.getModifiers() != (Modifier.PRIVATE + Modifier.STATIC))
+ {
+ // And Private Static.
+ continue;
+ }
+ return f;
+ }
+ return null;
+ }
+
+ /**
+ * Log to the MultiMC console
+ *
+ * @param message A String containing the message
+ * @param level A String containing the level name. See MinecraftProcess::getLevel()
+ */
+ public static void log(String message, String level)
+ {
+ // Kinda dirty
+ String tag = "!![" + level + "]!";
+ System.out.println(tag + message.replace("\n", "\n" + tag));
+ }
+
+ public static void log(String message)
+ {
+ log(message, "MultiMC");
+ }
+
+ public static void log()
+ {
+ System.out.println();
+ }
+}
diff --git a/depends/launcher/MCFrame.java b/depends/launcher/org/multimc/legacy/LegacyFrame.java
index ce4564c9..c3c0cafc 100644
--- a/depends/launcher/MCFrame.java
+++ b/depends/launcher/org/multimc/legacy/LegacyFrame.java
@@ -1,40 +1,39 @@
-//
-// Copyright 2012 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.
-//
+package org.multimc.legacy;/*
+ * Copyright 2012-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.
+ */
import net.minecraft.Launcher;
+
+import javax.imageio.ImageIO;
import java.applet.Applet;
-import java.awt.Dimension;
-import java.awt.Frame;
-import java.awt.Toolkit;
+import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
-import java.io.IOException;
-import java.io.File;
-import javax.imageio.ImageIO;
-import java.awt.image.BufferedImage;
-public class MCFrame extends Frame implements WindowListener
+public class LegacyFrame extends Frame implements WindowListener
{
private Launcher appletWrap = null;
- public MCFrame ( String title )
+ public LegacyFrame(String title)
{
super ( title );
- BufferedImage image = null;
+ BufferedImage image;
try {
image = ImageIO.read ( new File ( "icon.png" ) );
setIconImage ( image );
@@ -47,14 +46,14 @@ public class MCFrame extends Frame implements WindowListener
public void start ( Applet mcApplet, String user, String session, Dimension winSize, boolean maximize )
{
try {
- appletWrap = new Launcher ( mcApplet, new URL ( "http://www.minecraft.net/game" ) );
+ appletWrap = new Launcher( mcApplet, new URL ( "http://www.minecraft.net/game" ) );
} catch ( MalformedURLException ignored ) {}
-
appletWrap.setParameter ( "username", user );
appletWrap.setParameter ( "sessionid", session );
appletWrap.setParameter ( "stand-alone", "true" ); // Show the quit button.
- mcApplet.setStub ( appletWrap );
-
+ appletWrap.setParameter ( "demo", "false" );
+ appletWrap.setParameter("fullscreen", "false");
+ mcApplet.setStub(appletWrap);
this.add ( appletWrap );
appletWrap.setPreferredSize ( winSize );
this.pack();
@@ -63,7 +62,6 @@ public class MCFrame extends Frame implements WindowListener
if ( maximize ) {
this.setExtendedState ( MAXIMIZED_BOTH );
}
-
validate();
appletWrap.init();
appletWrap.start();
diff --git a/depends/launcher/org/multimc/legacy/LegacyLauncher.java b/depends/launcher/org/multimc/legacy/LegacyLauncher.java
new file mode 100644
index 00000000..1ca37c4a
--- /dev/null
+++ b/depends/launcher/org/multimc/legacy/LegacyLauncher.java
@@ -0,0 +1,178 @@
+package org.multimc.legacy;/*
+ * Copyright 2012-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.
+ */
+
+import org.multimc.Launcher;
+import org.multimc.NotFoundException;
+import org.multimc.ParamBucket;
+import org.multimc.Utils;
+
+import java.applet.Applet;
+import java.awt.*;
+import java.io.File;
+import java.lang.reflect.Field;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+public class LegacyLauncher implements Launcher
+{
+ @Override
+ public int launch(ParamBucket params)
+ {
+ String userName, sessionId, windowTitle, windowParams, lwjgl;
+ String mainClass = "net.minecraft.client.Minecraft";
+ try
+ {
+ userName = params.first("userName");
+ sessionId = params.first("sessionId");
+ windowTitle = params.first("windowTitle");
+ windowParams = params.first("windowParams");
+ lwjgl = params.first("lwjgl");
+ } catch (NotFoundException e)
+ {
+ System.err.println("Not enough arguments.");
+ return -1;
+ }
+
+ String cwd = System.getProperty("user.dir");
+ Dimension winSize = new Dimension(854, 480);
+ boolean maximize = false;
+
+ String[] dimStrings = windowParams.split("x");
+
+ if (windowParams.equalsIgnoreCase("max"))
+ {
+ maximize = true;
+ }
+ else if (dimStrings.length == 2)
+ {
+ try
+ {
+ winSize = new Dimension(Integer.parseInt(dimStrings[0]), Integer.parseInt(dimStrings[1]));
+ } catch (NumberFormatException ignored) {}
+ }
+
+ File binDir = new File(cwd, "bin");
+ File lwjglDir;
+ if (lwjgl.equalsIgnoreCase("Mojang"))
+ {
+ lwjglDir = binDir;
+ }
+ else
+ {
+ lwjglDir = new File(lwjgl);
+ }
+
+ URL[] classpath;
+ {
+ try
+ {
+ classpath = new URL[]
+ {
+ new File(binDir, "minecraft.jar").toURI().toURL(),
+ new File(lwjglDir, "lwjgl.jar").toURI().toURL(),
+ new File(lwjglDir, "lwjgl_util.jar").toURI().toURL(),
+ new File(lwjglDir, "jinput.jar").toURI().toURL(),
+ };
+ } catch (MalformedURLException e)
+ {
+ System.err.println("Class path entry is badly formed:");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+ }
+
+ String nativesDir = new File(lwjglDir, "natives").toString();
+
+ System.setProperty("org.lwjgl.librarypath", nativesDir);
+ System.setProperty("net.java.games.input.librarypath", nativesDir);
+
+ // print the pretty things
+ {
+ Utils.log("Main Class:");
+ Utils.log(" " + mainClass);
+ Utils.log();
+
+ Utils.log("Class Path:");
+ for (URL s : classpath)
+ {
+ Utils.log(" " + s);
+ }
+ Utils.log();
+
+ Utils.log("Native Path:");
+ Utils.log(" " + nativesDir);
+ Utils.log();
+ }
+
+ URLClassLoader cl = new URLClassLoader(classpath, LegacyLauncher.class.getClassLoader());
+
+ // Get the Minecraft Class and set the base folder
+ Class<?> mc;
+ try
+ {
+ mc = cl.loadClass(mainClass);
+
+ Field f = Utils.getMCPathField(mc);
+
+ if (f == null)
+ {
+ System.err.println("Could not find Minecraft path field. Launch failed.");
+ return -1;
+ }
+
+ f.setAccessible(true);
+ f.set(null, new File(cwd));
+ } catch (Exception e)
+ {
+ System.err.println("Could not set base folder. Failed to find/access Minecraft main class:");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+
+ System.setProperty("minecraft.applet.TargetDirectory", cwd);
+
+ String[] mcArgs = new String[2];
+ mcArgs[0] = userName;
+ mcArgs[1] = sessionId;
+
+ Utils.log("Launching with applet wrapper...");
+ try
+ {
+ Class<?> MCAppletClass = cl.loadClass("net.minecraft.client.MinecraftApplet");
+ Applet mcappl = (Applet) MCAppletClass.newInstance();
+ LegacyFrame mcWindow = new LegacyFrame(windowTitle);
+ mcWindow.start(mcappl, userName, sessionId, winSize, maximize);
+ } catch (Exception e)
+ {
+ Utils.log("Applet wrapper failed:", "Error");
+ e.printStackTrace(System.err);
+ Utils.log();
+ Utils.log("Falling back to compatibility mode.");
+ try
+ {
+ mc.getMethod("main", String[].class).invoke(null, (Object) mcArgs);
+ } catch (Exception e1)
+ {
+ Utils.log("Failed to invoke the Minecraft main class:", "Fatal");
+ e1.printStackTrace(System.err);
+ return -1;
+ }
+ }
+
+ return 0;
+ }
+}
diff --git a/depends/launcher/org/multimc/onesix/OneSixLauncher.java b/depends/launcher/org/multimc/onesix/OneSixLauncher.java
new file mode 100644
index 00000000..c1676c94
--- /dev/null
+++ b/depends/launcher/org/multimc/onesix/OneSixLauncher.java
@@ -0,0 +1,210 @@
+/* Copyright 2012-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.
+ */
+
+package org.multimc.onesix;
+
+import org.multimc.*;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+
+public class OneSixLauncher implements Launcher
+{
+ @Override
+ public int launch(ParamBucket params)
+ {
+ // get and process the launch script params
+ List<String> libraries;
+ List<String> mcparams;
+ List<String> mods;
+ String mainClass;
+ String natives;
+ final String windowTitle;
+ String windowParams;
+ try
+ {
+ libraries = params.all("cp");
+ mcparams = params.all("param");
+ mainClass = params.first("mainClass");
+ mods = params.allSafe("mods", new ArrayList<String>());
+ natives = params.first("natives");
+ windowTitle = params.first("windowTitle");
+ // windowParams = params.first("windowParams");
+ } catch (NotFoundException e)
+ {
+ System.err.println("Not enough arguments.");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+
+ List<String> allJars = new ArrayList<String>();
+ allJars.addAll(mods);
+ allJars.addAll(libraries);
+
+ if(!Utils.addToClassPath(allJars))
+ {
+ System.err.println("Halting launch due to previous errors.");
+ return -1;
+ }
+
+ String property = System.getProperty("os.arch");
+ List<String> allNativePaths = new ArrayList<String>();
+ boolean is_64 = property.equalsIgnoreCase("x86_64") || property.equalsIgnoreCase("amd64");
+ allNativePaths.add(natives);
+ allNativePaths.add(natives + "/" + (is_64 ? "64" : "32"));
+
+ // print the pretty things
+ {
+ Utils.log("Main Class:");
+ Utils.log(" " + mainClass);
+ Utils.log();
+
+ Utils.log("Native paths:");
+ for (String s : allNativePaths)
+ {
+ Utils.log(" " + s);
+ }
+ Utils.log();
+
+ Utils.log("Libraries:");
+ for (String s : libraries)
+ {
+ Utils.log(" " + s);
+ }
+ Utils.log();
+
+ if(mods.size() > 0)
+ {
+ Utils.log("Class Path Mods:");
+ for (String s : mods)
+ {
+ Utils.log(" " + s);
+ }
+ Utils.log();
+ }
+
+ Utils.log("Params:");
+ Utils.log(" " + mcparams.toString());
+ Utils.log();
+ }
+
+ final ClassLoader cl = ClassLoader.getSystemClassLoader();
+
+ // set up the natives path(s).
+ String libpath = Utils.join(allNativePaths, String.valueOf(File.pathSeparatorChar));
+ System.setProperty("java.library.path", libpath);
+ Field fieldSysPath;
+ try
+ {
+ fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
+ fieldSysPath.setAccessible( true );
+ fieldSysPath.set( null, null );
+ } catch (Exception e)
+ {
+ System.err.println("Failed to set the native library path:");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+
+ // Get the Minecraft Class.
+ Class<?> mc;
+ try
+ {
+ mc = cl.loadClass(mainClass);
+ } catch (ClassNotFoundException e)
+ {
+ System.err.println("Failed to find Minecraft main class:");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+
+ // get the main method.
+ Method meth;
+ try
+ {
+ meth = mc.getMethod("main", String[].class);
+ } catch (NoSuchMethodException e)
+ {
+ System.err.println("Failed to acquire the main method:");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+
+ // FIXME: works only on linux, we need a better solution
+/*
+ final java.nio.ByteBuffer[] icons = IconLoader.load("icon.png");
+ new Thread() {
+ public void run() {
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ try
+ {
+ Class<?> Display;
+ Method isCreated;
+ Method setTitle;
+ Method setIcon;
+
+ Display = cl.loadClass("org.lwjgl.opengl.Display");
+ isCreated = Display.getMethod("isCreated");
+ setTitle = Display.getMethod("setTitle", String.class);
+ setIcon = Display.getMethod("setIcon", java.nio.ByteBuffer[].class);
+
+ // set the window title? Maybe?
+ while(!(Boolean) isCreated.invoke(null))
+ {
+ try
+ {
+ Thread.sleep(150);
+ } catch (InterruptedException ignored) {}
+ }
+ // Give it a bit more time ;)
+ Thread.sleep(150);
+ // set the title
+ setTitle.invoke(null,windowTitle);
+ // only set icon when there's actually something to set...
+ if(icons.length > 0)
+ {
+ setIcon.invoke(null,(Object)icons);
+ }
+ }
+ catch (Exception e)
+ {
+ System.err.println("Couldn't set window icon or title.");
+ e.printStackTrace(System.err);
+ }
+ }
+ }
+ .start();
+*/
+ // start Minecraft
+ String[] paramsArray = mcparams.toArray(new String[mcparams.size()]); // init params accordingly
+ try
+ {
+ meth.invoke(null, (Object) paramsArray); // static method doesn't have an instance
+ } catch (Exception e)
+ {
+ System.err.println("Failed to start Minecraft:");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+ return 0;
+ }
+}
diff --git a/generated.qrc.in b/generated.qrc.in
deleted file mode 100644
index 82f4db99..00000000
--- a/generated.qrc.in
+++ /dev/null
@@ -1,6 +0,0 @@
-<RCC>
- <qresource prefix="/java">
- <file alias="launcher.jar">@MMC_BIN@/depends/launcher/MultiMCLauncher.jar</file>
- <file alias="checker.jar">@MMC_BIN@/depends/javacheck/JavaCheck.jar</file>
- </qresource>
-</RCC>
diff --git a/gui/ConsoleWindow.cpp b/gui/ConsoleWindow.cpp
index e640d261..dc36a8ff 100644
--- a/gui/ConsoleWindow.cpp
+++ b/gui/ConsoleWindow.cpp
@@ -19,12 +19,14 @@
#include <QScrollBar>
#include <QMessageBox>
+#include <QSystemTrayIcon>
#include <gui/Platform.h>
#include <gui/dialogs/CustomMessageBox.h>
#include <gui/dialogs/ProgressDialog.h>
#include "logic/net/PasteUpload.h"
+#include "logic/icons/IconList.h"
ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent)
: QMainWindow(parent), ui(new Ui::ConsoleWindow), proc(mcproc)
@@ -35,14 +37,28 @@ ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent)
SLOT(write(QString, MessageLevel::Enum)));
connect(mcproc, SIGNAL(ended(BaseInstance *, int, QProcess::ExitStatus)), this,
SLOT(onEnded(BaseInstance *, int, QProcess::ExitStatus)));
- connect(mcproc, SIGNAL(prelaunch_failed(BaseInstance*,int,QProcess::ExitStatus)), this,
+ connect(mcproc, SIGNAL(prelaunch_failed(BaseInstance *, int, QProcess::ExitStatus)), this,
SLOT(onEnded(BaseInstance *, int, QProcess::ExitStatus)));
- connect(mcproc, SIGNAL(launch_failed(BaseInstance*)), this,
- SLOT(onLaunchFailed(BaseInstance*)));
+ connect(mcproc, SIGNAL(launch_failed(BaseInstance *)), this,
+ SLOT(onLaunchFailed(BaseInstance *)));
- restoreState(QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowState").toByteArray()));
- restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowGeometry").toByteArray()));
+ restoreState(
+ QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowState").toByteArray()));
+ restoreGeometry(
+ QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowGeometry").toByteArray()));
+ QString iconKey = proc->instance()->iconKey();
+ QString name = proc->instance()->name();
+ auto icon = MMC->icons()->getIcon(iconKey);
+ setWindowIcon(icon);
+ m_trayIcon = new QSystemTrayIcon(icon, this);
+ QString consoleTitle = tr("Console window for ") + name;
+ m_trayIcon->setToolTip(consoleTitle);
+ setWindowTitle(consoleTitle);
+
+ connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
+ SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
+ m_trayIcon->show();
if (mcproc->instance()->settings().get("ShowConsole").toBool())
{
show();
@@ -55,13 +71,26 @@ ConsoleWindow::~ConsoleWindow()
delete ui;
}
+void ConsoleWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
+{
+ switch (reason)
+ {
+ case QSystemTrayIcon::Trigger:
+ {
+ toggleConsole();
+ }
+ default:
+ return;
+ }
+}
+
void ConsoleWindow::writeColor(QString text, const char *color)
{
// append a paragraph
QString newtext;
newtext += "<span style=\"";
{
- if(color)
+ if (color)
newtext += QString("color:") + color + ";";
newtext += "font-family: monospace;";
}
@@ -76,16 +105,17 @@ void ConsoleWindow::write(QString data, MessageLevel::Enum mode)
QScrollBar *bar = ui->text->verticalScrollBar();
int max_bar = bar->maximum();
int val_bar = bar->value();
- if(m_scroll_active)
+ if(isVisible())
{
- if(m_last_scroll_value > val_bar)
- m_scroll_active = false;
- }
- else
- {
- m_scroll_active = val_bar == max_bar;
+ if (m_scroll_active)
+ {
+ m_scroll_active = (max_bar - val_bar) <= 1;
+ }
+ else
+ {
+ m_scroll_active = val_bar == max_bar;
+ }
}
-
if (data.endsWith('\n'))
data = data.left(data.length() - 1);
QStringList paragraphs = data.split('\n');
@@ -110,15 +140,21 @@ void ConsoleWindow::write(QString data, MessageLevel::Enum mode)
else if (mode == MessageLevel::Debug)
while (iter.hasNext())
writeColor(iter.next(), "green");
+ else if (mode == MessageLevel::PrePost)
+ while (iter.hasNext())
+ writeColor(iter.next(), "grey");
// TODO: implement other MessageLevels
else
while (iter.hasNext())
writeColor(iter.next());
- if(m_scroll_active)
+ if(isVisible())
{
- bar->setValue(bar->maximum());
+ if (m_scroll_active)
+ {
+ bar->setValue(bar->maximum());
+ }
+ m_last_scroll_value = bar->value();
}
- m_last_scroll_value = bar->value();
}
void ConsoleWindow::clear()
@@ -133,23 +169,50 @@ void ConsoleWindow::on_closeButton_clicked()
void ConsoleWindow::setMayClose(bool mayclose)
{
+ if(mayclose)
+ ui->closeButton->setText(tr("Close"));
+ else
+ ui->closeButton->setText(tr("Hide"));
m_mayclose = mayclose;
- if (mayclose)
- ui->closeButton->setEnabled(true);
+}
+
+void ConsoleWindow::toggleConsole()
+{
+ QScrollBar *bar = ui->text->verticalScrollBar();
+ if (isVisible())
+ {
+ int max_bar = bar->maximum();
+ int val_bar = m_last_scroll_value = bar->value();
+ m_scroll_active = (max_bar - val_bar) <= 1;
+ hide();
+ }
else
- ui->closeButton->setEnabled(false);
+ {
+ show();
+ if (m_scroll_active)
+ {
+ bar->setValue(bar->maximum());
+ }
+ else
+ {
+ bar->setValue(m_last_scroll_value);
+ }
+ }
}
void ConsoleWindow::closeEvent(QCloseEvent *event)
{
if (!m_mayclose)
- event->ignore();
+ {
+ toggleConsole();
+ }
else
{
MMC->settings()->set("ConsoleWindowState", saveState().toBase64());
MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
emit isClosing();
+ m_trayIcon->hide();
QMainWindow::closeEvent(event);
}
}
@@ -170,19 +233,26 @@ void ConsoleWindow::on_btnKillMinecraft_clicked()
void ConsoleWindow::onEnded(BaseInstance *instance, int code, QProcess::ExitStatus status)
{
+ bool peacefulExit = code == 0 && status != QProcess::CrashExit;
ui->btnKillMinecraft->setEnabled(false);
setMayClose(true);
if (instance->settings().get("AutoCloseConsole").toBool())
{
- if (code == 0 && status != QProcess::CrashExit)
+ if (peacefulExit)
{
this->close();
return;
}
}
- if(!isVisible())
+ /*
+ if(!peacefulExit)
+ {
+ m_trayIcon->showMessage(tr("Oh no!"), tr("Minecraft crashed!"), QSystemTrayIcon::Critical);
+ }
+ */
+ if (!isVisible())
show();
}
@@ -192,7 +262,7 @@ void ConsoleWindow::onLaunchFailed(BaseInstance *instance)
setMayClose(true);
- if(!isVisible())
+ if (!isVisible())
show();
}
@@ -200,10 +270,11 @@ void ConsoleWindow::on_btnPaste_clicked()
{
auto text = ui->text->toPlainText();
ProgressDialog dialog(this);
- PasteUpload* paste=new PasteUpload(this, text);
+ PasteUpload *paste = new PasteUpload(this, text);
dialog.exec(paste);
- if(!paste->successful())
+ if (!paste->successful())
{
- CustomMessageBox::selectable(this, "Upload failed", paste->failReason(), QMessageBox::Critical)->exec();
+ CustomMessageBox::selectable(this, "Upload failed", paste->failReason(),
+ QMessageBox::Critical)->exec();
}
}
diff --git a/gui/ConsoleWindow.h b/gui/ConsoleWindow.h
index 731c616c..9291320e 100644
--- a/gui/ConsoleWindow.h
+++ b/gui/ConsoleWindow.h
@@ -16,6 +16,7 @@
#pragma once
#include <QMainWindow>
+#include <QSystemTrayIcon>
#include "logic/MinecraftProcess.h"
namespace Ui
@@ -77,7 +78,8 @@ slots:
// failures)
void on_btnPaste_clicked();
-
+ void iconActivated(QSystemTrayIcon::ActivationReason);
+ void toggleConsole();
protected:
void closeEvent(QCloseEvent *);
@@ -87,4 +89,6 @@ private:
bool m_mayclose = true;
int m_last_scroll_value = 0;
bool m_scroll_active = true;
+ QSystemTrayIcon *m_trayIcon = nullptr;
+ int m_saved_offset = 0;
};
diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp
index 968fecb7..d5cc1d44 100644
--- a/gui/MainWindow.cpp
+++ b/gui/MainWindow.cpp
@@ -77,6 +77,8 @@
#include "logic/news/NewsChecker.h"
+#include "logic/status/StatusChecker.h"
+
#include "logic/net/URLConstants.h"
#include "logic/BaseInstance.h"
@@ -99,7 +101,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
{
MultiMCPlatform::fixWM_CLASS(this);
ui->setupUi(this);
- setWindowTitle(QString("MultiMC %1").arg(MMC->version().toString()));
+
+ QString winTitle = QString("MultiMC 5 - Version %1").arg(MMC->version().toString());
+ if (!MMC->version().platform.isEmpty())
+ winTitle += " on " + MMC->version().platform;
+ setWindowTitle(winTitle);
// OSX magic.
// setUnifiedTitleAndToolBarOnMac(true);
@@ -195,7 +201,27 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
connect(MMC->instances().get(), SIGNAL(dataIsInvalid()), SLOT(selectionBad()));
m_statusLeft = new QLabel(tr("No instance selected"), this);
+ m_statusRight = new QLabel(tr("No status available"), this);
+ m_statusRefresh = new QToolButton(this);
+ m_statusRefresh->setToolButtonStyle(Qt::ToolButtonIconOnly);
+ m_statusRefresh->setIcon(
+ QPixmap(":/icons/toolbar/refresh").scaled(16, 16, Qt::KeepAspectRatio));
+
statusBar()->addPermanentWidget(m_statusLeft, 1);
+ statusBar()->addPermanentWidget(m_statusRight, 0);
+ statusBar()->addPermanentWidget(m_statusRefresh, 0);
+
+ // Start status checker
+ {
+ connect(MMC->statusChecker().get(), &StatusChecker::statusLoaded, this, &MainWindow::updateStatusUI);
+ connect(MMC->statusChecker().get(), &StatusChecker::statusLoadingFailed, this, &MainWindow::updateStatusFailedUI);
+
+ connect(m_statusRefresh, &QAbstractButton::clicked, this, &MainWindow::reloadStatus);
+ connect(&statusTimer, &QTimer::timeout, this, &MainWindow::reloadStatus);
+ statusTimer.setSingleShot(true);
+
+ reloadStatus();
+ }
// Add "manage accounts" button, right align
QWidget *spacer = new QWidget();
@@ -231,17 +257,20 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
connect(MMC->accounts().get(), &MojangAccountList::listChanged, [this]
{ repopulateAccountsMenu(); });
- std::shared_ptr<MojangAccountList> accounts = MMC->accounts();
+ // Show initial account
+ activeAccountChanged();
+
+ auto accounts = MMC->accounts();
// TODO: Nicer way to iterate?
for (int i = 0; i < accounts->count(); i++)
{
- MojangAccountPtr account = accounts->at(i);
+ auto account = accounts->at(i);
if (account != nullptr)
{
auto job = new NetJob("Startup player skins: " + account->username());
- for (AccountProfile profile : account->profiles())
+ for (auto profile : account->profiles())
{
auto meta = MMC->metacache()->resolveEntry("skins", profile.name + ".png");
auto action = CacheDownload::make(
@@ -289,24 +318,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
this, &MainWindow::notificationsChanged);
}
- const QString currentInstanceId = MMC->settings()->get("SelectedInstance").toString();
- if (!currentInstanceId.isNull())
- {
- const QModelIndex index = MMC->instances()->getInstanceIndexById(currentInstanceId);
- if (index.isValid())
- {
- const QModelIndex mappedIndex = proxymodel->mapFromSource(index);
- view->setCurrentIndex(mappedIndex);
- }
- else
- {
- view->setCurrentIndex(proxymodel->index(0, 0));
- }
- }
- else
- {
- view->setCurrentIndex(proxymodel->index(0, 0));
- }
+ setSelectedInstanceById(MMC->settings()->get("SelectedInstance").toString());
// removing this looks stupid
view->setFocus();
@@ -508,6 +520,63 @@ void MainWindow::updateNewsLabel()
}
}
+static QString convertStatus(const QString &status)
+{
+ if(status == "green") return "↑";
+ else if(status == "yellow") return "-";
+ else if(status == "red") return "↓";
+ else return "?";
+}
+
+void MainWindow::reloadStatus()
+{
+ MMC->statusChecker()->reloadStatus();
+ updateStatusUI();
+}
+
+static QString makeStatusString(const QMap<QString, QString> statuses)
+{
+ QString status = "";
+ status += "Web: " + convertStatus(statuses["minecraft.net"]);
+ status += " Account: " + convertStatus(statuses["account.mojang.com"]);
+ status += " Skins: " + convertStatus(statuses["skins.minecraft.net"]);
+ status += " Auth: " + convertStatus(statuses["authserver.mojang.com"]);
+ status += " Session: " + convertStatus(statuses["sessionserver.mojang.com"]);
+
+ return status;
+}
+
+void MainWindow::updateStatusUI()
+{
+ auto statusChecker = MMC->statusChecker();
+ auto statuses = statusChecker->getStatusEntries();
+
+ QString status = makeStatusString(statuses);
+ if(statusChecker->isLoadingStatus())
+ {
+ m_statusRefresh->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ m_statusRefresh->setText(tr("Loading..."));
+ }
+ else
+ {
+ m_statusRefresh->setToolButtonStyle(Qt::ToolButtonIconOnly);
+ m_statusRefresh->setText(tr(""));
+ }
+
+ m_statusRight->setText(status);
+
+ statusTimer.start(60 * 1000);
+}
+
+void MainWindow::updateStatusFailedUI()
+{
+ m_statusRight->setText(makeStatusString(QMap<QString, QString>()));
+ m_statusRefresh->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ m_statusRefresh->setText(tr("Failed."));
+
+ statusTimer.start(60 * 1000);
+}
+
void MainWindow::updateAvailable(QString repo, QString versionName, int versionId)
{
UpdateDialog dlg;
@@ -788,6 +857,20 @@ void MainWindow::updateInstanceToolIcon(QString new_icon)
ui->actionChangeInstIcon->setIcon(MMC->icons()->getIcon(m_currentInstIcon));
}
+void MainWindow::setSelectedInstanceById(const QString &id)
+{
+ QModelIndex selectionIndex = proxymodel->index(0, 0);
+ if (!id.isNull())
+ {
+ const QModelIndex index = MMC->instances()->getInstanceIndexById(id);
+ if (index.isValid())
+ {
+ selectionIndex = proxymodel->mapFromSource(index);
+ }
+ }
+ view->selectionModel()->setCurrentIndex(selectionIndex, QItemSelectionModel::ClearAndSelect);
+}
+
void MainWindow::on_actionChangeInstGroup_triggered()
{
if (!m_selectedInstance)
@@ -856,7 +939,7 @@ void MainWindow::on_actionManageAccounts_triggered()
void MainWindow::on_actionReportBug_triggered()
{
- openWebPage(QUrl("http://multimc.myjetbrains.com/youtrack/dashboard#newissue=yes"));
+ openWebPage(QUrl("https://github.com/MultiMC/MultiMC5/issues"));
}
void MainWindow::on_actionMoreNews_triggered()
@@ -1274,12 +1357,16 @@ void MainWindow::instanceChanged(const QModelIndex &current, const QModelIndex &
void MainWindow::selectionBad()
{
+ // start by reseting everything...
m_selectedInstance = nullptr;
statusBar()->clearMessage();
ui->instanceToolBar->setEnabled(false);
renameButton->setText(tr("Rename Instance"));
updateInstanceToolIcon("infinity");
+
+ // ...and then see if we can enable the previously selected instance
+ setSelectedInstanceById(MMC->settings()->get("SelectedInstance").toString());
}
void MainWindow::on_actionEditInstNotes_triggered()
diff --git a/gui/MainWindow.h b/gui/MainWindow.h
index af2f1dca..eb478776 100644
--- a/gui/MainWindow.h
+++ b/gui/MainWindow.h
@@ -17,6 +17,7 @@
#include <QMainWindow>
#include <QProcess>
+#include <QTimer>
#include "logic/lists/InstanceList.h"
#include "logic/BaseInstance.h"
@@ -168,6 +169,12 @@ slots:
void repopulateAccountsMenu();
void updateNewsLabel();
+
+ void updateStatusUI();
+
+ void updateStatusFailedUI();
+
+ void reloadStatus();
/*!
* Runs the DownloadUpdateTask and installs updates.
@@ -179,6 +186,8 @@ protected:
void setCatBackground(bool enabled);
void updateInstanceToolIcon(QString new_icon);
+ void setSelectedInstanceById(const QString &id);
+
private:
Ui::MainWindow *ui;
KCategoryDrawer *drawer;
@@ -196,8 +205,12 @@ private:
Task *m_versionLoadTask;
QLabel *m_statusLeft;
+ QLabel *m_statusRight;
+ QToolButton *m_statusRefresh;
QMenu *accountMenu;
QToolButton *accountMenuButton;
QAction *manageAccountsAction;
+
+ QTimer statusTimer;
};
diff --git a/gui/dialogs/AboutDialog.cpp b/gui/dialogs/AboutDialog.cpp
index 58d61dd0..35c85815 100644
--- a/gui/dialogs/AboutDialog.cpp
+++ b/gui/dialogs/AboutDialog.cpp
@@ -24,8 +24,25 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia
MultiMCPlatform::fixWM_CLASS(this);
ui->setupUi(this);
+ ui->urlLabel->setOpenExternalLinks(true);
+
ui->icon->setPixmap(QIcon(":/icons/multimc/scalable/apps/multimc.svg").pixmap(64));
- ui->title->setText("MultiMC " + MMC->version().toString());
+ ui->title->setText("MultiMC 5 " + MMC->version().toString());
+
+ ui->versionLabel->setText(tr("Version") +": " + MMC->version().toString());
+ ui->vtypeLabel->setText(tr("Version Type") +": " + MMC->version().typeName());
+ ui->platformLabel->setText(tr("Platform") +": " + MMC->version().platform);
+
+ if (MMC->version().build >= 0)
+ ui->buildNumLabel->setText(tr("Build Number") +": " + QString::number(MMC->version().build));
+ else
+ ui->buildNumLabel->setVisible(false);
+
+ if (!MMC->version().channel.isEmpty())
+ ui->channelLabel->setText(tr("Channel") +": " + MMC->version().channel);
+ else
+ ui->channelLabel->setVisible(false);
+
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
MMC->connect(ui->aboutQt, SIGNAL(clicked()), SLOT(aboutQt()));
diff --git a/gui/dialogs/AboutDialog.ui b/gui/dialogs/AboutDialog.ui
index df9b1a53..64a355d3 100644
--- a/gui/dialogs/AboutDialog.ui
+++ b/gui/dialogs/AboutDialog.ui
@@ -86,7 +86,7 @@
</font>
</property>
<property name="text">
- <string>MultiMC</string>
+ <string>MultiMC 5</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -103,8 +103,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>685</width>
- <height>304</height>
+ <width>689</width>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -112,6 +112,56 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
+ <widget class="QLabel" name="versionLabel">
+ <property name="text">
+ <string>Version:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="vtypeLabel">
+ <property name="text">
+ <string>Version Type:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="platformLabel">
+ <property name="text">
+ <string>Platform:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="buildNumLabel">
+ <property name="text">
+ <string>Build Number:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="channelLabel">
+ <property name="text">
+ <string>Channel:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QLabel" name="aboutLabel">
<property name="enabled">
<bool>true</bool>
@@ -158,6 +208,19 @@
</property>
</widget>
</item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="creditsPage">
@@ -165,8 +228,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>685</width>
- <height>304</height>
+ <width>689</width>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -182,19 +245,19 @@
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Andrew Okin &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:forkk@forkk.net&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;forkk@forkk.net&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Petr Mrázek &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:peterix@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;peterix@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Sky &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://www.twitter.com/drayshak&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@drayshak&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Andrew Okin &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:forkk@forkk.net&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;forkk@forkk.net&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Petr Mrázek &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:peterix@gmail.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;peterix@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Sky &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://www.twitter.com/drayshak&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@drayshak&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Ubuntu'; font-size:10pt; font-weight:600;&quot;&gt;With thanks to&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Orochimarufan &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:orochimarufan.x3@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;orochimarufan.x3@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;TakSuyu &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:taksuyu@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;taksuyu@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Kilobyte &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:stiepen22@gmx.de&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;stiepen22@gmx.de&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Jan (02JanDal) &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:02jandal@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;02jandal@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Robotbrain &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/skylordelros&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@skylordelros&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Rootbear75 &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/rootbear75&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@rootbear75&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt; (build server)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Orochimarufan &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:orochimarufan.x3@gmail.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;orochimarufan.x3@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;TakSuyu &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:taksuyu@gmail.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;taksuyu@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Kilobyte &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:stiepen22@gmx.de&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;stiepen22@gmx.de&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Jan (02JanDal) &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:02jandal@gmail.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;02jandal@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Robotbrain &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/skylordelros&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@skylordelros&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Rootbear75 &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/rootbear75&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@rootbear75&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt; (build server)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
@@ -218,8 +281,8 @@ p, li { white-space: pre-wrap; }
<rect>
<x>0</x>
<y>0</y>
- <width>684</width>
- <height>290</height>
+ <width>689</width>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -246,7 +309,7 @@ p, li { white-space: pre-wrap; }
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans Mono'; font-size:7.8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans Mono'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Copyright 2012-2014 MultiMC Contributors&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;);&lt;/span&gt;&lt;/p&gt;
@@ -367,7 +430,36 @@ p, li { white-space: pre-wrap; }
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; *&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * This file has been put into the public domain.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * You can do whatever you want with this file.&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; */&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; */&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;&quot;&gt;Java IconLoader class&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Copyright (c) 2011, Chris Molini&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;All rights reserved.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Redistribution and use in source and binary forms, with or without&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;modification, are permitted provided that the following conditions are met:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Redistributions of source code must retain the above copyright&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; notice, this list of conditions and the following disclaimer.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Redistributions in binary form must reproduce the above copyright&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; notice, this list of conditions and the following disclaimer in the&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; documentation and/or other materials provided with the distribution.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; names of its contributors may be used to endorse or promote products&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; derived from this software without specific prior written permission.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
@@ -378,8 +470,8 @@ p, li { white-space: pre-wrap; }
<rect>
<x>0</x>
<y>0</y>
- <width>684</width>
- <height>290</height>
+ <width>689</width>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -392,12 +484,12 @@ p, li { white-space: pre-wrap; }
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;Part of the reason for using the Apache license is we don't want people using the &amp;quot;MultiMC&amp;quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &amp;quot;MultiMC&amp;quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork &lt;/span&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:600;&quot;&gt;without&lt;/span&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt; implying that you have our blessing.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Part of the reason for using the Apache license is we don't want people using the &amp;quot;MultiMC&amp;quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &amp;quot;MultiMC&amp;quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork &lt;span style=&quot; font-weight:600;&quot;&gt;without&lt;/span&gt; implying that you have our blessing.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
diff --git a/gui/dialogs/InstanceSettings.ui b/gui/dialogs/InstanceSettings.ui
index 9260caea..9c7e1757 100644
--- a/gui/dialogs/InstanceSettings.ui
+++ b/gui/dialogs/InstanceSettings.ui
@@ -168,6 +168,12 @@
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="1">
<widget class="QSpinBox" name="maxMemSpinBox">
+ <property name="toolTip">
+ <string>The maximum amount of memory Minecraft is allowed to use.</string>
+ </property>
+ <property name="suffix">
+ <string> MB</string>
+ </property>
<property name="minimum">
<number>512</number>
</property>
@@ -198,6 +204,12 @@
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="minMemSpinBox">
+ <property name="toolTip">
+ <string>The amount of memory Minecraft is started with.</string>
+ </property>
+ <property name="suffix">
+ <string> MB</string>
+ </property>
<property name="minimum">
<number>256</number>
</property>
@@ -214,6 +226,12 @@
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="permGenSpinBox">
+ <property name="toolTip">
+ <string>The amount of memory available to store loaded Java classes.</string>
+ </property>
+ <property name="suffix">
+ <string> MB</string>
+ </property>
<property name="minimum">
<number>64</number>
</property>
diff --git a/gui/dialogs/ModEditDialogCommon.cpp b/gui/dialogs/ModEditDialogCommon.cpp
index 9a15d92d..eee42e5e 100644
--- a/gui/dialogs/ModEditDialogCommon.cpp
+++ b/gui/dialogs/ModEditDialogCommon.cpp
@@ -50,8 +50,8 @@ void showWebsiteForMod(QWidget *parentDlg, Mod &m)
else
{
CustomMessageBox::selectable(
- parentDlg, parentDlg->tr("How sad!"),
- parentDlg->tr("The mod author didn't provide a website link for this mod."),
+ parentDlg, QObject::tr("How sad!"),
+ QObject::tr("The mod author didn't provide a website link for this mod."),
QMessageBox::Warning);
}
}
diff --git a/gui/dialogs/SettingsDialog.cpp b/gui/dialogs/SettingsDialog.cpp
index 549b11b0..ef363f02 100644
--- a/gui/dialogs/SettingsDialog.cpp
+++ b/gui/dialogs/SettingsDialog.cpp
@@ -61,6 +61,7 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Se
{
MMC->updateChecker()->updateChanList();
}
+ connect(ui->proxyGroup, SIGNAL(buttonClicked(int)), SLOT(proxyChanged(int)));
}
SettingsDialog::~SettingsDialog()
@@ -83,6 +84,8 @@ void SettingsDialog::updateCheckboxStuff()
{
ui->windowWidthSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
ui->windowHeightSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
+ ui->proxyAddrBox->setEnabled(!ui->proxyNoneBtn->isChecked() && !ui->proxyDefaultBtn->isChecked());
+ ui->proxyAuthBox->setEnabled(!ui->proxyNoneBtn->isChecked() && !ui->proxyDefaultBtn->isChecked());
}
void SettingsDialog::on_ftbLauncherBrowseBtn_clicked()
@@ -202,6 +205,9 @@ void SettingsDialog::on_buttonBox_accepted()
{
applySettings(MMC->settings().get());
+ // Apply proxy settings
+ MMC->updateProxySettings();
+
MMC->settings()->set("SettingsGeometry", saveGeometry().toBase64());
}
@@ -210,6 +216,11 @@ 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
@@ -258,6 +269,10 @@ 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.
@@ -273,6 +288,9 @@ void SettingsDialog::refreshUpdateChannelDesc()
void SettingsDialog::applySettings(SettingsObject *s)
{
+ // Language
+ s->set("Language", ui->languageBox->itemData(ui->languageBox->currentIndex()).toLocale().bcp47Name());
+
// Updates
s->set("AutoUpdate", ui->autoUpdateCheckBox->isChecked());
s->set("UpdateChannel", m_currentUpdateChannel);
@@ -310,6 +328,19 @@ void SettingsDialog::applySettings(SettingsObject *s)
s->set("MinecraftWinWidth", ui->windowWidthSpinBox->value());
s->set("MinecraftWinHeight", ui->windowHeightSpinBox->value());
+ // Proxy
+ QString proxyType = "None";
+ if (ui->proxyDefaultBtn->isChecked()) proxyType = "Default";
+ else if (ui->proxyNoneBtn->isChecked()) proxyType = "None";
+ else if (ui->proxySOCKS5Btn->isChecked()) proxyType = "SOCKS5";
+ else if (ui->proxyHTTPBtn->isChecked()) proxyType = "HTTP";
+
+ s->set("ProxyType", proxyType);
+ s->set("ProxyAddr", ui->proxyAddrEdit->text());
+ s->set("ProxyPort", ui->proxyPortEdit->value());
+ s->set("ProxyUser", ui->proxyUserEdit->text());
+ s->set("ProxyPass", ui->proxyPassEdit->text());
+
// Memory
s->set("MinMemAlloc", ui->minMemSpinBox->value());
s->set("MaxMemAlloc", ui->maxMemSpinBox->value());
@@ -341,6 +372,19 @@ void SettingsDialog::applySettings(SettingsObject *s)
void SettingsDialog::loadSettings(SettingsObject *s)
{
+ // Language
+ ui->languageBox->clear();
+ ui->languageBox->addItem(tr("English"), QLocale(QLocale::English));
+ foreach(const QString & lang,
+ QDir(MMC->root() + "/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();
@@ -384,6 +428,18 @@ void SettingsDialog::loadSettings(SettingsObject *s)
ui->sortByNameBtn->setChecked(true);
}
+ // Proxy
+ QString proxyType = s->get("ProxyType").toString();
+ if (proxyType == "Default") ui->proxyDefaultBtn->setChecked(true);
+ else if (proxyType == "None") ui->proxyNoneBtn->setChecked(true);
+ else if (proxyType == "SOCKS5") ui->proxySOCKS5Btn->setChecked(true);
+ else if (proxyType == "HTTP") ui->proxyHTTPBtn->setChecked(true);
+
+ ui->proxyAddrEdit->setText(s->get("ProxyAddr").toString());
+ ui->proxyPortEdit->setValue(s->get("ProxyPort").value<qint16>());
+ ui->proxyUserEdit->setText(s->get("ProxyUser").toString());
+ ui->proxyPassEdit->setText(s->get("ProxyPass").toString());
+
// Java Settings
ui->javaPathTextBox->setText(s->get("JavaPath").toString());
ui->jvmArgsTextBox->setText(s->get("JvmArgs").toString());
@@ -447,4 +503,3 @@ void SettingsDialog::checkFinished(JavaCheckResult result)
"or set the path to the java executable."));
}
}
-
diff --git a/gui/dialogs/SettingsDialog.h b/gui/dialogs/SettingsDialog.h
index df67d492..d7bbbeb3 100644
--- a/gui/dialogs/SettingsDialog.h
+++ b/gui/dialogs/SettingsDialog.h
@@ -86,6 +86,7 @@ slots:
void refreshUpdateChannelDesc();
void updateChannelSelectionChanged(int index);
+ void proxyChanged(int);
private:
Ui::SettingsDialog *ui;
diff --git a/gui/dialogs/SettingsDialog.ui b/gui/dialogs/SettingsDialog.ui
index 7d2708cb..54e7db7a 100644
--- a/gui/dialogs/SettingsDialog.ui
+++ b/gui/dialogs/SettingsDialog.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>526</width>
- <height>639</height>
+ <width>545</width>
+ <height>609</height>
</rect>
</property>
<property name="sizePolicy">
@@ -35,80 +35,47 @@
<property name="currentIndex">
<number>0</number>
</property>
- <widget class="QWidget" name="generalTab">
+ <widget class="QWidget" name="featuresTab">
<attribute name="title">
- <string>General</string>
+ <string>Features</string>
</attribute>
- <layout class="QVBoxLayout" name="verticalLayout">
+ <layout class="QVBoxLayout" name="verticalLayout_9">
<item>
- <widget class="QGroupBox" name="sortingModeBox">
- <property name="enabled">
- <bool>true</bool>
- </property>
+ <widget class="QGroupBox" name="updateSettingsBox">
<property name="title">
- <string>Sorting Mode</string>
+ <string>Update Settings</string>
</property>
- <layout class="QHBoxLayout" name="sortingModeBoxLayout">
+ <layout class="QVBoxLayout" name="verticalLayout_7">
<item>
- <widget class="QRadioButton" name="sortLastLaunchedBtn">
+ <widget class="QCheckBox" name="autoUpdateCheckBox">
<property name="text">
- <string>By last launched</string>
+ <string>Check for updates when MultiMC starts?</string>
</property>
- <attribute name="buttonGroup">
- <string notr="true">sortingModeGroup</string>
- </attribute>
</widget>
</item>
<item>
- <widget class="QRadioButton" name="sortByNameBtn">
+ <widget class="QLabel" name="updateChannelLabel">
<property name="text">
- <string>By name</string>
+ <string>Update Channel:</string>
</property>
- <attribute name="buttonGroup">
- <string notr="true">sortingModeGroup</string>
- </attribute>
</widget>
</item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="updateSettingsBox">
- <property name="title">
- <string>Update Settings</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_7">
<item>
- <widget class="QCheckBox" name="autoUpdateCheckBox">
- <property name="text">
- <string>Check for updates when MultiMC starts?</string>
+ <widget class="QComboBox" name="updateChannelComboBox">
+ <property name="enabled">
+ <bool>false</bool>
</property>
</widget>
</item>
<item>
- <layout class="QVBoxLayout" name="channelVerticalLayout">
- <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>
- </widget>
- </item>
- </layout>
+ <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>
@@ -278,6 +245,78 @@
</widget>
</item>
<item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="generalTab">
+ <attribute name="title">
+ <string>User Interface</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QGridLayout" name="_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Language (needs restart):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="languageBox"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="sortingModeBox">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="title">
+ <string>Sorting Mode</string>
+ </property>
+ <layout class="QHBoxLayout" name="sortingModeBoxLayout">
+ <item>
+ <widget class="QRadioButton" name="sortLastLaunchedBtn">
+ <property name="text">
+ <string>By last launched</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">sortingModeGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="sortByNameBtn">
+ <property name="text">
+ <string>By name</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">sortingModeGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<widget class="QGroupBox" name="editorsBox">
<property name="title">
<string>External Editors (leave empty for system default)</string>
@@ -437,6 +476,12 @@
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="1">
<widget class="QSpinBox" name="maxMemSpinBox">
+ <property name="toolTip">
+ <string>The maximum amount of memory Minecraft is allowed to use.</string>
+ </property>
+ <property name="suffix">
+ <string> MB</string>
+ </property>
<property name="minimum">
<number>512</number>
</property>
@@ -467,6 +512,12 @@
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="minMemSpinBox">
+ <property name="toolTip">
+ <string>The amount of memory Minecraft is started with.</string>
+ </property>
+ <property name="suffix">
+ <string> MB</string>
+ </property>
<property name="minimum">
<number>256</number>
</property>
@@ -490,6 +541,12 @@
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="permGenSpinBox">
+ <property name="toolTip">
+ <string>The amount of memory available to store loaded Java classes.</string>
+ </property>
+ <property name="suffix">
+ <string> MB</string>
+ </property>
<property name="minimum">
<number>64</number>
</property>
@@ -647,6 +704,165 @@
</item>
</layout>
</widget>
+ <widget class="QWidget" name="networkTab">
+ <property name="toolTip">
+ <string>Network settings.</string>
+ </property>
+ <attribute name="title">
+ <string>Network</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <widget class="QGroupBox" name="proxySettingsBox">
+ <property name="title">
+ <string>Proxy</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_8">
+ <item>
+ <widget class="QGroupBox" name="proxyTypeBox">
+ <property name="title">
+ <string>Type</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QRadioButton" name="proxyDefaultBtn">
+ <property name="toolTip">
+ <string>Uses your system's default proxy settings.</string>
+ </property>
+ <property name="text">
+ <string>Default</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">proxyGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="proxyNoneBtn">
+ <property name="text">
+ <string>None</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">proxyGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="proxySOCKS5Btn">
+ <property name="text">
+ <string>SOCKS5</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">proxyGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="proxyHTTPBtn">
+ <property name="text">
+ <string>HTTP</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">proxyGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="proxyAddrBox">
+ <property name="title">
+ <string>Address and Port</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="proxyAddrEdit">
+ <property name="placeholderText">
+ <string>127.0.0.1</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="proxyPortEdit">
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::PlusMinus</enum>
+ </property>
+ <property name="maximum">
+ <number>65535</number>
+ </property>
+ <property name="value">
+ <number>8080</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="proxyAuthBox">
+ <property name="title">
+ <string>Authentication</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_5">
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="proxyUserEdit"/>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="proxyUsernameLabel">
+ <property name="text">
+ <string>Username:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="proxyPasswordLabel">
+ <property name="text">
+ <string>Password:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="proxyPassEdit">
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QLabel" name="proxyPlainTextWarningLabel">
+ <property name="text">
+ <string>Note: Proxy username and password are stored in plain text inside MultiMC's configuration file!</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
<item>
@@ -665,20 +881,6 @@
<tabstop>buttonBox</tabstop>
<tabstop>sortLastLaunchedBtn</tabstop>
<tabstop>sortByNameBtn</tabstop>
- <tabstop>autoUpdateCheckBox</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>jsonEditorTextBox</tabstop>
<tabstop>jsonEditorBrowseBtn</tabstop>
<tabstop>maximizedCheckBox</tabstop>
@@ -736,6 +938,7 @@
</connection>
</connections>
<buttongroups>
+ <buttongroup name="proxyGroup"/>
<buttongroup name="sortingModeGroup"/>
</buttongroups>
</ui>
diff --git a/install_prereqs.cmake.in b/install_prereqs.cmake.in
index 40fda8b2..3ae8302d 100644
--- a/install_prereqs.cmake.in
+++ b/install_prereqs.cmake.in
@@ -3,7 +3,7 @@ function(gp_resolved_file_type_override resolved_file type_var)
if(resolved_file MATCHES "^/usr/lib/libQt")
message("resolving ${resolved_file} as other")
set(${type_var} other PARENT_SCOPE)
- elseif(resolved_file MATCHES "^/usr/lib/libxcb")
+ elseif(resolved_file MATCHES "^/usr/lib(.+)?/libxcb")
message("resolving ${resolved_file} as other")
set(${type_var} other PARENT_SCOPE)
endif()
diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp
index ac66a8d5..222004a3 100644
--- a/logic/BaseInstance.cpp
+++ b/logic/BaseInstance.cpp
@@ -26,6 +26,7 @@
#include "overridesetting.h"
#include "pathutils.h"
+#include <cmdutils.h>
#include "lists/MinecraftVersionList.h"
#include "logic/icons/IconList.h"
@@ -81,6 +82,7 @@ BaseInstance::BaseInstance(BaseInstancePrivate *d_in, const QString &rootDir,
settings().registerSetting("OverrideConsole", false);
settings().registerOverride(globalSettings->getSetting("ShowConsole"));
settings().registerOverride(globalSettings->getSetting("AutoCloseConsole"));
+ settings().registerOverride(globalSettings->getSetting("LogPrePostOutput"));
}
void BaseInstance::iconUpdated(QString key)
@@ -248,8 +250,19 @@ void BaseInstance::setName(QString val)
d->m_settings->set("name", val);
emit propertiesChanged(this);
}
+
QString BaseInstance::name() const
{
I_D(BaseInstance);
return d->m_settings->get("name").toString();
}
+
+QString BaseInstance::windowTitle() const
+{
+ return "MultiMC: " + name();
+}
+
+QStringList BaseInstance::extraArguments() const
+{
+ return Util::Commandline::splitArgs(settings().get("JvmArgs").toString());
+}
diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h
index 01d6dc7d..a861e9b2 100644
--- a/logic/BaseInstance.h
+++ b/logic/BaseInstance.h
@@ -57,7 +57,7 @@ public:
/// The instance's ID. The ID SHALL be determined by MMC internally. The ID IS guaranteed to
/// be unique.
- QString id() const;
+ virtual QString id() const;
/// get the type of this instance
QString instanceType() const;
@@ -71,6 +71,9 @@ public:
QString name() const;
void setName(QString val);
+ /// Value used for instance window titles
+ QString windowTitle() const;
+
QString iconKey() const;
void setIconKey(QString val);
@@ -81,6 +84,8 @@ public:
void setGroupInitial(QString val);
void setGroupPost(QString val);
+ QStringList extraArguments() const;
+
virtual QString intendedVersionId() const = 0;
virtual bool setIntendedVersionId(QString version) = 0;
diff --git a/logic/BaseVersion.h b/logic/BaseVersion.h
index 1864c94c..43f5942a 100644
--- a/logic/BaseVersion.h
+++ b/logic/BaseVersion.h
@@ -39,6 +39,15 @@ struct BaseVersion
* the kind of version this is (Stable, Beta, Snapshot, whatever)
*/
virtual QString typeString() const = 0;
+
+ virtual bool operator<(BaseVersion &a)
+ {
+ return name() < a.name();
+ };
+ virtual bool operator>(BaseVersion &a)
+ {
+ return name() > a.name();
+ };
};
typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
diff --git a/logic/JavaChecker.cpp b/logic/JavaChecker.cpp
index 113974ff..b87ee3d5 100644
--- a/logic/JavaChecker.cpp
+++ b/logic/JavaChecker.cpp
@@ -1,31 +1,28 @@
#include "JavaChecker.h"
+#include "MultiMC.h"
+#include <pathutils.h>
#include <QFile>
#include <QProcess>
#include <QMap>
#include <QTemporaryFile>
-#define CHECKER_FILE "JavaChecker.jar"
-
JavaChecker::JavaChecker(QObject *parent) : QObject(parent)
{
}
void JavaChecker::performCheck()
{
- checkerJar.setFileTemplate("checker_XXXXXX.jar");
- checkerJar.open();
- QFile inner(":/java/checker.jar");
- inner.open(QIODevice::ReadOnly);
- checkerJar.write(inner.readAll());
- inner.close();
- checkerJar.close();
+ QString checkerJar = PathCombine(MMC->bin(), "jars", "JavaCheck.jar");
- QStringList args = {"-jar", checkerJar.fileName()};
+ QStringList args = {"-jar", checkerJar};
process.reset(new QProcess());
process->setArguments(args);
process->setProgram(path);
process->setProcessChannelMode(QProcess::SeparateChannels);
+ QLOG_DEBUG() << "Running java checker!";
+ QLOG_DEBUG() << "Java: " + path;
+ QLOG_DEBUG() << "Args: {" + args.join("|") + "}";
connect(process.get(), SIGNAL(finished(int, QProcess::ExitStatus)), this,
SLOT(finished(int, QProcess::ExitStatus)));
@@ -42,21 +39,25 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
killTimer.stop();
QProcessPtr _process;
_process.swap(process);
- checkerJar.remove();
JavaCheckResult result;
{
result.path = path;
+ result.id = id;
}
+ QLOG_DEBUG() << "Java checker finished with status " << status << " exit code " << exitcode;
if (status == QProcess::CrashExit || exitcode == 1)
{
+ QLOG_DEBUG() << "Java checker failed!";
emit checkFinished(result);
return;
}
bool success = true;
QString p_stdout = _process->readAllStandardOutput();
+ QLOG_DEBUG() << p_stdout;
+
QMap<QString, QString> results;
QStringList lines = p_stdout.split("\n", QString::SkipEmptyParts);
for(QString line : lines)
@@ -76,6 +77,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
if(!results.contains("os.arch") || !results.contains("java.version") || !success)
{
+ QLOG_DEBUG() << "Java checker failed - couldn't extract required information.";
emit checkFinished(result);
return;
}
@@ -90,7 +92,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
result.mojangPlatform = is_64 ? "64" : "32";
result.realPlatform = os_arch;
result.javaVersion = java_version;
-
+ QLOG_DEBUG() << "Java checker succeeded.";
emit checkFinished(result);
}
@@ -99,11 +101,11 @@ void JavaChecker::error(QProcess::ProcessError err)
if(err == QProcess::FailedToStart)
{
killTimer.stop();
- checkerJar.remove();
-
+ QLOG_DEBUG() << "Java checker has failed to start.";
JavaCheckResult result;
{
result.path = path;
+ result.id = id;
}
emit checkFinished(result);
@@ -116,6 +118,7 @@ void JavaChecker::timeout()
// NO MERCY. NO ABUSE.
if(process)
{
+ QLOG_DEBUG() << "Java checker has been killed by timeout.";
process->kill();
}
}
diff --git a/logic/JavaChecker.h b/logic/JavaChecker.h
index 291bf46c..e19895f7 100644
--- a/logic/JavaChecker.h
+++ b/logic/JavaChecker.h
@@ -1,7 +1,6 @@
#pragma once
#include <QProcess>
#include <QTimer>
-#include <QTemporaryFile>
#include <memory>
class JavaChecker;
@@ -15,6 +14,7 @@ struct JavaCheckResult
QString javaVersion;
bool valid = false;
bool is_64bit = false;
+ int id;
};
typedef std::shared_ptr<QProcess> QProcessPtr;
@@ -27,13 +27,13 @@ public:
void performCheck();
QString path;
+ int id;
signals:
void checkFinished(JavaCheckResult result);
private:
QProcessPtr process;
QTimer killTimer;
- QTemporaryFile checkerJar;
public
slots:
void timeout();
diff --git a/logic/JavaCheckerJob.cpp b/logic/JavaCheckerJob.cpp
index 36a8a050..b0aea758 100644
--- a/logic/JavaCheckerJob.cpp
+++ b/logic/JavaCheckerJob.cpp
@@ -26,10 +26,7 @@ void JavaCheckerJob::partFinished(JavaCheckResult result)
<< javacheckers.size();
emit progress(num_finished, javacheckers.size());
- javaresults.append(result);
- int result_size = javacheckers.size();
-
- emit progress(num_finished, result_size);
+ javaresults.replace(result.id, result);
if (num_finished == javacheckers.size())
{
@@ -43,6 +40,7 @@ void JavaCheckerJob::start()
m_running = true;
for (auto iter : javacheckers)
{
+ javaresults.append(JavaCheckResult());
connect(iter.get(), SIGNAL(checkFinished(JavaCheckResult)), SLOT(partFinished(JavaCheckResult)));
iter->performCheck();
}
diff --git a/logic/LegacyFTBInstance.cpp b/logic/LegacyFTBInstance.cpp
index 84d5a900..6c6bd10b 100644
--- a/logic/LegacyFTBInstance.cpp
+++ b/logic/LegacyFTBInstance.cpp
@@ -14,3 +14,8 @@ bool LegacyFTBInstance::menuActionEnabled(QString action_name) const
{
return false;
}
+
+QString LegacyFTBInstance::id() const
+{
+ return "FTB/" + BaseInstance::id();
+}
diff --git a/logic/LegacyFTBInstance.h b/logic/LegacyFTBInstance.h
index 2ae72797..70f60535 100644
--- a/logic/LegacyFTBInstance.h
+++ b/logic/LegacyFTBInstance.h
@@ -10,4 +10,5 @@ public:
QObject *parent = 0);
virtual QString getStatusbarDescription();
virtual bool menuActionEnabled(QString action_name) const;
+ virtual QString id() const;
};
diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp
index 0bc0961e..2828bcbf 100644
--- a/logic/LegacyInstance.cpp
+++ b/logic/LegacyInstance.cpp
@@ -31,8 +31,6 @@
#include "gui/dialogs/LegacyModEditDialog.h"
-#define LAUNCHER_FILE "MultiMCLauncher.jar"
-
LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings,
QObject *parent)
: BaseInstance(new LegacyInstancePrivate(), rootDir, settings, parent)
@@ -49,7 +47,7 @@ std::shared_ptr<Task> LegacyInstance::doUpdate(bool only_prepare)
// make sure the jar mods list is initialized by asking for it.
auto list = jarModList();
// create an update task
- return std::shared_ptr<Task> (new LegacyUpdate(this, only_prepare , this));
+ return std::shared_ptr<Task>(new LegacyUpdate(this, only_prepare, this));
}
MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account)
@@ -60,58 +58,27 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account)
auto pixmap = icon.pixmap(128, 128);
pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG");
- // extract the legacy launcher
- QFile(":/java/launcher.jar").copy(PathCombine(minecraftRoot(), LAUNCHER_FILE));
-
- // set the process arguments
+ // create the launch script
+ QString launchScript;
{
- QStringList args;
-
// window size
- QString windowSize;
+ QString windowParams;
if (settings().get("LaunchMaximized").toBool())
- windowSize = "max";
+ windowParams = "max";
else
- windowSize = QString("%1x%2").arg(settings().get("MinecraftWinWidth").toInt()).arg(
+ windowParams = QString("%1x%2").arg(settings().get("MinecraftWinWidth").toInt()).arg(
settings().get("MinecraftWinHeight").toInt());
- // window title
- QString windowTitle;
- windowTitle.append("MultiMC: ").append(name());
-
- // Java arguments
- args.append(Util::Commandline::splitArgs(settings().get("JvmArgs").toString()));
-
-#ifdef OSX
- // OSX dock icon and name
- args << "-Xdock:icon=icon.png";
- args << QString("-Xdock:name=\"%1\"").arg(windowTitle);
-#endif
-
QString lwjgl = QDir(MMC->settings()->get("LWJGLDir").toString() + "/" + lwjglVersion())
.absolutePath();
-
- // launcher arguments
- args << QString("-Xms%1m").arg(settings().get("MinMemAlloc").toInt());
- args << QString("-Xmx%1m").arg(settings().get("MaxMemAlloc").toInt());
- args << QString("-XX:PermSize=%1m").arg(settings().get("PermGen").toInt());
-/**
-* HACK: Stupid hack for Intel drivers.
-* See: https://mojang.atlassian.net/browse/MCL-767
-*/
-#ifdef Q_OS_WIN32
- args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_"
- "minecraft.exe.heapdump");
-#endif
-
- args << "-jar" << LAUNCHER_FILE;
- args << account->currentProfile()->name;
- args << account->sessionId();
- args << windowTitle;
- args << windowSize;
- args << lwjgl;
- proc->setArguments(args);
+ launchScript += "userName " + account->currentProfile()->name + "\n";
+ launchScript += "sessionId " + account->sessionId() + "\n";
+ launchScript += "windowTitle " + windowTitle() + "\n";
+ launchScript += "windowParams " + windowParams + "\n";
+ launchScript += "lwjgl " + lwjgl + "\n";
+ launchScript += "launch legacy\n";
}
+ proc->setLaunchScript(launchScript);
// set the process work path
proc->setWorkdir(minecraftRoot());
diff --git a/logic/MinecraftProcess.cpp b/logic/MinecraftProcess.cpp
index 209929b7..84610021 100644
--- a/logic/MinecraftProcess.cpp
+++ b/logic/MinecraftProcess.cpp
@@ -14,14 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include "MultiMC.h"
#include "MinecraftProcess.h"
#include <QDataStream>
#include <QFile>
#include <QDir>
-//#include <QImage>
#include <QProcessEnvironment>
+#include <QRegularExpression>
#include "BaseInstance.h"
@@ -42,6 +43,7 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst)
#ifdef LINUX
// Strip IBus
+ // IBus is a Linux IME framework. For some reason, it breaks MC?
if (env.value("XMODIFIERS").contains(IBUS))
env.insert("XMODIFIERS", env.value("XMODIFIERS").replace(IBUS, ""));
#endif
@@ -57,11 +59,15 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst)
// std channels
connect(this, SIGNAL(readyReadStandardError()), SLOT(on_stdErr()));
connect(this, SIGNAL(readyReadStandardOutput()), SLOT(on_stdOut()));
-}
-void MinecraftProcess::setArguments(QStringList args)
-{
- m_args = args;
+ // Log prepost launch command output (can be disabled.)
+ if (m_instance->settings().get("LogPrePostOutput").toBool())
+ {
+ connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardError,
+ this, &MinecraftProcess::on_prepost_stdErr);
+ connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardOutput,
+ this, &MinecraftProcess::on_prepost_stdOut);
+ }
}
void MinecraftProcess::setWorkdir(QString path)
@@ -90,47 +96,145 @@ QString MinecraftProcess::censorPrivateInfo(QString in)
in.replace(profileId, "<PROFILE ID>");
in.replace(profileName, "<PROFILE NAME>");
}
+
+ auto i = m_account->user().properties.begin();
+ while (i != m_account->user().properties.end())
+ {
+ in.replace(i.value(), "<" + i.key().toUpper() + ">");
+ ++i;
+ }
+
return in;
}
// console window
+MessageLevel::Enum MinecraftProcess::guessLevel(const QString &line, MessageLevel::Enum level)
+{
+ if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") ||
+ line.contains("[FINER]") || line.contains("[FINEST]"))
+ level = MessageLevel::Message;
+ if (line.contains("[SEVERE]") || line.contains("[STDERR]"))
+ level = MessageLevel::Error;
+ if (line.contains("[WARNING]"))
+ level = MessageLevel::Warning;
+ if (line.contains("Exception in thread") || line.contains(" at "))
+ level = MessageLevel::Fatal;
+ if (line.contains("[DEBUG]"))
+ level = MessageLevel::Debug;
+ return level;
+}
+
+MessageLevel::Enum MinecraftProcess::getLevel(const QString &levelName)
+{
+ if (levelName == "MultiMC")
+ return MessageLevel::MultiMC;
+ else if (levelName == "Debug")
+ return MessageLevel::Debug;
+ else if (levelName == "Info")
+ return MessageLevel::Info;
+ else if (levelName == "Message")
+ return MessageLevel::Message;
+ else if (levelName == "Warning")
+ return MessageLevel::Warning;
+ else if (levelName == "Error")
+ return MessageLevel::Error;
+ else if (levelName == "Fatal")
+ return MessageLevel::Fatal;
+ // Skip PrePost, it's not exposed to !![]!
+ else
+ return MessageLevel::Message;
+}
+
+void MinecraftProcess::logOutput(const QStringList &lines,
+ MessageLevel::Enum defaultLevel,
+ bool guessLevel, bool censor)
+{
+ for (int i = 0; i < lines.size(); ++i)
+ logOutput(lines[i], defaultLevel, guessLevel, censor);
+}
+
+void MinecraftProcess::logOutput(QString line,
+ MessageLevel::Enum defaultLevel,
+ bool guessLevel, bool censor)
+{
+ MessageLevel::Enum level = defaultLevel;
+
+ // Level prefix
+ int endmark = line.indexOf("]!");
+ if (line.startsWith("!![") && endmark != -1)
+ {
+ level = getLevel(line.left(endmark).mid(3));
+ line = line.mid(endmark + 2);
+ }
+ // Guess level
+ else if (guessLevel)
+ level = this->guessLevel(line, defaultLevel);
+
+ if (censor)
+ line = censorPrivateInfo(line);
+
+ emit log(line, level);
+}
+
void MinecraftProcess::on_stdErr()
{
QByteArray data = readAllStandardError();
QString str = m_err_leftover + QString::fromLocal8Bit(data);
- m_err_leftover.clear();
+
QStringList lines = str.split("\n");
- bool complete = str.endsWith("\n");
+ m_err_leftover = lines.takeLast();
- for (int i = 0; i < lines.size() - 1; i++)
- {
- QString &line = lines[i];
- emit log(censorPrivateInfo(line), getLevel(line, MessageLevel::Error));
- }
- if (!complete)
- m_err_leftover = lines.last();
+ logOutput(lines, MessageLevel::Error);
}
void MinecraftProcess::on_stdOut()
{
QByteArray data = readAllStandardOutput();
QString str = m_out_leftover + QString::fromLocal8Bit(data);
- m_out_leftover.clear();
+
QStringList lines = str.split("\n");
- bool complete = str.endsWith("\n");
+ m_out_leftover = lines.takeLast();
- for (int i = 0; i < lines.size() - 1; i++)
- {
- QString &line = lines[i];
- emit log(censorPrivateInfo(line), getLevel(line, MessageLevel::Message));
- }
- if (!complete)
- m_out_leftover = lines.last();
+ logOutput(lines);
+}
+
+void MinecraftProcess::on_prepost_stdErr()
+{
+ QByteArray data = m_prepostlaunchprocess.readAllStandardError();
+ QString str = m_err_leftover + QString::fromLocal8Bit(data);
+
+ QStringList lines = str.split("\n");
+ m_err_leftover = lines.takeLast();
+
+ logOutput(lines, MessageLevel::PrePost, false, false);
+}
+
+void MinecraftProcess::on_prepost_stdOut()
+{
+ QByteArray data = m_prepostlaunchprocess.readAllStandardOutput();
+ QString str = m_out_leftover + QString::fromLocal8Bit(data);
+
+ QStringList lines = str.split("\n");
+ m_out_leftover = lines.takeLast();
+
+ logOutput(lines, MessageLevel::PrePost, false, false);
}
// exit handler
void MinecraftProcess::finish(int code, ExitStatus status)
{
+ // Flush console window
+ if (!m_err_leftover.isEmpty())
+ {
+ logOutput(m_err_leftover, MessageLevel::Error);
+ m_err_leftover.clear();
+ }
+ if (!m_out_leftover.isEmpty())
+ {
+ logOutput(m_out_leftover);
+ m_out_leftover.clear();
+ }
+
if (!killed)
{
if (status == NormalExit)
@@ -153,15 +257,32 @@ void MinecraftProcess::finish(int code, ExitStatus status)
m_prepostlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(code));
// run post-exit
- if (!m_instance->settings().get("PostExitCommand").toString().isEmpty())
+ QString postlaunch_cmd = m_instance->settings().get("PostExitCommand").toString();
+ if (!postlaunch_cmd.isEmpty())
{
- m_prepostlaunchprocess.start(m_instance->settings().get("PostExitCommand").toString());
+ emit log(tr("Running Post-Launch command: %1").arg(postlaunch_cmd));
+ m_prepostlaunchprocess.start(postlaunch_cmd);
m_prepostlaunchprocess.waitForFinished();
+ // Flush console window
+ if (!m_err_leftover.isEmpty())
+ {
+ logOutput(m_err_leftover, MessageLevel::PrePost);
+ m_err_leftover.clear();
+ }
+ if (!m_out_leftover.isEmpty())
+ {
+ logOutput(m_out_leftover, MessageLevel::PrePost);
+ m_out_leftover.clear();
+ }
if (m_prepostlaunchprocess.exitStatus() != NormalExit)
{
+ emit log(tr("Post-Launch command failed with code %1.\n\n").arg(m_prepostlaunchprocess.exitCode()),
+ MessageLevel::Error);
emit postlaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(),
m_prepostlaunchprocess.exitStatus());
}
+ else
+ emit log(tr("Post-Launch command ran successfully.\n\n"));
}
m_instance->cleanupAfterRun();
emit ended(m_instance, code, status);
@@ -175,27 +296,78 @@ void MinecraftProcess::killMinecraft()
void MinecraftProcess::launch()
{
- if (!m_instance->settings().get("PreLaunchCommand").toString().isEmpty())
+ emit log("MultiMC version: " + MMC->version().toString() + "\n\n");
+ emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n");
+
+ QString prelaunch_cmd = m_instance->settings().get("PreLaunchCommand").toString();
+ if (!prelaunch_cmd.isEmpty())
{
- m_prepostlaunchprocess.start(m_instance->settings().get("PreLaunchCommand").toString());
+ // Launch
+ emit log(tr("Running Pre-Launch command: %1").arg(prelaunch_cmd));
+ m_prepostlaunchprocess.start(prelaunch_cmd);
+ // Wait
m_prepostlaunchprocess.waitForFinished();
+ // Flush console window
+ if (!m_err_leftover.isEmpty())
+ {
+ logOutput(m_err_leftover, MessageLevel::PrePost);
+ m_err_leftover.clear();
+ }
+ if (!m_out_leftover.isEmpty())
+ {
+ logOutput(m_out_leftover, MessageLevel::PrePost);
+ m_out_leftover.clear();
+ }
+ // Process return values
if (m_prepostlaunchprocess.exitStatus() != NormalExit)
{
+ emit log(tr("Pre-Launch command failed with code %1.\n\n").arg(m_prepostlaunchprocess.exitCode()),
+ MessageLevel::Fatal);
m_instance->cleanupAfterRun();
emit prelaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(),
m_prepostlaunchprocess.exitStatus());
return;
}
+ else
+ emit log(tr("Pre-Launch command ran successfully.\n\n"));
}
m_instance->setLastLaunch();
+ auto &settings = m_instance->settings();
+
+ //////////// java arguments ////////////
+ QStringList args;
+ {
+ // custom args go first. we want to override them if we have our own here.
+ args.append(m_instance->extraArguments());
+
+ // OSX dock icon and name
+ #ifdef OSX
+ args << "-Xdock:icon=icon.png";
+ args << QString("-Xdock:name=\"%1\"").arg(m_instance->windowTitle());
+ #endif
+
+ // HACK: Stupid hack for Intel drivers. See: https://mojang.atlassian.net/browse/MCL-767
+ #ifdef Q_OS_WIN32
+ args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_"
+ "minecraft.exe.heapdump");
+ #endif
+
+ args << QString("-Xms%1m").arg(settings.get("MinMemAlloc").toInt());
+ args << QString("-Xmx%1m").arg(settings.get("MaxMemAlloc").toInt());
+ args << QString("-XX:PermSize=%1m").arg(settings.get("PermGen").toInt());
+ if(!m_nativeFolder.isEmpty())
+ args << QString("-Djava.library.path=%1").arg(m_nativeFolder);
+ args << "-jar" << PathCombine(MMC->bin(), "jars", "NewLaunch.jar");
+ }
- emit log(QString("Minecraft folder is: '%1'").arg(workingDirectory()));
QString JavaPath = m_instance->settings().get("JavaPath").toString();
- emit log(QString("Java path: '%1'").arg(JavaPath));
- QString allArgs = m_args.join("' '");
- emit log(QString("Arguments: '%1'").arg(censorPrivateInfo(allArgs)));
- start(JavaPath, m_args);
+ emit log("Java path is:\n" + JavaPath + "\n\n");
+ QString allArgs = args.join(", ");
+ emit log("Java Arguments:\n[" + censorPrivateInfo(allArgs) + "]\n\n");
+
+ // instantiate the launcher part
+ start(JavaPath, args);
if (!waitForStarted())
{
//: Error message displayed if instace can't start
@@ -204,21 +376,7 @@ void MinecraftProcess::launch()
emit launch_failed(m_instance);
return;
}
-}
-
-MessageLevel::Enum MinecraftProcess::getLevel(const QString &line, MessageLevel::Enum level)
-{
-
- if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") ||
- line.contains("[FINER]") || line.contains("[FINEST]"))
- level = MessageLevel::Message;
- if (line.contains("[SEVERE]") || line.contains("[STDERR]"))
- level = MessageLevel::Error;
- if (line.contains("[WARNING]"))
- level = MessageLevel::Warning;
- if (line.contains("Exception in thread") || line.contains(" at "))
- level = MessageLevel::Fatal;
- if (line.contains("[DEBUG]"))
- level = MessageLevel::Debug;
- return level;
+ // send the launch script to the launcher part
+ QByteArray bytes = launchScript.toUtf8();
+ writeData(bytes.constData(), bytes.length());
}
diff --git a/logic/MinecraftProcess.h b/logic/MinecraftProcess.h
index bd0151cc..70e5df52 100644
--- a/logic/MinecraftProcess.h
+++ b/logic/MinecraftProcess.h
@@ -18,7 +18,7 @@
#pragma once
#include <QProcess>
-
+#include <QString>
#include "BaseInstance.h"
/**
@@ -31,11 +31,12 @@ enum Enum
{
MultiMC, /**< MultiMC Messages */
Debug, /**< Debug Messages */
- Info, /**< Info Messages */
+ Info, /**< Info Messages */
Message, /**< Standard Messages */
Warning, /**< Warnings */
Error, /**< Errors */
- Fatal /**< Fatal Errors */
+ Fatal, /**< Fatal Errors */
+ PrePost, /**< Pre/Post Launch command output */
};
}
@@ -65,7 +66,15 @@ public:
void setWorkdir(QString path);
- void setArguments(QStringList args);
+ void setLaunchScript(QString script)
+ {
+ launchScript = script;
+ }
+
+ void setNativeFolder(QString natives)
+ {
+ m_nativeFolder = natives;
+ }
void killMinecraft();
@@ -104,21 +113,30 @@ signals:
protected:
BaseInstance *m_instance = nullptr;
- QStringList m_args;
QString m_err_leftover;
QString m_out_leftover;
QProcess m_prepostlaunchprocess;
bool killed = false;
MojangAccountPtr m_account;
+ QString launchScript;
+ QString m_nativeFolder;
protected
slots:
void finish(int, QProcess::ExitStatus status);
void on_stdErr();
void on_stdOut();
+ void on_prepost_stdOut();
+ void on_prepost_stdErr();
+ void logOutput(const QStringList &lines,
+ MessageLevel::Enum defaultLevel = MessageLevel::Message,
+ bool guessLevel = true, bool censor = true);
+ void logOutput(QString line,
+ MessageLevel::Enum defaultLevel = MessageLevel::Message,
+ bool guessLevel = true, bool censor = true);
private:
QString censorPrivateInfo(QString in);
- MessageLevel::Enum getLevel(const QString &message, MessageLevel::Enum defaultLevel);
-
+ MessageLevel::Enum guessLevel(const QString &message, MessageLevel::Enum defaultLevel);
+ MessageLevel::Enum getLevel(const QString &levelName);
};
diff --git a/logic/NagUtils.cpp b/logic/NagUtils.cpp
index 6f81b3c7..c963a98a 100644
--- a/logic/NagUtils.cpp
+++ b/logic/NagUtils.cpp
@@ -23,15 +23,15 @@ void checkJVMArgs(QString jvmargs, QWidget *parent)
if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegExp("-Xm[sx]")))
{
CustomMessageBox::selectable(
- parent, parent->tr("JVM arguments warning"),
- parent->tr("You tried to manually set a JVM memory option (using "
- " \"-XX:PermSize\", \"-Xmx\" or \"-Xms\") - there"
- " are dedicated boxes for these in the settings (Java"
- " tab, in the Memory group at the top).\n"
- "Your manual settings will be overridden by the"
- " dedicated options.\n"
- "This message will be displayed until you remove them"
- " from the JVM arguments."),
+ parent, QObject::tr("JVM arguments warning"),
+ QObject::tr("You tried to manually set a JVM memory option (using "
+ " \"-XX:PermSize\", \"-Xmx\" or \"-Xms\") - there"
+ " are dedicated boxes for these in the settings (Java"
+ " tab, in the Memory group at the top).\n"
+ "Your manual settings will be overridden by the"
+ " dedicated options.\n"
+ "This message will be displayed until you remove them"
+ " from the JVM arguments."),
QMessageBox::Warning)->exec();
}
}
diff --git a/logic/OneSixFTBInstance.cpp b/logic/OneSixFTBInstance.cpp
index 4bb5cf42..e50a5b53 100644
--- a/logic/OneSixFTBInstance.cpp
+++ b/logic/OneSixFTBInstance.cpp
@@ -92,6 +92,11 @@ OneSixFTBInstance::OneSixFTBInstance(const QString &rootDir, SettingsObject *set
}
}
+QString OneSixFTBInstance::id() const
+{
+ return "FTB/" + BaseInstance::id();
+}
+
QString OneSixFTBInstance::getStatusbarDescription()
{
return "OneSix FTB: " + intendedVersionId();
diff --git a/logic/OneSixFTBInstance.h b/logic/OneSixFTBInstance.h
index 7600090c..dc028819 100644
--- a/logic/OneSixFTBInstance.h
+++ b/logic/OneSixFTBInstance.h
@@ -15,6 +15,8 @@ public:
virtual std::shared_ptr<Task> doUpdate(bool only_prepare) override;
+ virtual QString id() const;
+
private:
std::shared_ptr<OneSixLibrary> m_forge;
};
diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp
index 2392c683..3cfc1c76 100644
--- a/logic/OneSixInstance.cpp
+++ b/logic/OneSixInstance.cpp
@@ -13,12 +13,14 @@
* limitations under the License.
*/
+#include "MultiMC.h"
#include "OneSixInstance.h"
#include "OneSixInstance_p.h"
#include "OneSixUpdate.h"
#include "MinecraftProcess.h"
#include "OneSixVersion.h"
#include "JavaChecker.h"
+#include "logic/icons/IconList.h"
#include <setting.h>
#include <pathutils.h>
@@ -27,6 +29,7 @@
#include "gui/dialogs/OneSixModEditDialog.h"
#include "logger/QsLog.h"
#include "logic/assets/AssetsUtils.h"
+#include <QIcon>
OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_obj,
QObject *parent)
@@ -40,7 +43,7 @@ OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_o
std::shared_ptr<Task> OneSixInstance::doUpdate(bool only_prepare)
{
- return std::shared_ptr<Task> (new OneSixUpdate(this, only_prepare));
+ return std::shared_ptr<Task>(new OneSixUpdate(this, only_prepare));
}
QString replaceTokensIn(QString text, QMap<QString, QString> with)
@@ -78,47 +81,50 @@ QDir OneSixInstance::reconstructAssets(std::shared_ptr<OneSixVersion> version)
QFile indexFile(indexPath);
QDir virtualRoot(PathCombine(virtualDir.path(), version->assets));
- if(!indexFile.exists())
+ if (!indexFile.exists())
{
QLOG_ERROR() << "No assets index file" << indexPath << "; can't reconstruct assets";
return virtualRoot;
}
- QLOG_DEBUG() << "reconstructAssets" << assetsDir.path() << indexDir.path() << objectDir.path() << virtualDir.path() << virtualRoot.path();
+ QLOG_DEBUG() << "reconstructAssets" << assetsDir.path() << indexDir.path()
+ << objectDir.path() << virtualDir.path() << virtualRoot.path();
AssetsIndex index;
bool loadAssetsIndex = AssetsUtils::loadAssetsIndexJson(indexPath, &index);
- if(loadAssetsIndex)
+ if (loadAssetsIndex && index.isVirtual)
{
- if(index.isVirtual)
- {
- QLOG_INFO() << "Reconstructing virtual assets folder at" << virtualRoot.path();
+ QLOG_INFO() << "Reconstructing virtual assets folder at" << virtualRoot.path();
- for(QString map : index.objects.keys())
+ for (QString map : index.objects.keys())
+ {
+ AssetObject asset_object = index.objects.value(map);
+ QString target_path = PathCombine(virtualRoot.path(), map);
+ QFile target(target_path);
+
+ QString tlk = asset_object.hash.left(2);
+
+ QString original_path =
+ PathCombine(PathCombine(objectDir.path(), tlk), asset_object.hash);
+ QFile original(original_path);
+ if(!original.exists())
+ continue;
+ if (!target.exists())
{
- AssetObject asset_object = index.objects.value(map);
- QString target_path = PathCombine(virtualRoot.path(), map);
- QFile target(target_path);
-
- QString tlk = asset_object.hash.left(2);
-
- QString original_path = PathCombine(PathCombine(objectDir.path(), tlk), asset_object.hash);
- QFile original(original_path);
- if(!target.exists())
- {
- QFileInfo info(target_path);
- QDir target_dir = info.dir();
- //QLOG_DEBUG() << target_dir;
- if(!target_dir.exists()) QDir("").mkpath(target_dir.path());
-
- bool couldCopy = original.copy(target_path);
- QLOG_DEBUG() << " Copying" << original_path << "to" << target_path << QString::number(couldCopy);// << original.errorString();
- }
+ QFileInfo info(target_path);
+ QDir target_dir = info.dir();
+ // QLOG_DEBUG() << target_dir;
+ if (!target_dir.exists())
+ QDir("").mkpath(target_dir.path());
+
+ bool couldCopy = original.copy(target_path);
+ QLOG_DEBUG() << " Copying" << original_path << "to" << target_path
+ << QString::number(couldCopy); // << original.errorString();
}
-
- // TODO: Write last used time to virtualRoot/.lastused
}
+
+ // TODO: Write last used time to virtualRoot/.lastused
}
return virtualRoot;
@@ -155,7 +161,7 @@ QStringList OneSixInstance::processMinecraftArgs(MojangAccountPtr account)
auto user = account->user();
QJsonObject userAttrs;
- for(auto key: user.properties.keys())
+ for (auto key : user.properties.keys())
{
auto array = QJsonArray::fromStringList(user.properties.values(key));
userAttrs.insert(key, array);
@@ -180,71 +186,56 @@ MinecraftProcess *OneSixInstance::prepareForLaunch(MojangAccountPtr account)
{
I_D(OneSixInstance);
- QString natives_dir_raw = PathCombine(instanceRoot(), "natives/");
+ QIcon icon = MMC->icons()->getIcon(iconKey());
+ auto pixmap = icon.pixmap(128, 128);
+ pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG");
auto version = d->version;
if (!version)
return nullptr;
-
- QStringList args;
- args.append(Util::Commandline::splitArgs(settings().get("JvmArgs").toString()));
- args << QString("-Xms%1m").arg(settings().get("MinMemAlloc").toInt());
- args << QString("-Xmx%1m").arg(settings().get("MaxMemAlloc").toInt());
- args << QString("-XX:PermSize=%1m").arg(settings().get("PermGen").toInt());
-
-/**
- * HACK: Stupid hack for Intel drivers.
- * See: https://mojang.atlassian.net/browse/MCL-767
- */
-#ifdef Q_OS_WIN32
- args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_"
- "minecraft.exe.heapdump");
-#endif
-
- QDir natives_dir(natives_dir_raw);
- args << QString("-Djava.library.path=%1").arg(natives_dir.absolutePath());
- QString classPath;
+ QString launchScript;
{
auto libs = version->getActiveNormalLibs();
for (auto lib : libs)
{
QFileInfo fi(QString("libraries/") + lib->storagePath());
- classPath.append(fi.absoluteFilePath());
-#ifdef Q_OS_WIN32
- classPath.append(';');
-#else
- classPath.append(':');
-#endif
+ launchScript += "cp " + fi.absoluteFilePath() + "\n";
}
QString targetstr = "versions/" + version->id + "/" + version->id + ".jar";
QFileInfo fi(targetstr);
- classPath.append(fi.absoluteFilePath());
+ launchScript += "cp " + fi.absoluteFilePath() + "\n";
}
- if (classPath.size())
+ launchScript += "mainClass " + version->mainClass + "\n";
+
+ for (auto param : processMinecraftArgs(account))
{
- args << "-cp";
- args << classPath;
+ launchScript += "param " + param + "\n";
}
- args << version->mainClass;
- args.append(processMinecraftArgs(account));
// Set the width and height for 1.6 instances
bool maximize = settings().get("LaunchMaximized").toBool();
if (maximize)
{
// this is probably a BAD idea
- // args << QString("--fullscreen");
+ // launchScript += "param --fullscreen\n";
}
else
{
- args << QString("--width") << settings().get("MinecraftWinWidth").toString();
- args << QString("--height") << settings().get("MinecraftWinHeight").toString();
+ launchScript +=
+ "param --width\nparam " + settings().get("MinecraftWinWidth").toString() + "\n";
+ launchScript +=
+ "param --height\nparam " + settings().get("MinecraftWinHeight").toString() + "\n";
}
+ QDir natives_dir(PathCombine(instanceRoot(), "natives/"));
+ launchScript += "windowTitle " + windowTitle() + "\n";
+ launchScript += "natives " + natives_dir.absolutePath() + "\n";
+ launchScript += "launch onesix\n";
// create the process and set its parameters
MinecraftProcess *proc = new MinecraftProcess(this);
- proc->setArguments(args);
proc->setWorkdir(minecraftRoot());
+ proc->setLaunchScript(launchScript);
+ // proc->setNativeFolder(natives_dir.absolutePath());
return proc;
}
diff --git a/logic/OneSixLibrary.cpp b/logic/OneSixLibrary.cpp
index 4b6ed9dc..d1eceb0e 100644
--- a/logic/OneSixLibrary.cpp
+++ b/logic/OneSixLibrary.cpp
@@ -19,6 +19,9 @@
#include "OneSixRule.h"
#include "OpSys.h"
#include "logic/net/URLConstants.h"
+#include <pathutils.h>
+#include <JlCompress.h>
+#include "logger/QsLog.h"
void OneSixLibrary::finalize()
{
@@ -133,6 +136,90 @@ QString OneSixLibrary::hint()
return m_hint;
}
+bool OneSixLibrary::filesExist()
+{
+ QString storage = storagePath();
+ if (storage.contains("${arch}"))
+ {
+ QString cooked_storage = storage;
+ cooked_storage.replace("${arch}", "32");
+ QFileInfo info32(PathCombine("libraries", cooked_storage));
+ if (!info32.exists())
+ {
+ return false;
+ }
+ cooked_storage = storage;
+ cooked_storage.replace("${arch}", "64");
+ QFileInfo info64(PathCombine("libraries", cooked_storage));
+ if (!info64.exists())
+ {
+ return false;
+ }
+ }
+ else
+ {
+ QFileInfo info(PathCombine("libraries", storage));
+ if (!info.exists())
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool OneSixLibrary::extractTo(QString target_dir)
+{
+ QString storage = storagePath();
+ if (storage.contains("${arch}"))
+ {
+ QString cooked_storage = storage;
+ cooked_storage.replace("${arch}", "32");
+ QString origin = PathCombine("libraries", cooked_storage);
+ QString target_dir_cooked = PathCombine(target_dir, "32");
+ if(!ensureFolderPathExists(target_dir_cooked))
+ {
+ QLOG_ERROR() << "Couldn't create folder " + target_dir_cooked;
+ return false;
+ }
+ if (JlCompress::extractWithExceptions(origin, target_dir_cooked, extract_excludes)
+ .isEmpty())
+ {
+ QLOG_ERROR() << "Couldn't extract " + origin;
+ return false;
+ }
+ cooked_storage = storage;
+ cooked_storage.replace("${arch}", "64");
+ origin = PathCombine("libraries", cooked_storage);
+ target_dir_cooked = PathCombine(target_dir, "32");
+ if(!ensureFolderPathExists(target_dir_cooked))
+ {
+ QLOG_ERROR() << "Couldn't create folder " + target_dir_cooked;
+ return false;
+ }
+ if (JlCompress::extractWithExceptions(origin, target_dir_cooked, extract_excludes)
+ .isEmpty())
+ {
+ QLOG_ERROR() << "Couldn't extract " + origin;
+ return false;
+ }
+ }
+ else
+ {
+ if(!ensureFolderPathExists(target_dir))
+ {
+ QLOG_ERROR() << "Couldn't create folder " + target_dir;
+ return false;
+ }
+ QString path = PathCombine("libraries", storage);
+ if (JlCompress::extractWithExceptions(path, target_dir, extract_excludes).isEmpty())
+ {
+ QLOG_ERROR() << "Couldn't extract " + path;
+ return false;
+ }
+ }
+ return true;
+}
+
QJsonObject OneSixLibrary::toJson()
{
QJsonObject libRoot;
diff --git a/logic/OneSixLibrary.h b/logic/OneSixLibrary.h
index 3f0bc83d..227cdbef 100644
--- a/logic/OneSixLibrary.h
+++ b/logic/OneSixLibrary.h
@@ -126,4 +126,7 @@ public:
/// set a hint about how to treat the library. This is an MMC extension.
void setHint(QString hint);
QString hint();
+
+ bool extractTo(QString target_dir);
+ bool filesExist();
};
diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp
index 4d93477a..0119ab07 100644
--- a/logic/OneSixUpdate.cpp
+++ b/logic/OneSixUpdate.cpp
@@ -54,17 +54,7 @@ void OneSixUpdate::executeTask()
if (m_only_prepare)
{
- /*
- * FIXME: in offline mode, do not proceed!
- */
- setStatus(tr("Testing the Java installation..."));
- QString java_path = m_inst->settings().get("JavaPath").toString();
-
- checker.reset(new JavaChecker());
- connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
- SLOT(checkFinishedOffline(JavaCheckResult)));
- checker->path = java_path;
- checker->performCheck();
+ prepareForLaunch();
return;
}
@@ -83,46 +73,8 @@ void OneSixUpdate::executeTask()
}
else
{
- checkJavaOnline();
- }
-}
-
-void OneSixUpdate::checkJavaOnline()
-{
- setStatus(tr("Testing the Java installation..."));
- QString java_path = m_inst->settings().get("JavaPath").toString();
-
- checker.reset(new JavaChecker());
- connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
- SLOT(checkFinishedOnline(JavaCheckResult)));
- checker->path = java_path;
- checker->performCheck();
-}
-
-void OneSixUpdate::checkFinishedOnline(JavaCheckResult result)
-{
- if (result.valid)
- {
- java_is_64bit = result.is_64bit;
jarlibStart();
}
- else
- {
- emitFailed("The java binary doesn't work. Check the settings and correct the problem");
- }
-}
-
-void OneSixUpdate::checkFinishedOffline(JavaCheckResult result)
-{
- if (result.valid)
- {
- java_is_64bit = result.is_64bit;
- prepareForLaunch();
- }
- else
- {
- emitFailed("The java binary doesn't work. Check the settings and correct the problem");
- }
}
void OneSixUpdate::versionFileStart()
@@ -130,7 +82,8 @@ void OneSixUpdate::versionFileStart()
QLOG_INFO() << m_inst->name() << ": getting version file.";
setStatus(tr("Getting the version files from Mojang..."));
- QString urlstr = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json";
+ QString urlstr = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS +
+ targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json";
auto job = new NetJob("Version index");
job->addNetAction(ByteArrayDownload::make(QUrl(urlstr)));
specificVersionDownloadJob.reset(job);
@@ -186,7 +139,7 @@ void OneSixUpdate::versionFileFinished()
}
inst->reloadFullVersion();
- checkJavaOnline();
+ jarlibStart();
}
void OneSixUpdate::versionFileFailed()
@@ -230,7 +183,7 @@ void OneSixUpdate::assetIndexFinished()
{
emitFailed("Failed to read the assets index!");
}
-
+
QList<Md5EtagDownloadPtr> dls;
for (auto object : index.objects.values())
{
@@ -245,17 +198,17 @@ void OneSixUpdate::assetIndexFinished()
dls.append(objectDL);
}
}
- if(dls.size())
+ if (dls.size())
{
setStatus(tr("Getting the assets files from Mojang..."));
auto job = new NetJob("Assets for " + inst->name());
- for(auto dl: dls)
+ for (auto dl : dls)
job->addNetAction(dl);
jarlibDownloadJob.reset(job);
connect(jarlibDownloadJob.get(), SIGNAL(succeeded()), SLOT(assetsFinished()));
connect(jarlibDownloadJob.get(), SIGNAL(failed()), SLOT(assetsFailed()));
connect(jarlibDownloadJob.get(), SIGNAL(progress(qint64, qint64)),
- SIGNAL(progress(qint64, qint64)));
+ SIGNAL(progress(qint64, qint64)));
jarlibDownloadJob->start();
return;
}
@@ -277,8 +230,6 @@ void OneSixUpdate::assetsFailed()
emitFailed("Failed to download assets!");
}
-
-
void OneSixUpdate::jarlibStart()
{
setStatus(tr("Getting the library files from Mojang..."));
@@ -318,24 +269,37 @@ void OneSixUpdate::jarlibStart()
{
if (lib->hint() == "local")
continue;
- QString subst = java_is_64bit ? "64" : "32";
- QString storage = lib->storagePath();
- QString dl = lib->downloadUrl();
- storage.replace("${arch}", subst);
- dl.replace("${arch}", subst);
+ QString raw_storage = lib->storagePath();
+ QString raw_dl = lib->downloadUrl();
- auto entry = metacache->resolveEntry("libraries", storage);
- if (entry->stale)
+ auto f = [&](QString storage, QString dl)
{
- if (lib->hint() == "forge-pack-xz")
+ auto entry = metacache->resolveEntry("libraries", storage);
+ if (entry->stale)
{
- ForgeLibs.append(ForgeXzDownload::make(storage, entry));
- }
- else
- {
- jarlibDownloadJob->addNetAction(CacheDownload::make(dl, entry));
+ if (lib->hint() == "forge-pack-xz")
+ {
+ ForgeLibs.append(ForgeXzDownload::make(storage, entry));
+ }
+ else
+ {
+ jarlibDownloadJob->addNetAction(CacheDownload::make(dl, entry));
+ }
}
+ };
+ if (raw_storage.contains("${arch}"))
+ {
+ QString cooked_storage = raw_storage;
+ QString cooked_dl = raw_dl;
+ f(cooked_storage.replace("${arch}", "32"), cooked_dl.replace("${arch}", "32"));
+ cooked_storage = raw_storage;
+ cooked_dl = raw_dl;
+ f(cooked_storage.replace("${arch}", "64"), cooked_dl.replace("${arch}", "64"));
+ }
+ else
+ {
+ f(raw_storage, raw_dl);
}
}
// TODO: think about how to propagate this from the original json file... or IF AT ALL
@@ -376,7 +340,6 @@ void OneSixUpdate::prepareForLaunch()
// delete any leftovers, if they are present.
onesix_inst->cleanupAfterRun();
- // Acquire swag
QString natives_dir_raw = PathCombine(onesix_inst->instanceRoot(), "natives/");
auto version = onesix_inst->getFullVersion();
if (!version)
@@ -385,38 +348,30 @@ void OneSixUpdate::prepareForLaunch()
"it or changing the version.");
return;
}
- auto libs_to_extract = version->getActiveNativeLibs();
-
- // Acquire bag
- bool success = ensureFolderPathExists(natives_dir_raw);
- if (!success)
- {
- emitFailed("Could not create the native library folder:\n" + natives_dir_raw +
- "\nMake sure MultiMC has appropriate permissions and there is enough space "
- "on the storage device.");
- return;
- }
-
- // Put swag in the bag
- QString subst = java_is_64bit ? "64" : "32";
- for (auto lib : libs_to_extract)
+ /*
+ * emitFailed("Could not create the native library folder:\n" + natives_dir_raw +
+ "\nMake sure MultiMC has appropriate permissions and there is enough
+ space "
+ "on the storage device.");
+ */
+ for (auto lib : version->getActiveNativeLibs())
{
- QString storage = lib->storagePath();
- storage.replace("${arch}", subst);
-
- QString path = "libraries/" + storage;
- QLOG_INFO() << "Will extract " << path.toLocal8Bit();
- if (JlCompress::extractWithExceptions(path, natives_dir_raw, lib->extract_excludes)
- .isEmpty())
+ if (!lib->filesExist())
+ {
+ emitFailed("Native library is missing some files:\n" + lib->storagePath() +
+ "\n\nRun the instance at least once in online mode to get all the "
+ "required files.");
+ return;
+ }
+ if (!lib->extractTo(natives_dir_raw))
{
- emitFailed(
- "Could not extract the native library:\n" + path +
- "\nMake sure MultiMC has appropriate permissions and there is enough space "
- "on the storage device.");
+ emitFailed("Could not extract the native library:\n" + lib->storagePath() + " to " +
+ natives_dir_raw +
+ "\n\nMake sure MultiMC has appropriate permissions and there is enough "
+ "space on the storage device.");
return;
}
}
- // Show them your war face!
emitSucceeded();
}
diff --git a/logic/OneSixUpdate.h b/logic/OneSixUpdate.h
index 00b769c7..bc717a94 100644
--- a/logic/OneSixUpdate.h
+++ b/logic/OneSixUpdate.h
@@ -21,7 +21,6 @@
#include "logic/net/NetJob.h"
#include "logic/tasks/Task.h"
-#include "logic/JavaChecker.h"
class MinecraftVersion;
class BaseInstance;
@@ -50,10 +49,6 @@ slots:
void assetsFinished();
void assetsFailed();
- void checkJavaOnline();
- void checkFinishedOnline(JavaCheckResult result);
- void checkFinishedOffline(JavaCheckResult result);
-
// extract the appropriate libraries
void prepareForLaunch();
@@ -65,7 +60,4 @@ private:
std::shared_ptr<MinecraftVersion> targetVersion;
BaseInstance *m_inst = nullptr;
bool m_only_prepare = false;
- std::shared_ptr<JavaChecker> checker;
-
- bool java_is_64bit = false;
};
diff --git a/logic/auth/MojangAccount.cpp b/logic/auth/MojangAccount.cpp
index a462eda5..f41985ec 100644
--- a/logic/auth/MojangAccount.cpp
+++ b/logic/auth/MojangAccount.cpp
@@ -198,7 +198,11 @@ void MojangAccount::authFailed(QString reason)
{
// This is emitted when the yggdrasil tasks time out or are cancelled.
// -> we treat the error as no-op
- if (reason != "Yggdrasil task cancelled.")
+ if (reason == "Yggdrasil task cancelled.")
+ {
+ // do nothing
+ }
+ else
{
m_online = false;
m_accessToken = QString();
diff --git a/logic/lists/ForgeVersionList.cpp b/logic/lists/ForgeVersionList.cpp
index 56eca744..4902dc64 100644
--- a/logic/lists/ForgeVersionList.cpp
+++ b/logic/lists/ForgeVersionList.cpp
@@ -187,7 +187,7 @@ bool ForgeListLoadTask::parseForgeList(QList<BaseVersionPtr> &out)
QByteArray data;
{
auto dlJob = listDownload;
- auto filename = std::dynamic_pointer_cast<CacheDownload>(dlJob)->m_target_path;
+ auto filename = std::dynamic_pointer_cast<CacheDownload>(dlJob)->getTargetFilepath();
QFile listFile(filename);
if (!listFile.open(QIODevice::ReadOnly))
{
@@ -303,7 +303,7 @@ bool ForgeListLoadTask::parseForgeGradleList(QList<BaseVersionPtr> &out)
QByteArray data;
{
auto dlJob = gradleListDownload;
- auto filename = std::dynamic_pointer_cast<CacheDownload>(dlJob)->m_target_path;
+ auto filename = std::dynamic_pointer_cast<CacheDownload>(dlJob)->getTargetFilepath();
QFile listFile(filename);
if (!listFile.open(QIODevice::ReadOnly))
{
@@ -404,12 +404,8 @@ void ForgeListLoadTask::listDownloaded()
{
return;
}
-
- qSort(list.begin(), list.end(), [](const BaseVersionPtr & p1, const BaseVersionPtr & p2)
- {
- // TODO better comparison (takes major/minor/build number into account)
- return p1->name() > p2->name();
- });
+ std::sort(list.begin(), list.end(), [](const BaseVersionPtr & l, const BaseVersionPtr & r)
+ { return (*l > *r); });
m_list->updateListData(list);
diff --git a/logic/lists/ForgeVersionList.h b/logic/lists/ForgeVersionList.h
index 924084ae..b19d3f56 100644
--- a/logic/lists/ForgeVersionList.h
+++ b/logic/lists/ForgeVersionList.h
@@ -29,25 +29,38 @@ typedef std::shared_ptr<ForgeVersion> ForgeVersionPtr;
struct ForgeVersion : public BaseVersion
{
- virtual QString descriptor()
+ virtual QString descriptor() override
{
return filename;
}
;
- virtual QString name()
+ virtual QString name() override
{
return "Forge " + jobbuildver;
}
;
- virtual QString typeString() const
+ virtual QString typeString() const override
{
if (installer_url.isEmpty())
return "Universal";
else
return "Installer";
}
- ;
+ virtual bool operator<(BaseVersion &a) override
+ {
+ ForgeVersion *pa = dynamic_cast<ForgeVersion *>(&a);
+ if(!pa)
+ return true;
+ return m_buildnr < pa->m_buildnr;
+ }
+ virtual bool operator>(BaseVersion &a) override
+ {
+ ForgeVersion *pa = dynamic_cast<ForgeVersion *>(&a);
+ if(!pa)
+ return false;
+ return m_buildnr > pa->m_buildnr;
+ }
int m_buildnr = 0;
QString universal_url;
QString changelog_url;
diff --git a/logic/lists/InstanceList.cpp b/logic/lists/InstanceList.cpp
index bfd183d9..0d4eab95 100644
--- a/logic/lists/InstanceList.cpp
+++ b/logic/lists/InstanceList.cpp
@@ -308,45 +308,52 @@ void InstanceList::loadForgeInstances(QMap<QString, QString> groupMap)
return;
}
dir.cd("ModPacks");
- auto fpath = dir.absoluteFilePath("modpacks.xml");
- QFile f(fpath);
- QLOG_INFO() << "Discovering FTB instances -- " << fpath;
- if (!f.open(QFile::ReadOnly))
- return;
-
- // read the FTB packs XML.
- QXmlStreamReader reader(&f);
- while (!reader.atEnd())
+ auto allFiles = dir.entryList(QDir::Readable | QDir::Files, QDir::Name);
+ for(auto filename: allFiles)
{
- switch (reader.readNext())
- {
- case QXmlStreamReader::StartElement:
+ if(!filename.endsWith(".xml"))
+ continue;
+ auto fpath = dir.absoluteFilePath(filename);
+ QFile f(fpath);
+ QLOG_INFO() << "Discovering FTB instances -- " << fpath;
+ if (!f.open(QFile::ReadOnly))
+ continue;
+
+ // read the FTB packs XML.
+ QXmlStreamReader reader(&f);
+ while (!reader.atEnd())
{
- if (reader.name() == "modpack")
+ switch (reader.readNext())
{
- QXmlStreamAttributes attrs = reader.attributes();
- FTBRecord record;
- record.dir = attrs.value("dir").toString();
- QDir test(dataDir.absoluteFilePath(record.dir));
- if(!test.exists())
- continue;
- record.name = attrs.value("name").toString();
- record.logo = attrs.value("logo").toString();
- record.mcVersion = attrs.value("mcVersion").toString();
- record.description = attrs.value("description").toString();
- records.append(record);
+ case QXmlStreamReader::StartElement:
+ {
+ if (reader.name() == "modpack")
+ {
+ QXmlStreamAttributes attrs = reader.attributes();
+ FTBRecord record;
+ record.dir = attrs.value("dir").toString();
+ QDir test(dataDir.absoluteFilePath(record.dir));
+ if(!test.exists())
+ continue;
+ record.name = attrs.value("name").toString();
+ record.logo = attrs.value("logo").toString();
+ record.mcVersion = attrs.value("mcVersion").toString();
+ record.description = attrs.value("description").toString();
+ records.append(record);
+ }
+ break;
+ }
+ case QXmlStreamReader::EndElement:
+ break;
+ case QXmlStreamReader::Characters:
+ break;
+ default:
+ break;
}
- break;
- }
- case QXmlStreamReader::EndElement:
- break;
- case QXmlStreamReader::Characters:
- break;
- default:
- break;
}
+ f.close();
}
- f.close();
+
if(!records.size())
{
QLOG_INFO() << "No FTB instances to load.";
diff --git a/logic/lists/JavaVersionList.cpp b/logic/lists/JavaVersionList.cpp
index e8c5acd0..eb1c5650 100644
--- a/logic/lists/JavaVersionList.cpp
+++ b/logic/lists/JavaVersionList.cpp
@@ -182,13 +182,17 @@ void JavaListLoadTask::executeTask()
connect(m_job.get(), SIGNAL(progress(int, int)), this, SLOT(checkerProgress(int, int)));
QLOG_DEBUG() << "Probing the following Java paths: ";
+ int id = 0;
for(QString candidate : candidate_paths)
{
QLOG_DEBUG() << " " << candidate;
auto candidate_checker = new JavaChecker();
candidate_checker->path = candidate;
+ candidate_checker->id = id;
m_job->addJavaCheckerAction(JavaCheckerPtr(candidate_checker));
+
+ id++;
}
m_job->start();
diff --git a/logic/net/CacheDownload.cpp b/logic/net/CacheDownload.cpp
index 6eadae39..d2a9bdee 100644
--- a/logic/net/CacheDownload.cpp
+++ b/logic/net/CacheDownload.cpp
@@ -33,25 +33,44 @@ CacheDownload::CacheDownload(QUrl url, MetaEntryPtr entry)
void CacheDownload::start()
{
+ m_status = Job_InProgress;
if (!m_entry->stale)
{
+ m_status = Job_Finished;
emit succeeded(m_index_within_job);
return;
}
- m_output_file.setFileName(m_target_path);
+ // create a new save file
+ m_output_file.reset(new QSaveFile(m_target_path));
+
// if there already is a file and md5 checking is in effect and it can be opened
if (!ensureFilePathExists(m_target_path))
{
+ QLOG_ERROR() << "Could not create folder for " + m_target_path;
+ m_status = Job_Failed;
+ emit failed(m_index_within_job);
+ return;
+ }
+ if (!m_output_file->open(QIODevice::WriteOnly))
+ {
+ QLOG_ERROR() << "Could not open " + m_target_path + " for writing";
+ m_status = Job_Failed;
emit failed(m_index_within_job);
return;
}
QLOG_INFO() << "Downloading " << m_url.toString();
QNetworkRequest request(m_url);
- if (m_entry->remote_changed_timestamp.size())
- request.setRawHeader(QString("If-Modified-Since").toLatin1(),
- m_entry->remote_changed_timestamp.toLatin1());
- if (m_entry->etag.size())
- request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->etag.toLatin1());
+
+ // check file consistency first.
+ QFile current(m_target_path);
+ if(current.exists() && current.size() != 0)
+ {
+ if (m_entry->remote_changed_timestamp.size())
+ request.setRawHeader(QString("If-Modified-Since").toLatin1(),
+ m_entry->remote_changed_timestamp.toLatin1());
+ if (m_entry->etag.size())
+ request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->etag.toLatin1());
+ }
request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Cached)");
@@ -77,76 +96,74 @@ void CacheDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
void CacheDownload::downloadError(QNetworkReply::NetworkError error)
{
// error happened during download.
- QLOG_ERROR() << "Failed" << m_url.toString() << "with reason" << error;
+ QLOG_ERROR() << "Failed " << m_url.toString() << " with reason " << error;
m_status = Job_Failed;
}
void CacheDownload::downloadFinished()
{
// if the download succeeded
- if (m_status != Job_Failed)
+ if (m_status == Job_Failed)
{
+ m_output_file->cancelWriting();
+ m_reply.reset();
+ emit failed(m_index_within_job);
+ return;
+ }
+ // if we wrote any data to the save file, we try to commit the data to the real file.
+ if (wroteAnyData)
+ {
// nothing went wrong...
- m_status = Job_Finished;
- if (m_output_file.isOpen())
+ if (m_output_file->commit())
{
- // save the data to the downloadable if we aren't saving to file
- m_output_file.close();
+ m_status = Job_Finished;
m_entry->md5sum = md5sum.result().toHex().constData();
}
else
{
- if (m_output_file.open(QIODevice::ReadOnly))
- {
- m_entry->md5sum =
- QCryptographicHash::hash(m_output_file.readAll(), QCryptographicHash::Md5)
- .toHex()
- .constData();
- m_output_file.close();
- }
- }
- QFileInfo output_file_info(m_target_path);
-
- m_entry->etag = m_reply->rawHeader("ETag").constData();
- if (m_reply->hasRawHeader("Last-Modified"))
- {
- m_entry->remote_changed_timestamp = m_reply->rawHeader("Last-Modified").constData();
+ QLOG_ERROR() << "Failed to commit changes to " << m_target_path;
+ m_output_file->cancelWriting();
+ m_reply.reset();
+ m_status = Job_Failed;
+ emit failed(m_index_within_job);
+ return;
}
- m_entry->local_changed_timestamp =
- output_file_info.lastModified().toUTC().toMSecsSinceEpoch();
- m_entry->stale = false;
- MMC->metacache()->updateEntry(m_entry);
-
- m_reply.reset();
- emit succeeded(m_index_within_job);
- return;
}
- // else the download failed
else
{
- m_output_file.close();
- m_output_file.remove();
- m_reply.reset();
- emit failed(m_index_within_job);
- return;
+ m_status = Job_Finished;
+ }
+
+ // then get rid of the save file
+ m_output_file.reset();
+
+ QFileInfo output_file_info(m_target_path);
+
+ m_entry->etag = m_reply->rawHeader("ETag").constData();
+ if (m_reply->hasRawHeader("Last-Modified"))
+ {
+ m_entry->remote_changed_timestamp = m_reply->rawHeader("Last-Modified").constData();
}
+ m_entry->local_changed_timestamp =
+ output_file_info.lastModified().toUTC().toMSecsSinceEpoch();
+ m_entry->stale = false;
+ MMC->metacache()->updateEntry(m_entry);
+
+ m_reply.reset();
+ emit succeeded(m_index_within_job);
+ return;
}
void CacheDownload::downloadReadyRead()
{
- if (!m_output_file.isOpen())
- {
- if (!m_output_file.open(QIODevice::WriteOnly))
- {
- /*
- * Can't open the file... the job failed
- */
- m_reply->abort();
- emit failed(m_index_within_job);
- return;
- }
- }
QByteArray ba = m_reply->readAll();
md5sum.addData(ba);
- m_output_file.write(ba);
+ if (m_output_file->write(ba) != ba.size())
+ {
+ QLOG_ERROR() << "Failed writing into " + m_target_path;
+ m_status = Job_Failed;
+ m_reply->abort();
+ emit failed(m_index_within_job);
+ }
+ wroteAnyData = true;
}
diff --git a/logic/net/CacheDownload.h b/logic/net/CacheDownload.h
index e25aecd2..154f5988 100644
--- a/logic/net/CacheDownload.h
+++ b/logic/net/CacheDownload.h
@@ -17,29 +17,34 @@
#include "NetAction.h"
#include "HttpMetaCache.h"
-#include <QFile>
-#include <qcryptographichash.h>
+#include <QCryptographicHash>
+#include <QSaveFile>
typedef std::shared_ptr<class CacheDownload> CacheDownloadPtr;
class CacheDownload : public NetAction
{
Q_OBJECT
-public:
+private:
MetaEntryPtr m_entry;
/// if saving to file, use the one specified in this string
QString m_target_path;
/// this is the output file, if any
- QFile m_output_file;
+ std::shared_ptr<QSaveFile> m_output_file;
/// the hash-as-you-download
QCryptographicHash md5sum;
+ bool wroteAnyData = false;
+
public:
explicit CacheDownload(QUrl url, MetaEntryPtr entry);
static CacheDownloadPtr make(QUrl url, MetaEntryPtr entry)
{
return CacheDownloadPtr(new CacheDownload(url, entry));
}
-
+ QString getTargetFilepath()
+ {
+ return m_target_path;
+ }
protected
slots:
virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
diff --git a/logic/net/URLConstants.h b/logic/net/URLConstants.h
index 9579198d..8cb1f3fd 100644
--- a/logic/net/URLConstants.h
+++ b/logic/net/URLConstants.h
@@ -31,4 +31,6 @@ const QString SKINS_BASE("skins.minecraft.net/MinecraftSkins/");
const QString AUTH_BASE("authserver.mojang.com/");
const QString FORGE_LEGACY_URL("http://files.minecraftforge.net/minecraftforge/json");
const QString FORGE_GRADLE_URL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/json");
+const QString MOJANG_STATUS_URL("http://status.mojang.com/check");
+const QString MOJANG_STATUS_NEWS_URL("http://status.mojang.com/news");
}
diff --git a/logic/status/StatusChecker.cpp b/logic/status/StatusChecker.cpp
new file mode 100644
index 00000000..66f800ae
--- /dev/null
+++ b/logic/status/StatusChecker.cpp
@@ -0,0 +1,137 @@
+/* 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 "StatusChecker.h"
+
+#include <logic/net/URLConstants.h>
+
+#include <QByteArray>
+#include <QDomDocument>
+
+#include <logger/QsLog.h>
+
+StatusChecker::StatusChecker()
+{
+
+}
+
+void StatusChecker::reloadStatus()
+{
+ if (isLoadingStatus())
+ {
+ // QLOG_INFO() << "Ignored request to reload status. Currently reloading already.";
+ return;
+ }
+
+ // QLOG_INFO() << "Reloading status.";
+
+ NetJob* job = new NetJob("Status JSON");
+ job->addNetAction(ByteArrayDownload::make(URLConstants::MOJANG_STATUS_URL));
+ QObject::connect(job, &NetJob::succeeded, this, &StatusChecker::statusDownloadFinished);
+ QObject::connect(job, &NetJob::failed, this, &StatusChecker::statusDownloadFailed);
+ m_statusNetJob.reset(job);
+ job->start();
+}
+
+void StatusChecker::statusDownloadFinished()
+{
+ QLOG_DEBUG() << "Finished loading status JSON.";
+
+ QByteArray data;
+ {
+ ByteArrayDownloadPtr dl = std::dynamic_pointer_cast<ByteArrayDownload>(m_statusNetJob->first());
+ data = dl->m_data;
+ m_statusNetJob.reset();
+ }
+
+ QJsonParseError jsonError;
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
+
+ if (jsonError.error != QJsonParseError::NoError)
+ {
+ fail("Error parsing status JSON:" + jsonError.errorString());
+ return;
+ }
+
+ if (!jsonDoc.isArray())
+ {
+ fail("Error parsing status JSON: JSON root is not an array");
+ return;
+ }
+
+ QJsonArray root = jsonDoc.array();
+
+ for(auto status = root.begin(); status != root.end(); ++status)
+ {
+ QVariantMap map = (*status).toObject().toVariantMap();
+
+ for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter)
+ {
+ QString key = iter.key();
+ QVariant value = iter.value();
+
+ if(value.type() == QVariant::Type::String)
+ {
+ m_statusEntries.insert(key, value.toString());
+ //QLOG_DEBUG() << "Status JSON object: " << key << m_statusEntries[key];
+ }
+ else
+ {
+ fail("Malformed status JSON: expected status type to be a string.");
+ return;
+ }
+ }
+ }
+
+ succeed();
+}
+
+void StatusChecker::statusDownloadFailed()
+{
+ fail("Failed to load status JSON.");
+}
+
+
+QMap<QString, QString> StatusChecker::getStatusEntries() const
+{
+ return m_statusEntries;
+}
+
+bool StatusChecker::isLoadingStatus() const
+{
+ return m_statusNetJob.get() != nullptr;
+}
+
+QString StatusChecker::getLastLoadErrorMsg() const
+{
+ return m_lastLoadError;
+}
+
+void StatusChecker::succeed()
+{
+ m_lastLoadError = "";
+ QLOG_DEBUG() << "Status loading succeeded.";
+ m_statusNetJob.reset();
+ emit statusLoaded();
+}
+
+void StatusChecker::fail(const QString& errorMsg)
+{
+ m_lastLoadError = errorMsg;
+ QLOG_DEBUG() << "Failed to load status:" << errorMsg;
+ m_statusNetJob.reset();
+ emit statusLoadingFailed(errorMsg);
+}
+
diff --git a/logic/status/StatusChecker.h b/logic/status/StatusChecker.h
new file mode 100644
index 00000000..1cb01836
--- /dev/null
+++ b/logic/status/StatusChecker.h
@@ -0,0 +1,57 @@
+/* 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 <QObject>
+#include <QString>
+#include <QList>
+
+#include <logic/net/NetJob.h>
+
+class StatusChecker : public QObject
+{
+ Q_OBJECT
+public:
+ StatusChecker();
+
+ QString getLastLoadErrorMsg() const;
+
+ bool isStatusLoaded() const;
+
+ bool isLoadingStatus() const;
+
+ QMap<QString, QString> getStatusEntries() const;
+
+ void Q_SLOT reloadStatus();
+
+signals:
+ void statusLoaded();
+ void statusLoadingFailed(QString errorMsg);
+
+protected slots:
+ void statusDownloadFinished();
+ void statusDownloadFailed();
+
+protected:
+ QMap<QString, QString> m_statusEntries;
+ NetJobPtr m_statusNetJob;
+ bool m_loadedStatus;
+ QString m_lastLoadError;
+
+ void Q_SLOT succeed();
+ void Q_SLOT fail(const QString& errorMsg);
+};
+
diff --git a/logic/updater/NotificationChecker.cpp b/logic/updater/NotificationChecker.cpp
index 40367eac..191e90a3 100644
--- a/logic/updater/NotificationChecker.cpp
+++ b/logic/updater/NotificationChecker.cpp
@@ -5,8 +5,8 @@
#include <QJsonArray>
#include "MultiMC.h"
+#include "MultiMCVersion.h"
#include "logic/net/CacheDownload.h"
-#include "config.h"
NotificationChecker::NotificationChecker(QObject *parent)
: QObject(parent), m_notificationsUrl(QUrl(NOTIFICATION_URL))
@@ -55,7 +55,7 @@ void NotificationChecker::downloadSucceeded(int)
{
m_entries.clear();
- QFile file(m_download->m_output_file.fileName());
+ QFile file(m_download->getTargetFilepath());
if (file.open(QFile::ReadOnly))
{
QJsonArray root = QJsonDocument::fromJson(file.readAll()).array();
@@ -66,7 +66,7 @@ void NotificationChecker::downloadSucceeded(int)
entry.id = obj.value("id").toDouble();
entry.message = obj.value("message").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.to = obj.value("to").toString();
const QString type = obj.value("type").toString("critical");
@@ -93,13 +93,14 @@ void NotificationChecker::downloadSucceeded(int)
bool NotificationChecker::NotificationEntry::applies() const
{
- bool channelApplies = channel.isEmpty() || channel == VERSION_CHANNEL;
- bool buildtypeApplies = buildtype.isEmpty() || buildtype == VERSION_BUILD_TYPE;
+ MultiMCVersion version = MMC->version();
+ bool channelApplies = channel.isEmpty() || channel == version.channel;
+ bool platformApplies = platform.isEmpty() || platform == version.platform;
bool fromApplies =
from.isEmpty() || from == FULL_VERSION_STR || !versionLessThan(FULL_VERSION_STR, from);
bool toApplies =
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,
diff --git a/logic/updater/NotificationChecker.h b/logic/updater/NotificationChecker.h
index 20541757..915ee54d 100644
--- a/logic/updater/NotificationChecker.h
+++ b/logic/updater/NotificationChecker.h
@@ -26,7 +26,7 @@ public:
Information
} type;
QString channel;
- QString buildtype;
+ QString platform;
QString from;
QString to;
bool applies() const;
diff --git a/logic/updater/UpdateChecker.cpp b/logic/updater/UpdateChecker.cpp
index 68d97db5..8e2aa8b3 100644
--- a/logic/updater/UpdateChecker.cpp
+++ b/logic/updater/UpdateChecker.cpp
@@ -141,8 +141,6 @@ void UpdateChecker::updateCheckFinished(bool notifyNoUpdate)
if (newestVersion.value("Id").toVariant().toInt() <
version.value("Id").toVariant().toInt())
{
- QLOG_DEBUG() << "Found newer version with ID"
- << version.value("Id").toVariant().toInt();
newestVersion = version;
}
}
@@ -152,6 +150,7 @@ void UpdateChecker::updateCheckFinished(bool notifyNoUpdate)
int newBuildNumber = newestVersion.value("Id").toVariant().toInt();
if (newBuildNumber != MMC->version().build)
{
+ QLOG_DEBUG() << "Found newer version with ID" << newBuildNumber;
// Update!
emit updateAvailable(m_repoUrl, newestVersion.value("Name").toVariant().toString(),
newBuildNumber);
@@ -261,3 +260,4 @@ void UpdateChecker::chanListDownloadFailed()
QLOG_ERROR() << "Failed to download channel list.";
emit channelListLoaded();
}
+
diff --git a/main.cpp b/main.cpp
index 57131942..c91af978 100644
--- a/main.cpp
+++ b/main.cpp
@@ -19,7 +19,6 @@ int main(int argc, char *argv[])
MultiMC app(argc, argv);
Q_INIT_RESOURCE(graphics);
- Q_INIT_RESOURCE(generated);
switch (app.status())
{
diff --git a/translations/mmc_de.ts b/translations/mmc_de.ts
index 42047378..f1da9766 100644
--- a/translations/mmc_de.ts
+++ b/translations/mmc_de.ts
@@ -1,51 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.0" language="de">
+<TS version="2.1" language="de">
<context>
<name>AboutDialog</name>
<message>
- <location filename="../gui/aboutdialog.ui" line="20"/>
<source>Dialog</source>
- <translation>Dialog</translation>
+ <translation type="vanished">Dialog</translation>
</message>
<message>
- <location filename="../gui/aboutdialog.ui" line="86"/>
+ <location filename="../gui/dialogs/AboutDialog.ui" line="+89"/>
<source>MultiMC</source>
<translation>MultiMC</translation>
</message>
<message>
- <location filename="../gui/aboutdialog.ui" line="108"/>
+ <location line="+22"/>
<source>About</source>
<translation>Über</translation>
</message>
<message>
- <location filename="../gui/aboutdialog.ui" line="114"/>
<source>MultiMC is a custom launcher that makes managing Minecraft easier by allowing you to have multiple installations of Minecraft at once.</source>
- <translation>MultiMC ist ein alternativer Launcher, der das Management von Minecraft vereinfacht, indem er es dir erlaubt, mehrere Installationen von Minecraft zu verwalten.</translation>
+ <translation type="vanished">MultiMC ist ein alternativer Launcher, der das Management von Minecraft vereinfacht, indem er es dir erlaubt, mehrere Installationen von Minecraft zu verwalten.</translation>
</message>
<message>
- <location filename="../gui/aboutdialog.ui" line="133"/>
+ <location line="-91"/>
+ <source>About MultiMC</source>
+ <translation>Über MultiMC</translation>
+ </message>
+ <message>
+ <location line="+100"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;MultiMC is a custom launcher that makes managing Minecraft easier by allowing you to have multiple instances of Minecraft at once.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;MultiMC ist ein alternativer Launcher, der das Management von Minecraft vereinfacht, indem er es dir erlaubt, mehrere Installationen von Minecraft zu verwalten.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+ <message>
+ <location line="+19"/>
<source>© 2013 MultiMC Contributors</source>
<translation>© 2013 MultiMC Contributors</translation>
</message>
<message>
- <location filename="../gui/aboutdialog.ui" line="148"/>
+ <location line="+15"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://github.com/Forkk/MultiMC5&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://github.com/MultiMC/MultiMC5&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
- <location filename="../gui/aboutdialog.ui" line="190"/>
+ <location line="+28"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:7.8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Andrew Okin &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:forkk@forkk.net&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;forkk@forkk.net&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Petr Mrázek &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:peterix@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;peterix@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Sky &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://www.twitter.com/drayshak&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@drayshak&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;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:&apos;Ubuntu&apos;; font-size:10pt; font-weight:600;&quot;&gt;With thanks to&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Orochimarufan &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:orochimarufan.x3@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;orochimarufan.x3@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;TakSuyu &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:taksuyu@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;taksuyu@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Kilobyte &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:stiepen22@gmx.de&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;stiepen22@gmx.de&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Jan (02JanDal) &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:02jandal@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;02jandal@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Robotbrain &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/skylordelros&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@skylordelros&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Rootbear75 &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/rootbear75&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@rootbear75&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt; (build server)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:7.8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Andrew Okin &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:forkk@forkk.net&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;forkk@forkk.net&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Petr Mrázek &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:peterix@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;peterix@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Sky &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://www.twitter.com/drayshak&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@drayshak&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;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:&apos;Ubuntu&apos;; font-size:10pt; font-weight:600;&quot;&gt;Mit dank an&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Orochimarufan &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:orochimarufan.x3@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;orochimarufan.x3@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;TakSuyu &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:taksuyu@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;taksuyu@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Kilobyte &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:stiepen22@gmx.de&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;stiepen22@gmx.de&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Jan (02JanDal) &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:02jandal@gmail.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;02jandal@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Robotbrain &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/skylordelros&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@skylordelros&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Rootbear75 &amp;lt;&lt;/span&gt;&lt;a href=&quot;https://twitter.com/rootbear75&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;@rootbear75&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&amp;gt; (bau server)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+ <message>
+ <location line="+25"/>
<source>No Language file loaded.</source>
- <extracomment>Hey, Translator, You are free to put a reference to you here :)</extracomment>
- <translation>Deutsche Sprachdatei von Kilobyte (siehe oben).</translation>
+ <extracomment>Hey, Translator, feel free to put credit to you here</extracomment>
+ <translation>Deutsche Sprachdatei von Kilobyte (siehe oben). Aktualisiert von xnrand (nsfw auf IRC) und Jan.</translation>
</message>
<message>
- <location filename="../gui/aboutdialog.ui" line="224"/>
+ <location line="+39"/>
<source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;Ubuntu&apos;; 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;&quot;&gt;Copyright 2012 MultiMC Contributors&lt;/span&gt;&lt;/p&gt;
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;DejaVu Sans Mono&apos;; font-size:7.8pt; 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:&apos;Bitstream Vera Sans&apos;; font-size:18pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Copyright 2012-2014 MultiMC Contributors&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;);&lt;/span&gt;&lt;/p&gt;
&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;you may not use this file except in compliance with the 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-size:10pt;&quot;&gt;You may obtain a copy of the License at&lt;/span&gt;&lt;/p&gt;
@@ -58,39 +102,271 @@ p, li { white-space: pre-wrap; }
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;See the License for the specific language governing permissions and&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;limitations under the 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-size:10pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;MultiMC uses QSLog, &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 (c) 2010, Razvan Petru&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;All rights reserved.&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:&apos;Bitstream Vera Sans&apos;; font-size:18pt; font-weight:600;&quot;&gt;QSLog&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Copyright (c) 2010, Razvan Petru&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;All rights reserved.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Redistribution and use in source and binary forms, with or without modification,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;are permitted provided that the following conditions are met:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;* Redistributions of source code must retain the above copyright notice, this&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; list of conditions and the following disclaimer.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;* Redistributions in binary form must reproduce the above copyright notice, this&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; list of conditions and the following disclaimer in the documentation and/or other&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; materials provided with the distribution.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;* The name of the contributors may not be used to endorse or promote products&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; derived from this software without specific prior written permission.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;OF THE POSSIBILITY OF SUCH DAMAGE.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p 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:&apos;Bitstream Vera Sans&apos;; font-size:18pt; font-weight:600;&quot;&gt;Group View (instance view)&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; /*&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Copyright (C) 2007 Rafael Fernández López &amp;lt;ereslibre@kde.org&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Copyright (C) 2007 John Tapsell &amp;lt;tapsell@kde.org&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; *&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * This library is free software; you can redistribute it and/or&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * modify it under the terms of the GNU Library General Public&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * License as published by the Free Software Foundation; either&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * version 2 of the License, or (at your option) any later version.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; *&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * This library is distributed in the hope that it will be useful,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Library General Public License for more details.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; *&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * You should have received a copy of the GNU Library General Public 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-size:8pt;&quot;&gt; * along with this library; see the file COPYING.LIB. If not, write 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:8pt;&quot;&gt; * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Boston, MA 02110-1301, USA.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; */&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:&apos;Bitstream Vera Sans&apos;; font-size:18pt; font-weight:600;&quot;&gt;Pack200&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;The GNU General Public License (GPL)&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Version 2, June 1991&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;+ &amp;quot;CLASSPATH&amp;quot; EXCEPTION TO THE GPL&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Certain source files distributed by Oracle America and/or its affiliates are&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;subject to the following clarification and special exception to the GPL, but&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;only where Oracle has expressly included in the particular source file&apos;s header&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;the words &amp;quot;Oracle designates this particular file as subject to the &amp;quot;Classpath&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:8pt;&quot;&gt;exception as provided by Oracle in the LICENSE file that accompanied this code.&amp;quot;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; Linking this library statically or dynamically with other modules is making&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; a combined work based on this library. Thus, the terms and conditions of&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; the GNU General Public License cover the whole combination.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; As a special exception, the copyright holders of this library give you&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; permission to link this library with independent modules to produce an&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; executable, regardless of the license terms of these independent modules,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; and to copy and distribute the resulting executable under terms of your&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; choice, provided that you also meet, for each linked independent module,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; the terms and conditions of the license of that module. An independent&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; module is a module which is not derived from or based on this library. If&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; you modify this library, you may extend this exception to your version of&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; the library, but you are not obligated to do so. If you do not wish to do&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; so, delete this exception statement from your version.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:&apos;Bitstream Vera Sans&apos;; font-size:18pt; font-weight:600;&quot;&gt;Quazip&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Copyright (C) 2005-2011 Sergey A. Tachenov&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;This program is free software; you can redistribute it and/or modify it&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;under the terms of the GNU Lesser General Public License as published by&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;the Free Software Foundation; either version 2 of the License, or (at&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;your option) any later version.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;This program is distributed in the hope that it will be useful, but&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;WITHOUT ANY WARRANTY; without even the implied warranty of&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;General Public License for more details.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;You should have received a copy of the GNU Lesser General Public 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-size:8pt;&quot;&gt;along with this program; if not, write to the Free Software Foundation,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;See COPYING file for the full LGPL text.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Original ZIP package is copyrighted by Gilles Vollant, see&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;quazip/(un)zip.h files for details, basically it&apos;s zlib 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-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:&apos;Bitstream Vera Sans&apos;; font-size:18pt; font-weight:600;&quot;&gt;xz-minidec&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;/*&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * XZ decompressor&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; *&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Authors: Lasse Collin &amp;lt;lasse.collin@tukaani.org&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Igor Pavlov &amp;lt;http://7-zip.org/&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; *&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * This file has been put into the public domain.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * You can do whatever you want with this file.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; */&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;DejaVu Sans Mono&apos;; font-size:7.8pt; 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:&apos;Bitstream Vera Sans&apos;; font-size:18pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Copyright 2012-2014 MultiMC Contributors&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;);&lt;/span&gt;&lt;/p&gt;
+&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;you may not use this file except in compliance with the 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-size:10pt;&quot;&gt;You may obtain a copy of the License at&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;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Redistribution and use in source and binary forms, with or without modification,&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;are permitted provided that the following conditions are met:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt; http://www.apache.org/licenses/LICENSE-2.0&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;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;* Redistributions of source code must retain the above copyright notice, this&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt; list of conditions and the following disclaimer.&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;* Redistributions in binary form must reproduce the above copyright notice, this&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt; list of conditions and the following disclaimer in the documentation and/or other&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; materials provided with the distribution.&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;* The name of the contributors may not be used to endorse or promote products&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt; derived from this software without specific prior written permission.&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;Unless required by applicable law or agreed to in writing, software&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;distributed under the License is distributed on an &amp;quot;AS IS&amp;quot; BASIS,&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;WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;See the License for the specific language governing permissions and&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;limitations under the 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-size:10pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.&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;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,&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;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,&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;BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,&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;DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF&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;LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE&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;OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED&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;OF THE POSSIBILITY OF SUCH DAMAGE.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
- <translation></translation>
+&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:&apos;Bitstream Vera Sans&apos;; font-size:18pt; font-weight:600;&quot;&gt;QSLog&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Copyright (c) 2010, Razvan Petru&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;All rights reserved.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Redistribution and use in source and binary forms, with or without modification,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;are permitted provided that the following conditions are met:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;* Redistributions of source code must retain the above copyright notice, this&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; list of conditions and the following disclaimer.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;* Redistributions in binary form must reproduce the above copyright notice, this&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; list of conditions and the following disclaimer in the documentation and/or other&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; materials provided with the distribution.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;* The name of the contributors may not be used to endorse or promote products&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; derived from this software without specific prior written permission.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;OF THE POSSIBILITY OF SUCH DAMAGE.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p 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:&apos;Bitstream Vera Sans&apos;; font-size:18pt; font-weight:600;&quot;&gt;Group View (instance view)&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; /*&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Copyright (C) 2007 Rafael Fernández López &amp;lt;ereslibre@kde.org&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Copyright (C) 2007 John Tapsell &amp;lt;tapsell@kde.org&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; *&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * This library is free software; you can redistribute it and/or&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * modify it under the terms of the GNU Library General Public&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * License as published by the Free Software Foundation; either&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * version 2 of the License, or (at your option) any later version.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; *&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * This library is distributed in the hope that it will be useful,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Library General Public License for more details.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; *&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * You should have received a copy of the GNU Library General Public 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-size:8pt;&quot;&gt; * along with this library; see the file COPYING.LIB. If not, write 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:8pt;&quot;&gt; * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Boston, MA 02110-1301, USA.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; */&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:&apos;Bitstream Vera Sans&apos;; font-size:18pt; font-weight:600;&quot;&gt;Pack200&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;The GNU General Public License (GPL)&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Version 2, June 1991&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;+ &amp;quot;CLASSPATH&amp;quot; EXCEPTION TO THE GPL&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Certain source files distributed by Oracle America and/or its affiliates are&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;subject to the following clarification and special exception to the GPL, but&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;only where Oracle has expressly included in the particular source file&apos;s header&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;the words &amp;quot;Oracle designates this particular file as subject to the &amp;quot;Classpath&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:8pt;&quot;&gt;exception as provided by Oracle in the LICENSE file that accompanied this code.&amp;quot;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; Linking this library statically or dynamically with other modules is making&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; a combined work based on this library. Thus, the terms and conditions of&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; the GNU General Public License cover the whole combination.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; As a special exception, the copyright holders of this library give you&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; permission to link this library with independent modules to produce an&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; executable, regardless of the license terms of these independent modules,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; and to copy and distribute the resulting executable under terms of your&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; choice, provided that you also meet, for each linked independent module,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; the terms and conditions of the license of that module. An independent&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; module is a module which is not derived from or based on this library. If&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; you modify this library, you may extend this exception to your version of&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; the library, but you are not obligated to do so. If you do not wish to do&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; so, delete this exception statement from your version.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:&apos;Bitstream Vera Sans&apos;; font-size:18pt; font-weight:600;&quot;&gt;Quazip&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Copyright (C) 2005-2011 Sergey A. Tachenov&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;This program is free software; you can redistribute it and/or modify it&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;under the terms of the GNU Lesser General Public License as published by&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;the Free Software Foundation; either version 2 of the License, or (at&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;your option) any later version.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;This program is distributed in the hope that it will be useful, but&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;WITHOUT ANY WARRANTY; without even the implied warranty of&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;General Public License for more details.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;You should have received a copy of the GNU Lesser General Public 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-size:8pt;&quot;&gt;along with this program; if not, write to the Free Software Foundation,&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;See COPYING file for the full LGPL text.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Original ZIP package is copyrighted by Gilles Vollant, see&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;quazip/(un)zip.h files for details, basically it&apos;s zlib 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-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:&apos;Bitstream Vera Sans&apos;; font-size:18pt; font-weight:600;&quot;&gt;xz-minidec&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;/*&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * XZ decompressor&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; *&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Authors: Lasse Collin &amp;lt;lasse.collin@tukaani.org&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Igor Pavlov &amp;lt;http://7-zip.org/&amp;gt;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; *&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * This file has been put into the public domain.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * You can do whatever you want with this file.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; */&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+ <message>
+ <location line="+140"/>
+ <source>Forking/Redistribution</source>
+ <translation>Abspaltung/Weiterverbreitung</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:7.8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:&apos;Bitstream Vera Sans&apos;; font-size:11pt;&quot;&gt;We keep MultiMC open source because we think it&apos;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:&apos;Bitstream Vera Sans&apos;; 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:&apos;Bitstream Vera Sans&apos;; font-size:11pt;&quot;&gt;Part of the reason for using the Apache license is we don&apos;t want people using the &amp;quot;MultiMC&amp;quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &amp;quot;MultiMC&amp;quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:&apos;Bitstream Vera Sans&apos;; 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:&apos;Bitstream Vera Sans&apos;; font-size:11pt;&quot;&gt;The Apache license covers reasonable use for the name - a mention of the project&apos;s origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork &lt;/span&gt;&lt;span style=&quot; font-family:&apos;Bitstream Vera Sans&apos;; font-size:11pt; font-weight:600;&quot;&gt;without&lt;/span&gt;&lt;span style=&quot; font-family:&apos;Bitstream Vera Sans&apos;; font-size:11pt;&quot;&gt; implying that you have our blessing.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:7.8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:&apos;Bitstream Vera Sans&apos;; font-size:11pt;&quot;&gt;Wir wollen das MultiMC open source bleibt da wir glauben das es wichtig ist den Quellcode einem Projekt wie diesem einzusehen. Daher verbreiten wir MultiMC unter der Apache Licens&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:&apos;Bitstream Vera Sans&apos;; 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:&apos;Bitstream Vera Sans&apos;; font-size:11pt;&quot;&gt;Eine der grunde das wir die Apache Licens gewählt haben ist das wir nicht wollen das der &amp;quot;MultiMC&amp;quot; name benutzt wird beim weiterverbreiten. Dies bedeutet das leute sich die zeit nehmen mussen den code durchzugehen und alle referencen zu &amp;quot;MultiMC&amp;quot;, inkludirend aber nicht begrenzt zu dem &amp;quot;MultiMC&amp;quot; Logo und den titeln in Fenstern (kein *MultiMC-fork* im titel)&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:&apos;Bitstream Vera Sans&apos;; 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:&apos;Bitstream Vera Sans&apos;; font-size:11pt;&quot;&gt;Die Apache Licens gibt ihnen ein angemessenes recht den namen zu benutzen - eine bemerkung im Über dialog und in der Licens is akzeptabel. Es sollte aber klar sein das das Projekt eine abspaltung ist &lt;/span&gt;&lt;span style=&quot; font-family:&apos;Bitstream Vera Sans&apos;; font-size:11pt; font-weight:600;&quot;&gt;ohne&lt;/span&gt;&lt;span style=&quot; font-family:&apos;Bitstream Vera Sans&apos;; font-size:11pt;&quot;&gt; unserem Segen&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://github.com/Forkk/MultiMC5&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://github.com/Forkk/MultiMC5&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="obsolete">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://github.com/Forkk/MultiMC5&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://github.com/Forkk/MultiMC5&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
- <location filename="../gui/aboutdialog.ui" line="167"/>
+ <location line="-219"/>
<source>Credits</source>
<translation>Dank an</translation>
</message>
@@ -112,7 +388,7 @@ p, li { white-space: pre-wrap; }
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Deutsche Übersetzung: Kilobyte &amp;lt;&lt;a href=&quot;mailto:stiepen22@gmx.de&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;stiepen22@gmx.de&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
- <location filename="../gui/aboutdialog.ui" line="209"/>
+ <location line="+53"/>
<source>License</source>
<translation>Lizenz</translation>
</message>
@@ -201,83 +477,289 @@ p, li { white-space: pre-wrap; }
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;POSSIBILITY OF SUCH DAMAGE.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
- <location filename="../gui/aboutdialog.ui" line="278"/>
+ <location line="+193"/>
<source>About Qt</source>
<translation>Über Qt</translation>
</message>
<message>
- <location filename="../gui/aboutdialog.ui" line="298"/>
+ <location line="+20"/>
<source>Close</source>
<translation>Schließen</translation>
</message>
</context>
<context>
+ <name>AccountListDialog</name>
+ <message>
+ <location filename="../gui/dialogs/AccountListDialog.ui" line="+14"/>
+ <source>Manage Accounts</source>
+ <translation>Konto verwaltung</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Welcome! If you&apos;re new here, you can click the &amp;quot;Add&amp;quot; button to add your Mojang or Minecraft account.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Willkommen! Sollten Sie neu sein können Sie &amp;quot;Hinzufügen&amp;quot; drucken um ihr Mojang oder Minecraft Konto hinzuzufügen&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+ <message>
+ <location line="+17"/>
+ <source>&amp;Add</source>
+ <translation>&amp;Hinzufügen</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>&amp;Remove</source>
+ <translation>&amp;Entfernen</translation>
+ </message>
+ <message>
+ <location line="+20"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set the currently selected account as the active account. The active account is the account that is used to log in (unless it is overridden in an instance-specific setting).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Mache das ausgewählten Konto zum voreingestellten Konto. Das voreingestellte Konto ist das Konto das zum Einloggen benutzt wird (es sei denn es wird von einer Instanz-spezifischen Einstellung überschrieben).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>&amp;Set Default</source>
+ <translation>&amp;Benutze als voreinstellung</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Set no default account. This will cause MultiMC to prompt you to select an account every time you launch an instance that doesn&apos;t have its own default set.</source>
+ <translation>Mache die Voreinstellung rückgängig. Wenn kein Konto voreingestellt ist wird MultiMC dich beim jedem Start einer Instanz fragen, welches Konto benutzt werden soll, es sei denn die Instans hat ein Instanz-spezifisches Konto eingeställt.</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>&amp;No Default</source>
+ <translation>&amp;Keine Voreinstellung</translation>
+ </message>
+ <message>
+ <location filename="../gui/dialogs/AccountListDialog.cpp" line="+71"/>
+ <source>Please enter your Mojang or Minecraft account username and password to add your account.</source>
+ <translation>Bitte gib Benutzernamen und Passwort deines Mojang- oder Minecraft-Kontos an um es hinzuzufügen.</translation>
+ </message>
+ <message>
+ <location line="+84"/>
+ <source>Login error.</source>
+ <translation>Loginfehler.</translation>
+ </message>
+</context>
+<context>
+ <name>AccountSelectDialog</name>
+ <message>
+ <location filename="../gui/dialogs/AccountSelectDialog.ui" line="+14"/>
+ <source>Select an Account</source>
+ <translation>Wähle ein Konto</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Select an account.</source>
+ <translation>Wähle ein konto.</translation>
+ </message>
+ <message>
+ <location line="+12"/>
+ <source>Use as default?</source>
+ <translation>Als Voreinstellung benutzen?</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Use as default for this instance only?</source>
+ <translation>Nur für diese Instanz als Voreinstellung benutzen?</translation>
+ </message>
+</context>
+<context>
+ <name>AssetsMigrateTask</name>
+ <message>
+ <location filename="../logic/assets/AssetsMigrateTask.cpp" line="+19"/>
+ <source>Migrating legacy assets...</source>
+ <translation>Migriere bestehende Daten...</translation>
+ </message>
+</context>
+<context>
+ <name>AuthenticateTask</name>
+ <message>
+ <location filename="../logic/auth/flows/AuthenticateTask.cpp" line="+197"/>
+ <source>Authenticating: Sending request...</source>
+ <translation>Authentifizierung: Sende Anfrage...</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Authenticating: Processing response...</source>
+ <translation>Authentifizierung: Bearbeite Antwort...</translation>
+ </message>
+</context>
+<context>
<name>ConsoleWindow</name>
<message>
- <location filename="../gui/consolewindow.ui" line="14"/>
+ <location filename="../gui/ConsoleWindow.ui" line="+14"/>
<source>MultiMC Console</source>
<translation>MultiMC-Konsole</translation>
</message>
<message>
- <location filename="../gui/consolewindow.ui" line="68"/>
+ <location line="+34"/>
+ <source>Upload Log</source>
+ <translation>Log hochladen</translation>
+ </message>
+ <message>
+ <location line="+20"/>
+ <source>&amp;Kill Minecraft</source>
+ <translation>&amp;Minecraft Killen</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>&amp;Close</source>
+ <translation>&amp;Schließen</translation>
+ </message>
+ <message>
<source>Kill Minecraft</source>
- <translation>Minecraft Killen</translation>
+ <translation type="vanished">Minecraft Killen</translation>
</message>
<message>
- <location filename="../gui/consolewindow.ui" line="75"/>
<source>Close</source>
- <translation>Schließen</translation>
+ <translation type="vanished">Schließen</translation>
</message>
<message>
- <location filename="../gui/consolewindow.cpp" line="93"/>
+ <location filename="../gui/ConsoleWindow.cpp" line="+161"/>
<source>Kill Minecraft?</source>
- <extracomment>Main question of the kill confirmation dialog</extracomment>
<translation>Minecraft Killen?</translation>
</message>
<message>
- <location filename="../gui/consolewindow.cpp" line="94"/>
+ <location line="+1"/>
<source>This can cause the instance to get corrupted and should only be used if Minecraft is frozen for some reason</source>
<translation>Dies kann diese Instanz beschädigen und sollte daher nur genutzt werden, wenn Minecraft eingefroren ist</translation>
</message>
</context>
<context>
+ <name>CopyInstanceDialog</name>
+ <message>
+ <location filename="../gui/dialogs/CopyInstanceDialog.ui" line="+17"/>
+ <source>Copy Instance</source>
+ <translation>Kopiere Instanz</translation>
+ </message>
+ <message>
+ <location line="+57"/>
+ <source>Name</source>
+ <translation>Name</translation>
+ </message>
+</context>
+<context>
+ <name>DownloadUpdateTask</name>
+ <message>
+ <location filename="../logic/updater/DownloadUpdateTask.cpp" line="+80"/>
+ <source>Finding information about the current version...</source>
+ <translation>Finde Informationen zur benutzten Version...</translation>
+ </message>
+ <message>
+ <location line="+21"/>
+ <source>Loading version information...</source>
+ <translation>Lade Versionsinformationen...</translation>
+ </message>
+ <message>
+ <location line="+50"/>
+ <source>Failed to download version info files.</source>
+ <translation>Laden der Versionsdateien ist fehlgeschlagen.</translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Reading file list for new version...</source>
+ <translation>Bearbeite die Dateiliste der neuen Version...</translation>
+ </message>
+ <message>
+ <location line="+15"/>
+ <source>Reading file list for current version...</source>
+ <translation>Bearbeite die Dateilsite der benutzten Version...</translation>
+ </message>
+ <message>
+ <location line="+90"/>
+ <source>Failed to process update lists...</source>
+ <translation>Fehler beim Bearbeiten der Updateliste...</translation>
+ </message>
+ <message>
+ <location line="+12"/>
+ <source>Downloading %1 update files.</source>
+ <translation>%1 Dateien werden heruntergeladen.</translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Processing file lists - figuring out how to install the update...</source>
+ <translation>Bearbete Dateilisten - Rechne aus, wie das Update installiert werden soll...</translation>
+ </message>
+ <message>
+ <location line="+206"/>
+ <source>Failed to write update script file.</source>
+ <translation>Fehler beim Schreiben des Updatescripts.</translation>
+ </message>
+ <message>
+ <location line="+43"/>
+ <source>Failed to download update files.</source>
+ <translation>Fehler beim Herunterladen der Updatedateien.</translation>
+ </message>
+</context>
+<context>
+ <name>EditAccountDialog</name>
+ <message>
+ <location filename="../gui/dialogs/EditAccountDialog.ui" line="+14"/>
+ <source>Edit Account</source>
+ <translation>Bearbeite Konto</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Message label placeholder.</source>
+ <translation>Message label placeholder.</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Email / Username</source>
+ <translation>Email / Benutzername</translation>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Password</source>
+ <translation>Passwort</translation>
+ </message>
+</context>
+<context>
<name>EditNotesDialog</name>
<message>
- <location filename="../gui/EditNotesDialog.ui" line="14"/>
+ <location filename="../gui/dialogs/EditNotesDialog.ui" line="+14"/>
<source>Edit Notes</source>
<translation>Notizen bearbeiten</translation>
</message>
<message>
- <location filename="../gui/EditNotesDialog.cpp" line="15"/>
+ <location filename="../gui/dialogs/EditNotesDialog.cpp" line="+30"/>
<source>Edit notes of %1</source>
<translation>Notizen von %1 bearbeiten</translation>
</message>
</context>
<context>
+ <name>ForgeListLoadTask</name>
+ <message>
+ <location filename="../logic/lists/ForgeVersionList.cpp" line="+161"/>
+ <source>Fetching Forge version lists...</source>
+ <translation>Lade die Forge-Versionslisten...</translation>
+ </message>
+</context>
+<context>
<name>IconPickerDialog</name>
<message>
- <location filename="../gui/IconPickerDialog.ui" line="14"/>
+ <location filename="../gui/dialogs/IconPickerDialog.ui" line="+14"/>
<source>Pick icon</source>
<translation>Symbol auswählen</translation>
</message>
<message>
- <location filename="../gui/IconPickerDialog.cpp" line="44"/>
+ <location filename="../gui/dialogs/IconPickerDialog.cpp" line="+64"/>
<source>Add Icon</source>
<translation>Symbol hinzufügen</translation>
</message>
<message>
- <location filename="../gui/IconPickerDialog.cpp" line="45"/>
+ <location line="+2"/>
<source>Remove Icon</source>
<translation>Symbol entfernen</translation>
</message>
<message>
- <location filename="../gui/IconPickerDialog.cpp" line="91"/>
+ <location line="+37"/>
<source>Select Icons</source>
<extracomment>The title of the select icons open file dialog</extracomment>
<translation>Symbol auswählen</translation>
</message>
<message>
- <location filename="../gui/IconPickerDialog.cpp" line="93"/>
+ <location line="+3"/>
<source>Icons</source>
<extracomment>The type of icon files</extracomment>
<translation>Symbole</translation>
@@ -286,140 +768,190 @@ p, li { white-space: pre-wrap; }
<context>
<name>InstanceSettings</name>
<message>
- <location filename="../gui/instancesettings.ui" line="27"/>
+ <location filename="../gui/dialogs/InstanceSettings.ui" line="+14"/>
+ <source>Instance Settings</source>
+ <translation>Instanzeinstellungen</translation>
+ </message>
+ <message>
+ <location line="+13"/>
<source>Minecraft</source>
<translation></translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="36"/>
+ <location line="+9"/>
<source>Window Size</source>
<translation>Fenstergröße</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="48"/>
+ <location line="+12"/>
<source>Start Minecraft maximized?</source>
<translation>Minecraft maximiert starten?</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="57"/>
+ <location line="+9"/>
<source>Window height:</source>
<translation>Fensterhöhe:</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="64"/>
+ <location line="+7"/>
<source>Window width:</source>
<translation>Fensterbreite:</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="108"/>
+ <location line="+44"/>
<source>Console Settings</source>
<translation>Konsoleneinstellungen</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="120"/>
+ <location line="+12"/>
<source>Show console while the game is running?</source>
<translation>Konsole anzeigen wenn das Spiel läuft?</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="127"/>
+ <location line="+7"/>
<source>Automatically close console when the game quits?</source>
<translation>Konsole automatisch schließen, nachdem das Spiel beendet wurde?</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="140"/>
+ <location line="+159"/>
+ <source>Browse...</source>
+ <translation>Durchsuchen...</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Auto-detect...</source>
+ <translation>Auto-Erkennung...</translation>
+ </message>
+ <message>
<source>Account Settings</source>
- <translation>Konteneinstellungen</translation>
+ <translation type="vanished">Konteneinstellungen</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="155"/>
<source>Login automatically when an instance icon is double clicked?</source>
- <translation>Automatisch einloggen, wenn das Instanzsymbol doppelt gecklickt wurde?</translation>
+ <translation type="vanished">Automatisch einloggen, wenn das Instanzsymbol doppelt gecklickt wurde?</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="182"/>
+ <location line="-142"/>
<source>Java</source>
<translation>Java</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="191"/>
+ <location line="+9"/>
<source>Memory</source>
<translation>Arbeitsspeicher</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="219"/>
+ <location line="+28"/>
<source>Minimum memory allocation:</source>
<translation>Min. Arbeitspeicher:</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="226"/>
+ <location line="+7"/>
<source>Maximum memory allocation:</source>
<translation>Max. Arbeitspeicher:</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="265"/>
+ <location line="+39"/>
<source>PermGen:</source>
<translation>PermGen:</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="278"/>
+ <location line="+13"/>
<source>Java Settings</source>
<translation>Java-Einstellungen</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="290"/>
+ <location line="+12"/>
+ <source>Test</source>
+ <translation>Teste</translation>
+ </message>
+ <message>
+ <location line="+7"/>
<source>Java path:</source>
<translation>Java-Pfad:</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="300"/>
+ <location line="+7"/>
<source>JVM arguments:</source>
<translation>JVM-Argumente:</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="307"/>
<source>Auto-detect</source>
- <translation>Automatisch erkennen</translation>
+ <translation type="vanished">Automatisch erkennen</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="323"/>
+ <location line="+33"/>
<source>Custom Commands</source>
<translation>Eigene Befehle</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="338"/>
+ <location line="+15"/>
<source>Post-exit command:</source>
<translation>Nach-abschluss-Befehl:</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="345"/>
+ <location line="+7"/>
<source>Pre-launch command:</source>
<translation>Vor-Start-Befehl:</translation>
</message>
<message>
- <location filename="../gui/instancesettings.ui" line="367"/>
+ <location line="+22"/>
<source>Pre-launch command runs before the instance launches and post-exit command runs after it exits. Both will be run in MultiMC&apos;s working directory with INST_ID, INST_DIR, and INST_NAME as environment variables.</source>
<translation>Vor-Start wird ausgeführt, bevor die Instanz startet, Nach-Ende nachdem die Instanz beendet wurde. Beide werden Im ausführungsverzeichnis von MultiMC gestartet. Verfügbare Umgebungsvariablen: INST_ID, INST_DIR, INST_NAME.</translation>
</message>
+ <message>
+ <location filename="../gui/dialogs/InstanceSettings.cpp" line="+195"/>
+ <source>Select a Java version</source>
+ <translation>Wähle eine Java-Version</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Find Java executable</source>
+ <translation>Java-Programm finden</translation>
+ </message>
+ <message>
+ <location line="+26"/>
+ <source>Java test success</source>
+ <translation>Java test erfolgreich abgeschlossen</translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Java test failure</source>
+ <translation>Java test fehlgeschlagen</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>The specified java binary didn&apos;t work. You should use the auto-detect feature, or set the path to the java executable.</source>
+ <translation>Das ausgewählte Java-Programm hat nicht funktioniert. Sie sollten die Auto-Erkennung benutzen, oder den Pfad zum Java-Programm angeben.</translation>
+ </message>
+</context>
+<context>
+ <name>JavaListLoadTask</name>
+ <message>
+ <location filename="../logic/lists/JavaVersionList.cpp" line="+175"/>
+ <source>Detecting Java installations...</source>
+ <translation>Suche nach Java-Installationen...</translation>
+ </message>
</context>
<context>
<name>LWJGLSelectDialog</name>
<message>
- <location filename="../gui/lwjglselectdialog.ui" line="14"/>
- <source>Dialog</source>
- <translation></translation>
+ <location filename="../gui/dialogs/LwjglSelectDialog.ui" line="+14"/>
+ <source>Manage Lwjgl Versions</source>
+ <translation>LWJGL Versionsverwaltung</translation>
</message>
<message>
- <location filename="../gui/lwjglselectdialog.ui" line="20"/>
+ <location line="+6"/>
<source>Status label...</source>
<translation></translation>
</message>
<message>
- <location filename="../gui/lwjglselectdialog.ui" line="32"/>
+ <location line="+12"/>
<source>&amp;Refresh</source>
<translation>Anktualisie&amp;ren</translation>
</message>
<message>
- <location filename="../gui/lwjglselectdialog.cpp" line="59"/>
+ <location filename="../gui/dialogs/LwjglSelectDialog.cpp" line="+61"/>
<source>Loading LWJGL version list...</source>
<translation>Lade LWJGL-Versionsliste...</translation>
</message>
@@ -427,550 +959,788 @@ p, li { white-space: pre-wrap; }
<context>
<name>LegacyModEditDialog</name>
<message>
- <location filename="../gui/LegacyModEditDialog.ui" line="14"/>
- <source>Dialog</source>
- <translation></translation>
+ <location filename="../gui/dialogs/LegacyModEditDialog.ui" line="+14"/>
+ <source>Edit Mods</source>
+ <translation>Mods bearbeiten</translation>
</message>
<message>
- <location filename="../gui/LegacyModEditDialog.ui" line="24"/>
+ <location line="+10"/>
<source>Jar Mods</source>
<translation>Jar-Mods</translation>
</message>
<message>
- <location filename="../gui/LegacyModEditDialog.ui" line="42"/>
- <location filename="../gui/LegacyModEditDialog.ui" line="108"/>
- <location filename="../gui/LegacyModEditDialog.ui" line="163"/>
- <location filename="../gui/LegacyModEditDialog.ui" line="221"/>
+ <location line="+20"/>
+ <location line="+77"/>
+ <location line="+69"/>
+ <location line="+70"/>
<source>&amp;Add</source>
<translation>&amp;Hinzufügen</translation>
</message>
<message>
- <location filename="../gui/LegacyModEditDialog.ui" line="49"/>
- <location filename="../gui/LegacyModEditDialog.ui" line="115"/>
- <location filename="../gui/LegacyModEditDialog.ui" line="170"/>
- <location filename="../gui/LegacyModEditDialog.ui" line="228"/>
+ <location line="-209"/>
+ <location line="+77"/>
+ <location line="+69"/>
+ <location line="+70"/>
<source>&amp;Remove</source>
<translation>&amp;Entfernen</translation>
</message>
<message>
- <location filename="../gui/LegacyModEditDialog.ui" line="56"/>
+ <location line="-209"/>
<source>MCForge</source>
<translation></translation>
</message>
<message>
- <location filename="../gui/LegacyModEditDialog.ui" line="76"/>
+ <location line="+20"/>
<source>Move &amp;Up</source>
<translation>&amp;Nach Oben</translation>
</message>
<message>
- <location filename="../gui/LegacyModEditDialog.ui" line="83"/>
+ <location line="+7"/>
<source>Move &amp;Down</source>
<translation>Nach &amp;Unten</translation>
</message>
<message>
- <location filename="../gui/LegacyModEditDialog.ui" line="93"/>
+ <location line="+19"/>
<source>Core Mods</source>
<translation>Coremods</translation>
</message>
<message>
- <location filename="../gui/LegacyModEditDialog.ui" line="135"/>
- <location filename="../gui/LegacyModEditDialog.ui" line="190"/>
- <location filename="../gui/LegacyModEditDialog.ui" line="248"/>
+ <location line="+44"/>
+ <location line="+69"/>
+ <location line="+70"/>
<source>&amp;View Folder</source>
<translation>&amp;Ordner öffnen</translation>
</message>
<message>
- <location filename="../gui/LegacyModEditDialog.ui" line="145"/>
+ <location line="-117"/>
<source>Loader Mods</source>
<translation>Normale Mods</translation>
</message>
<message>
- <location filename="../gui/LegacyModEditDialog.ui" line="203"/>
+ <location line="+72"/>
<source>Texture Packs</source>
- <translation>Texturenpacks</translation>
+ <translation>Texturenpakete</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.cpp" line="249"/>
- <location filename="../gui/LegacyModEditDialog.cpp" line="246"/>
+ <location filename="../gui/dialogs/OneSixModEditDialog.cpp" line="+303"/>
+ <location filename="../gui/dialogs/LegacyModEditDialog.cpp" line="+258"/>
<source>Select Loader Mods</source>
<extracomment>Title of regular mod selection dialog</extracomment>
<translation>Mods auswählen</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.cpp" line="276"/>
+ <location line="+27"/>
<source>Select Resource Packs</source>
<translation>Resourcenpacks auswählen</translation>
</message>
<message>
- <location filename="../gui/LegacyModEditDialog.cpp" line="188"/>
+ <location filename="../gui/dialogs/LegacyModEditDialog.cpp" line="-58"/>
<source>Select Core Mods</source>
<extracomment>Title of core mod selection dialog</extracomment>
- <translation>Coremodsauswählen</translation>
+ <translation>Coremods auswählen</translation>
</message>
<message>
- <location filename="../gui/LegacyModEditDialog.cpp" line="235"/>
+ <location line="+10"/>
+ <source>Select Forge version</source>
+ <translation>Wähle Forge-Version</translation>
+ </message>
+ <message>
+ <location line="+37"/>
<source>Select Jar Mods</source>
<extracomment>Title of jar mod selection dialog</extracomment>
<translation>Jarmods auswählen</translation>
</message>
<message>
- <location filename="../gui/LegacyModEditDialog.cpp" line="257"/>
+ <location line="+22"/>
<source>Select Texture Packs</source>
<extracomment>Title of texture pack selection dialog</extracomment>
- <translation>Texturenpacks auswählen</translation>
+ <translation>Texturenpakete auswählen</translation>
</message>
</context>
<context>
- <name>LoginDialog</name>
+ <name>LegacyUpdate</name>
<message>
- <location filename="../gui/logindialog.ui" line="14"/>
- <source>Login</source>
- <translation>Einloggen</translation>
+ <location filename="../logic/LegacyUpdate.cpp" line="+79"/>
+ <source>Downloading new LWJGL...</source>
+ <translation>LWJGL wird herruntergeladen...</translation>
</message>
<message>
- <location filename="../gui/logindialog.ui" line="20"/>
- <source>&lt;span style=&quot; color:#ff0000;&quot;&gt;Error&lt;/span&gt;</source>
- <translation></translation>
+ <location line="+68"/>
+ <source>Installing new LWJGL...</source>
+ <translation>Das neue LWJGL wird installiert...</translation>
+ </message>
+ <message>
+ <location line="+76"/>
+ <source>Installing new LWJGL - extracting </source>
+ <translation>Das neue LWJGL wird installiert - entpacken</translation>
+ </message>
+ <message>
+ <location line="+30"/>
+ <source>Checking for jar updates...</source>
+ <translation>Suche nach jar Änderungen...</translation>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Downloading new minecraft.jar ...</source>
+ <translation>Neue minecraft.jar wird herruntergeladen...</translation>
+ </message>
+ <message>
+ <location line="+34"/>
+ <source>Installing mods: Adding </source>
+ <translation>Mod-Installation: Hinzufügen </translation>
+ </message>
+ <message>
+ <location line="+86"/>
+ <source>Installing mods: Backing up minecraft.jar ...</source>
+ <translation>Mod-Installation: Erstellen einer Sicherheitskopie von minecraft.jar...</translation>
+ </message>
+ <message>
+ <location line="+25"/>
+ <source>Installing mods: Opening minecraft.jar ...</source>
+ <translation>Mod-Installation: minecraft.jar wird geöffnet...</translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Installing mods: Adding mod files...</source>
+ <translation>Mod-Installation: Mod-Dateien werden hinzugefügt...</translation>
+ </message>
+</context>
+<context>
+ <name>LoginDialog</name>
+ <message>
+ <source>Login</source>
+ <translation type="vanished">Einloggen</translation>
</message>
<message>
- <location filename="../gui/logindialog.ui" line="29"/>
<source>Username:</source>
- <translation>Nutzername:</translation>
+ <translation type="vanished">Nutzername:</translation>
</message>
<message>
- <location filename="../gui/logindialog.ui" line="43"/>
<source>Password:</source>
- <translation>Passwort:</translation>
+ <translation type="vanished">Passwort:</translation>
</message>
<message>
- <location filename="../gui/logindialog.ui" line="53"/>
<source>Password</source>
- <translation>Passwort</translation>
+ <translation type="vanished">Passwort</translation>
</message>
<message>
- <location filename="../gui/logindialog.ui" line="66"/>
<source>Forget</source>
- <translation>Vergessen</translation>
+ <translation type="vanished">Vergessen</translation>
</message>
<message>
- <location filename="../gui/logindialog.ui" line="83"/>
<source>&amp;Remember Username?</source>
- <translation>&amp;Nutzernamen speichern?</translation>
+ <translation type="vanished">&amp;Nutzernamen speichern?</translation>
</message>
<message>
- <location filename="../gui/logindialog.ui" line="96"/>
<source>R&amp;emember Password?</source>
- <translation>&amp;Passwort speichern?</translation>
+ <translation type="vanished">&amp;Passwort speichern?</translation>
</message>
<message>
- <location filename="../gui/logindialog.cpp" line="28"/>
<source>Offline Once</source>
<extracomment>Use offline mode one time</extracomment>
- <translation>Einmal Offline</translation>
+ <translation type="vanished">Einmal Offline-Modus verwenden</translation>
</message>
<message>
- <location filename="../gui/logindialog.cpp" line="37"/>
<source>Name</source>
<extracomment>The username during login (placeholder)</extracomment>
- <translation>Name</translation>
+ <translation type="vanished">Name</translation>
</message>
</context>
<context>
<name>LoginTask</name>
<message>
- <location filename="../logic/net/LoginTask.cpp" line="41"/>
- <location filename="../logic/net/LoginTask.cpp" line="135"/>
<source>Logging in...</source>
- <translation>Einloggen...</translation>
+ <translation type="vanished">Einloggen...</translation>
</message>
<message>
<source>Failed to parse Minecraft version string.</source>
<translation type="obsolete">Konnte Minecraft-Versionsstring nicht parsen.</translation>
</message>
<message>
- <location filename="../logic/net/LoginTask.cpp" line="124"/>
<source>Invalid username or password.</source>
- <translation>Falsche Kombination von Nutzernamen und Passwort.</translation>
+ <translation type="vanished">Falsche Kombination von Nutzernamen und Passwort.</translation>
</message>
<message>
- <location filename="../logic/net/LoginTask.cpp" line="126"/>
<source>Launcher outdated, please update.</source>
- <translation>Veralteter Launcher, Bitte lade ein Update herunter.</translation>
+ <translation type="vanished">Veralteter Launcher, Bitte lade ein Update herunter.</translation>
</message>
<message>
- <location filename="../logic/net/LoginTask.cpp" line="93"/>
- <location filename="../logic/net/LoginTask.cpp" line="128"/>
- <location filename="../logic/net/LoginTask.cpp" line="205"/>
- <location filename="../logic/net/LoginTask.cpp" line="232"/>
<source>Login failed: %1</source>
- <translation>Login fehlgeschlagen: %1</translation>
+ <translation type="vanished">Login fehlgeschlagen: %1</translation>
</message>
<message>
- <location filename="../logic/net/LoginTask.cpp" line="77"/>
- <location filename="../logic/net/LoginTask.cpp" line="189"/>
<source>The login servers are currently unavailable. Check http://help.mojang.com/ for more info.</source>
- <translation>Derzeit kann auf die Login-Server nicht zugegriffe werden. Für weitere Informationen siehe http://help.mojang.com/.</translation>
+ <translation type="vanished">Derzeit kann auf die Login-Server nicht zugegriffen werden. Für weitere Informationen siehe http://help.mojang.com/.</translation>
</message>
<message>
- <location filename="../logic/net/LoginTask.cpp" line="82"/>
- <location filename="../logic/net/LoginTask.cpp" line="194"/>
<source>Login failed: Unknown HTTP error %1 occurred.</source>
- <translation>Login fehlgeschlagen. Unbekannter HTTP-Fehler: %1.</translation>
+ <translation type="vanished">Login fehlgeschlagen. Unbekannter HTTP-Fehler: %1.</translation>
</message>
<message>
- <location filename="../logic/net/LoginTask.cpp" line="89"/>
- <location filename="../logic/net/LoginTask.cpp" line="201"/>
<source>Login canceled.</source>
- <translation>Login abgebrochen.</translation>
+ <translation type="vanished">Login abgebrochen.</translation>
</message>
+</context>
+<context>
+ <name>MCModInfoFrame</name>
<message>
- <location filename="../logic/net/LoginTask.cpp" line="238"/>
- <source>Login failed: BAD FORMAT #1</source>
- <translatorcomment>Login fehlgeschlagen: UNGÜLTIGES FORMAT #1</translatorcomment>
- <translation></translation>
+ <location filename="../gui/widgets/MCModInfoFrame.ui" line="+26"/>
+ <source>Frame</source>
+ <translation>Frame</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <location filename="../gui/widgets/MCModInfoFrame.cpp" line="+54"/>
+ <source>Select a mod to view title and authors...</source>
+ <translation>Wähle einem Mod aus, um Titel und Autoren zu sehen...</translation>
+ </message>
+ <message>
+ <location line="+19"/>
+ <location filename="../gui/widgets/MCModInfoFrame.cpp" line="+1"/>
+ <source>Select a mod to view description...</source>
+ <translation>Wähle ein Mod um die Beschreibung zu sehen...</translation>
+ </message>
+ <message>
+ <location filename="../gui/widgets/MCModInfoFrame.cpp" line="-11"/>
+ <source>No description provided in mcmod.info</source>
+ <translation>mcmod.info wurde nicht mit einer Beschreibung versehen</translation>
+ </message>
+</context>
+<context>
+ <name>MCVListLoadTask</name>
+ <message>
+ <location filename="../logic/lists/MinecraftVersionList.cpp" line="+142"/>
+ <source>Loading instance version list...</source>
+ <translation>Lade Liste von Minecraft-Versionen...</translation>
</message>
</context>
<context>
<name>MainWindow</name>
<message>
- <location filename="../gui/mainwindow.ui" line="14"/>
+ <location filename="../gui/MainWindow.ui" line="+14"/>
<source>MultiMC 5</source>
<translation>MultiMC 5</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="40"/>
+ <location line="+30"/>
<source>Main Toolbar</source>
<translation>Haupt-Werkzeugleiste</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="80"/>
+ <location line="+41"/>
<source>Instance Toolbar</source>
<translation>Instanz-Werkzeugleiste</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="123"/>
+ <location line="+40"/>
+ <source>News Toolbar</source>
+ <translation>Nachrichten-Werkzeugleiste</translation>
+ </message>
+ <message>
+ <location line="+34"/>
<source>Add Instance</source>
<translation>Instanz hinzufügen</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="126"/>
- <location filename="../gui/mainwindow.ui" line="129"/>
+ <location line="+3"/>
+ <location line="+3"/>
+ <location line="+332"/>
<source>Add a new instance.</source>
<translation>Neue Instanz erstellen.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="138"/>
+ <location line="-323"/>
<source>View Instance Folder</source>
<translation>Instanzordner öffnen</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="141"/>
- <location filename="../gui/mainwindow.ui" line="144"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Open the instance folder in a file browser.</source>
<translation>Instanzordner im Dateimanager öffnen.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="153"/>
+ <location line="+9"/>
<source>Refresh</source>
<translation>Aktualisieren</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="156"/>
- <location filename="../gui/mainwindow.ui" line="159"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Reload the instance list.</source>
<translation>Instanzliste neu Laden.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="168"/>
+ <location line="+9"/>
<source>View Central Mods Folder</source>
- <translation>Zenstralen Modordner öffnen</translation>
+ <translation>Zenstralen Mod-Ordner öffnen</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="171"/>
- <location filename="../gui/mainwindow.ui" line="174"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Open the central mods folder in a file browser.</source>
- <translation>Zentralen Modordner in einem Dateimanager öffnen.</translation>
+ <translation>Zentralen Mod-Ordner in einem Dateimanager öffnen.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="183"/>
+ <location line="+9"/>
<source>Check for Updates</source>
<translation>Auf Updates überprüfen</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="186"/>
- <location filename="../gui/mainwindow.ui" line="189"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Check for new updates for MultiMC</source>
<translation>Auf Updates für MultiMC prüfen</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="198"/>
- <location filename="../gui/mainwindow.ui" line="325"/>
+ <location line="+9"/>
+ <location line="+133"/>
<source>Settings</source>
<translation>Einstellungen</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="201"/>
- <location filename="../gui/mainwindow.ui" line="204"/>
+ <location line="-130"/>
+ <location line="+3"/>
<source>Change settings.</source>
<translation>Einstellungen ändern.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="216"/>
+ <location line="+12"/>
<source>Report a Bug</source>
<translation>Fehler melden</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="219"/>
- <location filename="../gui/mainwindow.ui" line="222"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Open the bug tracker to report a bug with MultiMC.</source>
- <translation>Fehler-Verfolgung öffnen, um einen Fehler zu melden (Bitte auf Englisch ;))</translation>
+ <translation>Fehler-Verfolgung öffnen, um einen Fehler zu melden (Bitte auf Englisch ;)).</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="231"/>
<source>News</source>
- <translation>Neuigkeiten</translation>
+ <translation type="vanished">Neuigkeiten</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="234"/>
- <location filename="../gui/mainwindow.ui" line="237"/>
<source>Open the MultiMC dev blog to read news about MultiMC.</source>
- <translation>Den MultiMC Entwicklerblog öffnen und Neuigkeiten über MultiMC erfahren.</translation>
+ <translation type="vanished">Den MultiMC Entwicklerblog öffnen und Neuigkeiten über MultiMC erfahren.</translation>
+ </message>
+ <message>
+ <location line="+9"/>
+ <source>More News</source>
+ <translation>Mehr Nachrichten</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>More news...</source>
+ <translation>Mehr Nachrichten...</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <location line="+3"/>
+ <source>Open the MultiMC development blog to read more news about MultiMC.</source>
+ <translation>Öffne den MultiMC Entwicklerblog um mehr Nachrichten zu MultiMC zu lesen.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="246"/>
- <location filename="../gui/mainwindow.ui" line="252"/>
+ <location line="+9"/>
+ <location line="+6"/>
<source>About MultiMC</source>
<translation>Über MultiMC</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="249"/>
+ <location line="-3"/>
<source>View information about MultiMC.</source>
<translation>Informationen über MultiMC anzeigen.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="260"/>
+ <location line="+11"/>
<source>Play</source>
<translation>Spielen</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="263"/>
- <location filename="../gui/mainwindow.ui" line="266"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Launch the selected instance.</source>
<translation>Die ausgewählte Instanz starten.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="271"/>
+ <location line="+5"/>
<source>Instance Name</source>
<translation>Instanzname</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="274"/>
- <location filename="../gui/mainwindow.ui" line="277"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Rename the selected instance.</source>
<translation>Ausgewählte Instanz umbenennen.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="282"/>
+ <location line="+5"/>
<source>Change Group</source>
<translation>Gruppe ändern</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="285"/>
- <location filename="../gui/mainwindow.ui" line="288"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Change the selected instance&apos;s group.</source>
<translation>Die Gruppe der ausgewählten Instanz ändern.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="300"/>
+ <location line="+12"/>
<source>Change Icon</source>
<translation>Symbol ändern</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="303"/>
- <location filename="../gui/mainwindow.ui" line="306"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Change the selected instance&apos;s icon.</source>
<translation>Das Symbol der ausgewählten Instanz ändern.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="311"/>
+ <location line="+8"/>
<source>Edit Notes</source>
<translation>Notizen bearbeiten</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="314"/>
- <location filename="../gui/mainwindow.ui" line="317"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Edit the notes for the selected instance.</source>
<translation>Notizen für die ausgewählte Instanz bearbeiten.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="328"/>
- <location filename="../gui/mainwindow.ui" line="331"/>
+ <location line="+11"/>
+ <location line="+3"/>
<source>Change settings for the selected instance.</source>
<translation>Einstellungen für die ausgewählte Instanz bearbeiten.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="339"/>
+ <location line="+8"/>
<source>Make Shortcut</source>
<translation>Verknüpfung erstellen</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="342"/>
- <location filename="../gui/mainwindow.ui" line="345"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Make a shortcut on the desktop for the selected instance.</source>
<translation>Erstellt eine Verknüpfung für die ausgewählte Instanz auf dem Desktop.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="353"/>
+ <location line="+8"/>
<source>Manage Saves</source>
<translation>Speicherstände verwalten</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="356"/>
- <location filename="../gui/mainwindow.ui" line="359"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Manage saves for the selected instance.</source>
<translation>Die Speicherstände der ausgewählten Instanz verwalten.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="364"/>
+ <location line="+5"/>
<source>Edit Mods</source>
<translation>Mods bearbeiten</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="367"/>
- <location filename="../gui/mainwindow.ui" line="370"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Edit the mods for the selected instance.</source>
<translation>Die Mods der ausgewähten Instanz bearbeiten.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="378"/>
+ <location line="+5"/>
<source>Change Version</source>
<translation>Version ändern</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="381"/>
- <location filename="../gui/mainwindow.ui" line="384"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Change the selected instance&apos;s Minecraft version.</source>
<translation>Die Minecraftversion der ausgewählten Instanz ändern.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="392"/>
+ <location line="+8"/>
<source>Change LWJGL</source>
<translation>LWJGL ändern</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="395"/>
- <location filename="../gui/mainwindow.ui" line="398"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Change the version of LWJGL for the selected instance to use.</source>
<translation>Die zu benutzende Version von LWJGL für die aktuelle Instanz ändern.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="403"/>
+ <location line="+5"/>
<source>Instance Folder</source>
<translation>Instanzordner</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="406"/>
- <location filename="../gui/mainwindow.ui" line="409"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Open the selected instance&apos;s root folder in a file browser.</source>
<translation>Den Wurzelordner der Aktuellen Instanz im Dateimanager öffnen.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="414"/>
+ <location line="+5"/>
<source>Delete</source>
<translation>Löschen</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="417"/>
- <location filename="../gui/mainwindow.ui" line="420"/>
+ <location line="+3"/>
+ <location line="+3"/>
<source>Delete the selected instance.</source>
<translation>Ausgewählte Instanz löschen.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="425"/>
+ <location line="+5"/>
<source>Config Folder</source>
- <translation>Konfig-ordner</translation>
+ <translation>Konfig-Ordner</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="428"/>
+ <location line="+3"/>
<source>Open the instance&apos;s config folder</source>
<translation>Den Konfigurationsordner im Dateimanager anzeigen</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="440"/>
+ <location line="+12"/>
<source>Meow</source>
<translation>Miau</translation>
</message>
<message>
- <location filename="../gui/mainwindow.ui" line="443"/>
+ <location line="+3"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; color:#ff0004;&quot;&gt;Catnarok!&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;Or just a cat with a ball of yarn?&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;WHO KNOWS?!&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;:/icons/instances/tnt&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
+ <location line="+9"/>
+ <source>Copy Instance</source>
+ <translation>Kopiere Instanz</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Copy the selected instance.</source>
+ <translation>Kopiere die ausgewählte Instanz.</translation>
+ </message>
+ <message>
+ <location line="+8"/>
+ <location filename="../gui/MainWindow.cpp" line="+201"/>
+ <source>Manage Accounts</source>
+ <translation>Verwalte Konten</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Manage your Mojang or Minecraft accounts.</source>
+ <translation>Verwalte diene Mojang- und Minecraft -onten.</translation>
+ </message>
+ <message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; color:#ff0004;&quot;&gt;Catnatok!&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;Or just a cat with a ball of yarn?&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;WHO KNOWS?!&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;:/icons/instances/tnt&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="obsolete">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; color:#ff0004;&quot;&gt;Catnatok!&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;Or just a cat with a ball of yarn?&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;WHO KNOWS?!&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;:/icons/instances/tnt&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
- <location filename="../gui/mainwindow.cpp" line="313"/>
+ <location filename="../gui/MainWindow.cpp" line="-9"/>
+ <source>No instance selected</source>
+ <translation>Keine Instanz ausgewählt</translation>
+ </message>
+ <message>
+ <location line="+17"/>
+ <source>Accounts</source>
+ <translation>Konten</translation>
+ </message>
+ <message>
+ <location line="+67"/>
+ <source>No update found.</source>
+ <translation>Keine neue Version gefunden.</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>No MultiMC update was found!
+You are using the latest version.</source>
+ <translation>Kein update zu MultiMC konnte gefunden werden!
+Sie benutzen die neuste Version.</translation>
+ </message>
+ <message>
+ <location line="+52"/>
+ <source>No accounts added!</source>
+ <translation>Keine Konten angegeben!</translation>
+ </message>
+ <message>
+ <location line="+37"/>
+ <source>No Default Account</source>
+ <translation>Kein voreingestelltes Konto</translation>
+ </message>
+ <message>
+ <location line="+95"/>
+ <source>Loading news...</source>
+ <translation>Nachrichten werden geladen...</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>No news available.</source>
+ <translation>Keine Nachrichten zugänglich.</translation>
+ </message>
+ <message>
+ <location line="+105"/>
+ <location line="+7"/>
+ <location line="+7"/>
+ <location line="+12"/>
+ <location line="+8"/>
+ <location line="+37"/>
+ <location line="+7"/>
+ <location line="+7"/>
+ <location line="+436"/>
+ <source>Error</source>
+ <translation>Fehler</translation>
+ </message>
+ <message>
+ <location line="-486"/>
+ <location line="+487"/>
+ <source>MultiMC cannot download Minecraft or update instances unless you have at least one account added.
+Please add your Mojang or Minecraft account.</source>
+ <translation>MultiMC kann Minecraft nicht herrunterladen und keine Instanzen aktualisieren so lange Sie nicht mindestens ein Konto angegeben haben.
+Bitte fügen Sie Ihr Mojang oder Minecraft Konto hinzu.</translation>
+ </message>
+ <message>
+ <location line="-390"/>
<source>Group name</source>
<translation>Gruppenname</translation>
</message>
<message>
- <location filename="../gui/mainwindow.cpp" line="313"/>
+ <location line="+0"/>
<source>Enter a new group name.</source>
<translation>Neuen Gruppennamen eingeben.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.cpp" line="398"/>
+ <location line="+91"/>
+ <source>CAREFUL</source>
+ <translation>ACHTUNG</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>This is permanent! Are you sure?
+About to delete: </source>
+ <translation>Dies ist permanent! Sind sie sich sicher?
+Die folgende Instanz löschen:</translation>
+ </message>
+ <message>
+ <location line="+17"/>
<source>Instance name</source>
<translation>Instanzname</translation>
</message>
<message>
- <location filename="../gui/mainwindow.cpp" line="398"/>
+ <location line="+0"/>
<source>Enter a new instance name.</source>
<translation>Neuen Instanznamen eingeben.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.cpp" line="580"/>
+ <location line="+89"/>
+ <source>No Accounts</source>
+ <translation>Keine Konten</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>In order to play Minecraft, you must have at least one Mojang or Minecraft account logged in to MultiMC.Would you like to open the account manager to add an account now?</source>
+ <translation>Damit sie Minecraft spielen können mussen sie mindestens ein Mojang- oder Minecraft-Konto in MultiMC hinterlegen. Wollen sie die Konto Verwaltung öffen um ein Konto hinzuzufügen?</translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Which account would you like to use?</source>
+ <translation>Wälches Konto wollen Sie benutzen?</translation>
+ </message>
+ <message>
+ <location line="+17"/>
+ <source>Your account is currently not logged in. Please enter your password to log in again.</source>
+ <translation>Ihr Konto ist momentan nicht angemeldet. Bitte geben sie ihr passwort an um sich anzumelden.</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Play Offline</source>
+ <translation>Offline spielen</translation>
+ </message>
+ <message>
+ <location line="+90"/>
+ <source>Error updating instance</source>
+ <translation>Fehler beim Aktualisieren der Instanz</translation>
+ </message>
+ <message>
+ <location line="+30"/>
<source>MultiMC Shortcut</source>
<translation>MultiMC-Verknüpfung</translation>
</message>
<message>
- <location filename="../gui/mainwindow.cpp" line="580"/>
+ <location line="+0"/>
<source>Enter a Shortcut Name.</source>
<translation>Verknüpfungsnamen eingeben.</translation>
</message>
<message>
- <location filename="../gui/mainwindow.cpp" line="588"/>
+ <location line="+8"/>
<source>Not useful</source>
<translation>Sinnlos</translation>
</message>
<message>
- <location filename="../gui/mainwindow.cpp" line="589"/>
+ <location line="+1"/>
<source>A Dummy Shortcut was created. it will not do anything productive</source>
<translation>Eine Dummy-Verknüpfung wurde erstellt. Sie wird jedoch absolut nichts bewirken</translation>
</message>
<message>
- <location filename="../gui/mainwindow.cpp" line="665"/>
+ <location line="+16"/>
+ <source>Change Minecraft version</source>
+ <translation>Minecraft-Version ändern</translation>
+ </message>
+ <message>
+ <location line="+18"/>
+ <source>Are you sure?</source>
+ <translation>Sind Sie sicher?</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>This will remove any library/version customization you did previously. This includes things like Forge install and similar.</source>
+ <translation>Dies will sämtliche Bibliotheks/Versions-Anpassung die Sie vorgenommen haben entfernen. Dies schließt Sachen wie Forge mit ein.</translation>
+ </message>
+ <message>
+ <location line="+40"/>
+ <source>Instance settings</source>
+ <translation>Instanzeinstellungen</translation>
+ </message>
+ <message>
+ <location line="+38"/>
<source>Rename Instance</source>
<translation>Instanz umbenennen</translation>
</message>
+ <message>
+ <location line="+77"/>
+ <source>Select a Java version</source>
+ <translation>Wähle eine Java-Version</translation>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Invalid version selected</source>
+ <translation>Ungültige version ausgewählt</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>You didn&apos;t select a valid Java version, so MultiMC will select the default. You can change this in the settings dialog.</source>
+ <translation>Sie haben keine gültige Java-Version ausgewählt, daher wird MultiMC für Sie eine Voreinstellung benutzen. Sie können dies in den Einstellungen ändern.</translation>
+ </message>
</context>
<context>
<name>MinecraftProcess</name>
<message>
- <location filename="../logic/MinecraftProcess.cpp" line="123"/>
+ <location filename="../logic/MinecraftProcess.cpp" line="+139"/>
<source>Minecraft exited with exitcode %1.</source>
<extracomment>Message displayed on instance exit</extracomment>
- <translation>Minecraft wurde mit exitcode %1 beendet.</translation>
+ <translation>Minecraft wurde mit Status %1 beendet.</translation>
</message>
<message>
- <location filename="../logic/MinecraftProcess.cpp" line="126"/>
+ <location line="+5"/>
+ <source>Minecraft crashed with exitcode %1.</source>
+ <extracomment>Message displayed on instance crashed</extracomment>
+ <translation>Minecraft ist mit dem Status %1 abgesturtzt</translation>
+ </message>
+ <message>
+ <location line="+6"/>
<source>Minecraft was killed by user.</source>
<extracomment>Message displayed after the instance exits due to kill request</extracomment>
- <translation>Minecraft wurde durch den nutzer gekillt.</translation>
+ <translation>Minecraft wurde durch den Nutzer gekillt.</translation>
</message>
<message>
- <location filename="../logic/MinecraftProcess.cpp" line="175"/>
+ <location line="+52"/>
<source>Could not launch minecraft!</source>
<extracomment>Error message displayed if instace can&apos;t start</extracomment>
<translation>Konnte Minecraft nicht starten!</translation>
@@ -980,15 +1750,15 @@ p, li { white-space: pre-wrap; }
<name>MultiMC</name>
<message>
<source>display this help and exit.</source>
- <translation type="obsolete">Zeigt diese Hilfe und beended das Programm.</translation>
+ <translation type="obsolete">Zeigt diese Hilfe und beendet das Programm.</translation>
</message>
<message>
<source>display program version and exit.</source>
- <translation type="obsolete">Zeigt die programmversion an und beendet das Programm.</translation>
+ <translation type="obsolete">Zeigt die Programmversion an und beendet das Programm.</translation>
</message>
<message>
<source>use the supplied directory as MultiMC root instead of the binary location (use &apos;.&apos; for current)</source>
- <translation type="obsolete">Benutze das angegebene Verzeichnis als Arbeitsverzeichnis anstelle des speicherorts. (Benutze &apos;.&apos; um das aktuele Verzeichnis zu verwenden)</translation>
+ <translation type="obsolete">Benutze das angegebene Verzeichnis als Arbeitsverzeichnis anstelle des Speicherorts. (Benutze &apos;.&apos; um das aktuele Verzeichnis zu verwenden)</translation>
</message>
<message>
<source>replaces the given file with the running executable</source>
@@ -1030,362 +1800,632 @@ p, li { white-space: pre-wrap; }
<context>
<name>NewInstanceDialog</name>
<message>
- <location filename="../gui/newinstancedialog.ui" line="17"/>
+ <location filename="../gui/dialogs/NewInstanceDialog.ui" line="+17"/>
<source>New Instance</source>
<translation>Neue Instanz</translation>
</message>
<message>
- <location filename="../gui/newinstancedialog.ui" line="74"/>
+ <location line="+57"/>
<source>Name</source>
<translation>Name</translation>
</message>
<message>
- <location filename="../gui/newinstancedialog.ui" line="90"/>
+ <location line="+16"/>
<source>Version:</source>
<translation>Version:</translation>
</message>
<message>
- <location filename="../gui/newinstancedialog.ui" line="104"/>
+ <location line="+14"/>
<source>...</source>
<translation>...</translation>
</message>
+ <message>
+ <location filename="../gui/dialogs/NewInstanceDialog.cpp" line="+99"/>
+ <source>Change Minecraft version</source>
+ <translation>Ändere die Minecraft-Version...</translation>
+ </message>
+</context>
+<context>
+ <name>NewsEntry</name>
+ <message>
+ <location filename="../logic/news/NewsEntry.cpp" line="+24"/>
+ <location line="+36"/>
+ <source>Untitled</source>
+ <translation>Unbennant</translation>
+ </message>
+ <message>
+ <location line="-35"/>
+ <location line="+36"/>
+ <source>No content.</source>
+ <translation>Kein Eintrag.</translation>
+ </message>
+ <message>
+ <location line="-34"/>
+ <location line="+36"/>
+ <source>Unknown Author</source>
+ <translation>Unbekannter Autor</translation>
+ </message>
+</context>
+<context>
+ <name>OneSixFTBInstanceForge</name>
+ <message>
+ <location filename="../logic/OneSixFTBInstance.cpp" line="+37"/>
+ <source>Downloading Forge...</source>
+ <translation>Forge wird heruntergeladen...</translation>
+ </message>
+ <message>
+ <location line="+18"/>
+ <source>Installing Forge...</source>
+ <translation>Forge wird installiert...</translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Couldn&apos;t load the version config</source>
+ <translation>Fehlschlag beim laden der Versions-Konfiguration</translation>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>Couldn&apos;t install Forge</source>
+ <translation>Fehler beim Installieren von Forge</translation>
+ </message>
</context>
<context>
<name>OneSixModEditDialog</name>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="14"/>
<source>Dialog</source>
<translatorcomment>Am i really responsible for this?</translatorcomment>
- <translation>Edit Mods</translation>
+ <translation type="vanished">Edit Mods</translation>
</message>
<message>
<source>Library</source>
<translation type="obsolete">Bibliothek</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="158"/>
+ <location filename="../gui/dialogs/OneSixModEditDialog.ui" line="+179"/>
<source>Loader Mods</source>
<translation>Mods</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="122"/>
- <location filename="../gui/OneSixModEditDialog.ui" line="176"/>
- <location filename="../gui/OneSixModEditDialog.ui" line="231"/>
+ <location line="-50"/>
+ <location line="+80"/>
+ <location line="+67"/>
<source>&amp;Add</source>
<translation>&amp;Hinzufügen</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="33"/>
+ <location line="-262"/>
+ <source>Manage Mods</source>
+ <translation>Verwalte Mods</translation>
+ </message>
+ <message>
+ <location line="+19"/>
<source>Version</source>
<translation>Version</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="53"/>
+ <location line="+20"/>
<source>Main Class:</source>
<translation>Hauptklasse:</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="73"/>
+ <location line="+20"/>
<source>Replace any current custom version with Minecraft Forge</source>
<translation>Die aktuelle benutzerdefinierte Version mit Minecraft Forge ersetzen</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="76"/>
+ <location line="+3"/>
<source>Install Forge</source>
<translation>Forge Installieren</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="83"/>
+ <location line="+7"/>
+ <source>Install LiteLoader</source>
+ <translation>Installiere LiteLoader</translation>
+ </message>
+ <message>
+ <location line="+7"/>
<source>Create an customized copy of the base version</source>
<translation>Eine modifizierbare Kopie der Version erstellen</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="86"/>
+ <location line="+3"/>
<source>Customize</source>
<translation>Benutzerdefiniert</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="96"/>
+ <location line="+10"/>
<source>Revert to original base version</source>
<translation>Benutzerdefinierte Einstellungen zurücksetzen</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="99"/>
+ <location line="+3"/>
<source>Revert</source>
<translation>Zurücksetzen</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="119"/>
+ <location line="+20"/>
<source>Add new libraries</source>
<translation></translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="132"/>
+ <location line="+13"/>
<source>Remove selected libraries</source>
<translation></translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="135"/>
- <location filename="../gui/OneSixModEditDialog.ui" line="183"/>
- <location filename="../gui/OneSixModEditDialog.ui" line="238"/>
+ <location line="+3"/>
+ <location line="+74"/>
+ <location line="+67"/>
<source>&amp;Remove</source>
<translation>&amp;Entfernen</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="203"/>
- <location filename="../gui/OneSixModEditDialog.ui" line="258"/>
+ <location line="-127"/>
+ <source>Open custom.json</source>
+ <translation>Öffne custom.json</translation>
+ </message>
+ <message>
+ <location line="+80"/>
+ <location line="+67"/>
<source>&amp;View Folder</source>
<translation>&amp;Ordner öffnen</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.ui" line="213"/>
+ <location line="-45"/>
<source>Resource Packs</source>
<translation>Resourcenpacks</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.cpp" line="108"/>
- <location filename="../gui/OneSixModEditDialog.cpp" line="131"/>
+ <location filename="../gui/dialogs/OneSixModEditDialog.cpp" line="-205"/>
+ <location line="+34"/>
<source>Revert?</source>
<translation>Zurücksetzen?</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.cpp" line="108"/>
+ <location line="-34"/>
<source>Do you want to revert the version of this instance to its original configuration?</source>
<translation>Möchtest du wirklich die Version dieser Instanz zurücksetzen?</translation>
</message>
<message>
- <location filename="../gui/OneSixModEditDialog.cpp" line="132"/>
+ <location line="+20"/>
+ <source>Error</source>
+ <translation>Fehler</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Unable to open custom.json, check the settings</source>
+ <translation>Fehler beim Öffnen der custom.json Datei, überprüfen Sie Ihre Einstellungen</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Select Forge version</source>
+ <translation>Wähle Forge-Version</translation>
+ </message>
+ <message>
+ <location line="+8"/>
<source>This will revert any changes you did to the version up to this point. Is that OK?</source>
<translation>Dies wird alle Änderungen, die du vorgenommen hast zurücksetzen. Bist du damit einverstanden?</translation>
</message>
+ <message>
+ <location line="+69"/>
+ <location line="+15"/>
+ <source>LiteLoader</source>
+ <translation>LiteLoader</translation>
+ </message>
+ <message>
+ <location line="-14"/>
+ <source>There is no information available on how to install LiteLoader into this version of Minecraft</source>
+ <translation>Es gibt momentan keine Informationen zur Installation von LiteLoader für diese Version von Minecraft</translation>
+ </message>
+ <message>
+ <location line="+15"/>
+ <source>For reasons unknown, the LiteLoader installation failed. Check your MultiMC log files for details.</source>
+ <translation>Aus unbekannten Gründen ist die Installation von LiteLoader fehlgeschlagen. Schauen sie sich Ihre MultiMC Logdateien an, um weitere Details zu erhalten.</translation>
+ </message>
+</context>
+<context>
+ <name>OneSixUpdate</name>
+ <message>
+ <location filename="../logic/OneSixUpdate.cpp" line="+60"/>
+ <location line="+32"/>
+ <source>Testing the Java installation...</source>
+ <translation>Java-Installation wird getestet...</translation>
+ </message>
+ <message>
+ <location line="+39"/>
+ <source>Getting the version files from Mojang...</source>
+ <translation>Versionsdateien von Mojang werden herruntergeladen...</translation>
+ </message>
+ <message>
+ <location line="+68"/>
+ <source>Updating assets index...</source>
+ <translation>Datenindex wird aktualisiert...</translation>
+ </message>
+ <message>
+ <location line="+51"/>
+ <source>Getting the assets files from Mojang...</source>
+ <translation>Daten werden von Mojang geholt...</translation>
+ </message>
+ <message>
+ <location line="+34"/>
+ <source>Getting the library files from Mojang...</source>
+ <translation>Bibliotheken werden von Mojang geholt...</translation>
+ </message>
+ <message>
+ <location line="+88"/>
+ <source>Preparing for launch...</source>
+ <translation>Der Start wird vorbereitet...</translation>
+ </message>
</context>
<context>
<name>ProgressDialog</name>
<message>
- <location filename="../gui/ProgressDialog.ui" line="26"/>
+ <location filename="../gui/dialogs/ProgressDialog.ui" line="+26"/>
<source>Please wait...</source>
<translation>Bitte warten...</translation>
</message>
<message>
- <location filename="../gui/ProgressDialog.ui" line="32"/>
+ <location line="+6"/>
<source>Task Status...</source>
<translation>Aufgabenstatus...</translation>
</message>
+ <message>
+ <location line="+26"/>
+ <source>Skip</source>
+ <translation>Überspringen</translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <location filename="../logic/NagUtils.cpp" line="+26"/>
+ <source>JVM arguments warning</source>
+ <translation>JVM argument verwarnung</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>You tried to manually set a JVM memory option (using &quot;-XX:PermSize&quot;, &quot;-Xmx&quot; or &quot;-Xms&quot;) - there are dedicated boxes for these in the settings (Java tab, in the Memory group at the top).
+Your manual settings will be overridden by the dedicated options.
+This message will be displayed until you remove them from the JVM arguments.</source>
+ <translation>Sie haben versucht manuel eine JVM Speicher option anzugeben (&quot;-XX:PermSize&quot;, &quot;-Xmx&quot; oder &quot;-Xms&quot;) - es gibt hierfür gewidmete boxen in den einstellung (Java tab, in der Speicher gruppe am anfang).
+Ihre manuellen einstellungen werden von den gewidmeten überschrieben werden.
+Diese Mitteilung wird angezeigt werden bis Sie sie von den JVM argumenten entfernt haben.</translation>
+ </message>
+ <message>
+ <location filename="../gui/dialogs/ModEditDialogCommon.cpp" line="+53"/>
+ <source>How sad!</source>
+ <translation>Wie schade!</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>The mod author didn&apos;t provide a website link for this mod.</source>
+ <translation>Der Autor des mods hat keine link zu einer webseite angegeben.</translation>
+ </message>
+</context>
+<context>
+ <name>RefreshTask</name>
+ <message>
+ <location filename="../logic/auth/flows/RefreshTask.cpp" line="+148"/>
+ <source>Refreshing login token...</source>
+ <translation>Auffrischung des Login-Tokens...</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Refreshing login token: Processing response...</source>
+ <translation>Auffrischung des Login-Tokens: Verarbeite Antwort...</translation>
+ </message>
</context>
<context>
<name>SettingsDialog</name>
<message>
- <location filename="../gui/settingsdialog.ui" line="20"/>
+ <location filename="../gui/dialogs/SettingsDialog.ui" line="+20"/>
<source>Settings</source>
<translation>Einstellungen</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="40"/>
+ <location line="+20"/>
<source>General</source>
- <translation>Generell</translation>
+ <translation>Allgemein</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="49"/>
+ <location line="+9"/>
<source>Sorting Mode</source>
<translation>Sortiermodus</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="55"/>
+ <location line="+6"/>
<source>By last launched</source>
<translation>Nach letzem Start</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="65"/>
+ <location line="+10"/>
<source>By name</source>
<translation>Nach Namen</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="78"/>
+ <location line="+13"/>
<source>Update Settings</source>
<translation>Updateeinstellungen</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="84"/>
+ <location line="+6"/>
<source>Use development builds?</source>
<translation>Entwicklerversionen benutzen?</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="91"/>
+ <location line="+7"/>
<source>Check for updates when MultiMC starts?</source>
<translation>Beim Start nach Updates suchen?</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="101"/>
+ <location line="+97"/>
<source>Folders</source>
<translation>Ordner</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="107"/>
+ <location line="+6"/>
<source>Instances:</source>
<translation>Instanzen:</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="117"/>
- <location filename="../gui/settingsdialog.ui" line="134"/>
- <location filename="../gui/settingsdialog.ui" line="151"/>
+ <location line="-69"/>
+ <location line="+46"/>
+ <location line="+33"/>
+ <location line="+20"/>
+ <location line="+14"/>
+ <location line="+17"/>
+ <location line="+26"/>
+ <location line="+289"/>
<source>...</source>
<translation>...</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="124"/>
+ <location line="-469"/>
+ <source>FTB</source>
+ <translation>FTB</translation>
+ </message>
+ <message>
+ <location line="+31"/>
+ <source>Launcher:</source>
+ <translation>Launcher:</translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Track FTB instances</source>
+ <translation>FTB-Instanzen beobachten</translation>
+ </message>
+ <message>
+ <location line="+32"/>
+ <source>Files:</source>
+ <translation>Dateien:</translation>
+ </message>
+ <message>
+ <location line="+33"/>
<source>Mods:</source>
<translation>Mods:</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="141"/>
+ <location line="+20"/>
<source>LWJGL:</source>
<translation>LWJGL:</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="175"/>
+ <location line="+17"/>
+ <source>Icons:</source>
+ <translation>Symbole:</translation>
+ </message>
+ <message>
+ <location line="+17"/>
+ <source>External Editors (leave empty for system default)</source>
+ <translation>Externe Editor-Anwendungen (leer lassen, um die System-Voreinstellung zu benutzen)</translation>
+ </message>
+ <message>
+ <location line="+9"/>
+ <source>JSON Editor:</source>
+ <translation>JSON Editor:</translation>
+ </message>
+ <message>
+ <location line="+31"/>
<source>Minecraft</source>
<translation>Minecraft</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="181"/>
+ <location line="+6"/>
<source>Window Size</source>
<translation>Fenstergröße</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="187"/>
+ <location line="+6"/>
<source>Start Minecraft maximized?</source>
<translation>Minecraft maximiert starten?</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="196"/>
+ <location line="+9"/>
<source>Window height:</source>
<translation>Fensterhöhe:</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="203"/>
+ <location line="+7"/>
<source>Window width:</source>
<translation>Fensterbreite:</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="244"/>
+ <location line="+41"/>
<source>Console Settings</source>
<translation>Konsoleneinstellungen</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="250"/>
+ <location line="+6"/>
<source>Show console while the game is running?</source>
<translation>Konsole anzeigen wenn das Spiel läuft?</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="257"/>
+ <location line="+7"/>
<source>Automatically close console when the game quits?</source>
<translation>Konsole automatisch schließen, nachdem das Spiel beendet wurde?</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="267"/>
<source>Login automatically when an instance icon is double clicked?</source>
- <translation>Automatisch einloggen, wenn das Instanzsymbol doppelt gecklickt wurde?</translation>
+ <translation type="vanished">Automatisch einloggen, wenn das Instanzsymbol doppelt geklickt wurde?</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="288"/>
+ <location line="+24"/>
<source>Java</source>
<translation>Java</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="294"/>
+ <location line="+6"/>
<source>Memory</source>
<translation>Arbeitsspeicher</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="316"/>
+ <location line="+22"/>
<source>Minimum memory allocation:</source>
<translation>Min. Arbeitspeicher:</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="323"/>
+ <location line="+7"/>
<source>Maximum memory allocation:</source>
<translation>Max. Arbeitspeicher:</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="346"/>
+ <location line="+23"/>
<source>PermGen:</source>
<translation>PermGen:</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="372"/>
+ <location line="+26"/>
<source>Java Settings</source>
<translation>Java-Einstellungen</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="378"/>
+ <location line="+12"/>
<source>Java path:</source>
<translation>Java-Pfad:</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="385"/>
+ <location line="+13"/>
+ <source>Auto-detect...</source>
+ <translation>Auto-Erkennung:</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Test</source>
+ <translation>Test</translation>
+ </message>
+ <message>
+ <location line="+13"/>
<source>JVM arguments:</source>
<translation>JVM-Argumente:</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="398"/>
<source>Browse...</source>
- <translation>Durchsuchen...</translation>
+ <translation type="vanished">Durchsuchen...</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="417"/>
<source>Auto-detect</source>
- <translation>Automatisch erkennen</translation>
+ <translation type="vanished">Automatisch erkennen</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="427"/>
+ <location line="+39"/>
<source>Custom Commands</source>
<translation>Eigene Befehle</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="433"/>
+ <location line="+6"/>
<source>Post-exit command:</source>
<translation>Nach-abschluss-Befehl:</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="440"/>
+ <location line="+7"/>
<source>Pre-launch command:</source>
<translation>Vor-Start-Befehl:</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.ui" line="462"/>
+ <location line="+22"/>
<source>Pre-launch command runs before the instance launches and post-exit command runs after it exits. Both will be run in MultiMC&apos;s working directory with INST_ID, INST_DIR, and INST_NAME as environment variables.</source>
<translation>Vor-Start wird ausgeführt, bevor die Instanz startet, Nach-Ende nachdem die Instanz beendet wurde. Beide werden Im ausführungsverzeichnis von MultiMC gestartet. Verfügbare Umgebungsvariablen: INST_ID, INST_DIR, INST_NAME.</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.cpp" line="53"/>
+ <location filename="../gui/dialogs/SettingsDialog.cpp" line="+77"/>
+ <source>FTB Launcher Directory</source>
+ <translation>FTB-Launcher-Ordner</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>FTB Directory</source>
+ <translation>FTB-Ordner</translation>
+ </message>
+ <message>
+ <location line="+13"/>
<source>Instance Directory</source>
<translation>Instanz-Ordner</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.cpp" line="61"/>
+ <location line="+12"/>
+ <source>Icons Directory</source>
+ <translation>Symbolordner</translation>
+ </message>
+ <message>
+ <location line="+13"/>
<source>Mods Directory</source>
<translation>Modordner</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.cpp" line="69"/>
+ <location line="+13"/>
<source>LWJGL Directory</source>
<translation>LWJGL-Ordner</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.cpp" line="103"/>
+ <location line="+14"/>
+ <source>JSON Editor</source>
+ <translation>JSON Editor</translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Invalid</source>
+ <translation>Ungültig</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>The file chosen does not seem to be an executable</source>
+ <translation>Die ausgesuchte Datei scheint keine Anwendung zu sein</translation>
+ </message>
+ <message>
+ <location line="+34"/>
<source>Development builds</source>
<translation>Entwicklerversionen</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.cpp" line="104"/>
+ <location line="+1"/>
<source>Development builds contain experimental features and may be unstable. Are you sure you want to enable them?</source>
- <translation>Entwicklerversionen enthalten experimentelle Features und können instabil sein. Möchtest du sie dennoch aktivieren?</translation>
+ <translation>Entwicklerversionen enthalten experimentelle Features und können instabil sein. Möchtest du Sie dennoch aktivieren?</translation>
+ </message>
+ <message>
+ <location line="+132"/>
+ <source>Select a Java version</source>
+ <translation>Wähle Java version</translation>
</message>
<message>
- <location filename="../gui/settingsdialog.cpp" line="195"/>
+ <location line="+13"/>
<source>Find Java executable</source>
<translatorcomment>Umm... this translation is a bit meh</translatorcomment>
- <translation type="unfinished">Java-Anwendung finden</translation>
+ <translation>Java-Anwendung finden</translation>
+ </message>
+ <message>
+ <location line="+27"/>
+ <source>Java test success</source>
+ <translation>Java test erfolgreich abgeschlossen</translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Java test failure</source>
+ <translation>Java test fehlgeschlagen</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>The specified java binary didn&apos;t work. You should use the auto-detect feature, or set the path to the java executable.</source>
+ <translation>Das ausgewählte Java-Program hat nicht funktioniert. Sie sollten die Auto-Erkennung benutzen, oder den Pfad zum Java-Programm angeben.</translation>
</message>
</context>
<context>
@@ -1400,11 +2440,51 @@ p, li { white-space: pre-wrap; }
</message>
</context>
<context>
+ <name>UpdateDialog</name>
+ <message>
+ <location filename="../gui/dialogs/UpdateDialog.ui" line="+14"/>
+ <source>MultiMC Update</source>
+ <translation>Neue MultiMC Version</translation>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>A new MultiMC update is available!</source>
+ <translation>Eine Neue Version von MultiMC ist jetzt verfügbar!</translation>
+ </message>
+ <message>
+ <location line="+16"/>
+ <source>Update now</source>
+ <translation>Jetzt herunterladen</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Update after MultiMC closes</source>
+ <translation>Herunterladen wenn MultiMC geschlossen wird</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Don&apos;t update yet</source>
+ <translation>Noch nicht herrunterladen</translation>
+ </message>
+</context>
+<context>
+ <name>ValidateTask</name>
+ <message>
+ <location filename="../logic/auth/flows/ValidateTask.cpp" line="+58"/>
+ <source>Validating access token: Sending request...</source>
+ <translation>Validiere Zugriffstoken: Sende Anfrage...</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Validating access token: Processing response...</source>
+ <translation>Validiere Zugriffstoken: Bearbeite Antwort...</translation>
+ </message>
+</context>
+<context>
<name>VersionSelectDialog</name>
<message>
- <location filename="../gui/versionselectdialog.ui" line="14"/>
<source>Dialog</source>
- <translation>Dialog</translation>
+ <translation type="vanished">Dialog</translation>
</message>
<message>
<source>Show &amp;snapshots?</source>
@@ -1412,17 +2492,65 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<source>Show &amp;Nostalgia?</source>
- <translation type="obsolete">&apos;&amp;Nostalgia&apos;-Versionen anzeigen?</translation>
+ <translation type="obsolete">&apos;&amp;Nostalgie&apos;-Versionen anzeigen?</translation>
+ </message>
+ <message>
+ <location filename="../gui/dialogs/VersionSelectDialog.ui" line="+14"/>
+ <source>Choose Version</source>
+ <translation>Wähle Version</translation>
</message>
<message>
- <location filename="../gui/versionselectdialog.ui" line="47"/>
+ <location line="+33"/>
<source>Reloads the version list.</source>
<translation>Instanzliste aktualisieren.</translation>
</message>
<message>
- <location filename="../gui/versionselectdialog.ui" line="50"/>
+ <location line="+3"/>
<source>&amp;Refresh</source>
<translation>&amp;Aktualisieren</translation>
</message>
</context>
+<context>
+ <name>YggdrasilTask</name>
+ <message>
+ <location filename="../logic/auth/YggdrasilTask.cpp" line="+98"/>
+ <source>&lt;b&gt;SSL Handshake failed.&lt;/b&gt;&lt;br/&gt;There might be a few causes for it:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;You use Windows XP and need to &lt;a href=&quot;http://www.microsoft.com/en-us/download/details.aspx?id=38918&quot;&gt;update your root certificates&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Some device on your network is interfering with SSL traffic. In that case, you have bigger worries than Minecraft not starting.&lt;/li&gt;&lt;li&gt;Possibly something else. Check the MultiMC log file for details&lt;/li&gt;&lt;/ul&gt;</source>
+ <translation>&lt;b&gt;SSL-Handshake fehlgeschlagen.&lt;/b&gt;&lt;br/&gt;Es kann mehrere Erklärungen geben:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;Sie benutzen Windows XP und mussen &lt;a href=&quot;http://www.microsoft.com/en-us/download/details.aspx?id=38918&quot;&gt;Ihr root certifikat aktualisieren&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Irgend ein gerät in Ihrem Netzwerk mischt sich in den SSL verkehr mit ein. In diesem fall haben sie grössere probleme alls das Minecraft nicht starten kann.&lt;/li&gt;&lt;li&gt;Möglicherweise irgendetwas anderes. Sehen sie in der MultiMC log Datei nach um weitere Details zu finden&lt;/li&gt;&lt;/ul&gt;</translation>
+ </message>
+ <message>
+ <location line="+47"/>
+ <source>An unknown error occurred when processing the response from the authentication server.</source>
+ <translation>Ein unbekannter Fehler ist beim Bearbeiten der Antwort des Authentifizierungs-Servers aufgetreten.</translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Failed to parse Yggdrasil JSON response: %1 at offset %2.</source>
+ <translation>Fehler beim Bearbeiten der Yggdrasil-JSON-Antwort: %1 bei %2.</translation>
+ </message>
+ <message>
+ <location line="+26"/>
+ <source>An unknown error occurred when trying to communicate with the authentication server: %1</source>
+ <translation>Ein unbekannter Fehler ist aufgetreten bei der Kommunikation mit den Authentifizierungs-Server: %1</translation>
+ </message>
+ <message>
+ <location line="+20"/>
+ <source>An unknown Yggdrasil error occurred.</source>
+ <translation>Ein unbekannter Yggdrasil-Fehler ist aufgetreten.</translation>
+ </message>
+ <message>
+ <location line="+9"/>
+ <source>Sending request to auth servers...</source>
+ <translation>Sende Anfrage an die Authentifizierungs-Server...</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Processing response from servers...</source>
+ <translation>Bearbeite Antwort des Authentifizierungs-Servers...</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Processing. Please wait...</source>
+ <translation>Bearbeite. Bitte warten...</translation>
+ </message>
+</context>
</TS>