summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt32
-rw-r--r--MultiMC.cpp5
-rw-r--r--cmake/UseJava.cmake (renamed from depends/launcher/UseJava.cmake)0
-rw-r--r--cmake/UseJavaClassFilelist.cmake (renamed from depends/launcher/UseJavaClassFilelist.cmake)0
-rw-r--r--cmake/UseJavaSymlinks.cmake (renamed from depends/launcher/UseJavaSymlinks.cmake)0
-rw-r--r--depends/javacheck/CMakeLists.txt14
-rw-r--r--depends/javacheck/JavaCheck.java14
-rw-r--r--depends/launcher/CMakeLists.txt6
-rw-r--r--generated.qrc.in6
-rw-r--r--graphics.qrc (renamed from multimc.qrc)3
-rw-r--r--gui/ConsoleWindow.cpp83
-rw-r--r--gui/ConsoleWindow.h20
-rw-r--r--gui/ConsoleWindow.ui151
-rw-r--r--gui/MainWindow.cpp43
-rw-r--r--gui/MainWindow.h3
-rw-r--r--gui/dialogs/AboutDialog.ui166
-rw-r--r--gui/dialogs/CopyInstanceDialog.ui6
-rw-r--r--gui/dialogs/LoginDialog.ui4
-rw-r--r--gui/dialogs/NewInstanceDialog.ui6
-rw-r--r--gui/dialogs/SettingsDialog.cpp40
-rw-r--r--gui/dialogs/SettingsDialog.h13
-rw-r--r--gui/dialogs/SettingsDialog.ui41
-rw-r--r--logic/BaseInstance.h4
-rw-r--r--logic/BaseUpdate.cpp26
-rw-r--r--logic/BaseUpdate.h47
-rw-r--r--logic/InstanceLauncher.cpp9
-rw-r--r--logic/JavaChecker.cpp89
-rw-r--r--logic/JavaChecker.h32
-rw-r--r--logic/JavaUtils.h1
-rw-r--r--logic/LegacyInstance.cpp57
-rw-r--r--logic/LegacyInstance.h4
-rw-r--r--logic/LegacyUpdate.cpp2
-rw-r--r--logic/LegacyUpdate.h4
-rw-r--r--logic/MinecraftProcess.cpp44
-rw-r--r--logic/MinecraftProcess.h26
-rw-r--r--logic/OneSixAssets.cpp6
-rw-r--r--logic/OneSixInstance.cpp16
-rw-r--r--logic/OneSixInstance.h5
-rw-r--r--logic/OneSixRule.h1
-rw-r--r--logic/OneSixUpdate.cpp46
-rw-r--r--logic/OneSixUpdate.h4
-rw-r--r--logic/OneSixVersion.cpp2
-rw-r--r--logic/auth/MojangAccount.cpp4
-rw-r--r--logic/auth/MojangAccount.h7
-rw-r--r--logic/lists/BaseVersionList.h1
-rw-r--r--logic/lists/ForgeVersionList.h1
-rw-r--r--logic/lists/InstanceList.h1
-rw-r--r--logic/lists/JavaVersionList.h1
-rw-r--r--logic/lists/MinecraftVersionList.h1
-rw-r--r--logic/net/CacheDownload.cpp6
-rw-r--r--logic/net/CacheDownload.h2
-rw-r--r--logic/net/FileDownload.cpp4
-rw-r--r--logic/net/FileDownload.h2
-rw-r--r--logic/net/ForgeMirror.h10
-rw-r--r--logic/net/ForgeMirrors.cpp116
-rw-r--r--logic/net/ForgeMirrors.h58
-rw-r--r--logic/net/ForgeXzDownload.cpp100
-rw-r--r--logic/net/ForgeXzDownload.h19
-rw-r--r--logic/net/HttpMetaCache.h1
-rw-r--r--logic/net/LoginTask.cpp15
-rw-r--r--logic/net/LoginTask.h15
-rw-r--r--logic/net/NetJob.cpp1
-rw-r--r--logic/net/NetJob.h10
-rwxr-xr-xpackage/linux/MultiMC12
64 files changed, 1001 insertions, 467 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 343f6ac8..1bb3126b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,6 +12,11 @@ SET(CMAKE_AUTOMOC ON)
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
SET(FILES_TO_TRANSLATE )
+######## Set module path ########
+SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
+SET(MMC_SRC "${PROJECT_SOURCE_DIR}")
+SET(MMC_BIN "${PROJECT_BINARY_DIR}")
+
# Output all executables and shared libs in the main build folder, not in subfolders.
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
@@ -49,8 +54,9 @@ include_directories(${Qt5Widgets_INCLUDE_DIRS})
add_subdirectory(depends/quazip)
include_directories(depends/quazip)
-# Add the java launcher
+# Add the java launcher and checker
add_subdirectory(depends/launcher)
+add_subdirectory(depends/javacheck)
# Add xz decompression
add_subdirectory(depends/xz-embedded)
@@ -84,10 +90,6 @@ IF(${BIGENDIAN})
ENDIF(${BIGENDIAN})
-######## Set module path ########
-SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}")
-
-
######## Set version numbers ########
SET(MultiMC_VERSION_MAJOR 5)
SET(MultiMC_VERSION_MINOR 0)
@@ -233,8 +235,6 @@ logic/BaseVersion.h
logic/MinecraftVersion.h
logic/InstanceFactory.h
logic/InstanceFactory.cpp
-logic/BaseUpdate.h
-logic/BaseUpdate.cpp
logic/BaseInstance.h
logic/BaseInstance.cpp
logic/BaseInstance_p.h
@@ -258,6 +258,8 @@ logic/net/ByteArrayDownload.h
logic/net/ByteArrayDownload.cpp
logic/net/CacheDownload.h
logic/net/CacheDownload.cpp
+logic/net/ForgeMirrors.h
+logic/net/ForgeMirrors.cpp
logic/net/ForgeXzDownload.h
logic/net/ForgeXzDownload.cpp
logic/net/NetJob.h
@@ -338,6 +340,8 @@ logic/tasks/Task.h
logic/tasks/Task.cpp
# Utilities
+logic/JavaChecker.h
+logic/JavaChecker.cpp
logic/JavaUtils.h
logic/JavaUtils.cpp
logic/NagUtils.h
@@ -408,20 +412,24 @@ IF(WIN32)
ENDIF(WIN32)
# Tell CMake that MultiMCLauncher.jar is generated.
-SET_SOURCE_FILES_PROPERTIES(resources/MultiMCLauncher.jar GENERATED)
+SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/depends/launcher/MultiMCLauncher.jar GENERATED)
+SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/depends/javacheck/JavaCheck.jar GENERATED)
# Qt 5 stuff
QT5_WRAP_UI(MULTIMC_UI ${MULTIMC_UIS})
-QT5_ADD_RESOURCES(MULTIMC_QRC multimc.qrc)
+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 executable
ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32
- ${MULTIMC_SOURCES} ${MULTIMC_UI} ${MULTIMC_QRC} ${MULTIMC_RCS})
+ ${MULTIMC_SOURCES} ${MULTIMC_UI} ${GRAPHICS_QRC} ${GENERATED_QRC} ${MULTIMC_RCS})
# Link
TARGET_LINK_LIBRARIES(MultiMC xz-embedded unpack200 quazip libUtil libSettings libGroupView ${MultiMC_LINK_ADDITIONAL_LIBS})
QT5_USE_MODULES(MultiMC Core Widgets Network Xml ${MultiMC_QT_ADDITIONAL_MODULES})
-ADD_DEPENDENCIES(MultiMC MultiMCLauncher)
+ADD_DEPENDENCIES(MultiMC MultiMCLauncher JavaCheck)
option(BUILD_KEYRING_TEST "Build the simple keyring test binary" OFF)
IF(BUILD_KEYRING_TEST)
@@ -579,3 +587,5 @@ endif (UPDATE_TRANSLATIONS)
add_custom_target (translations DEPENDS ${QM_FILES})
install(FILES ${QM_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/translations)
+
+
diff --git a/MultiMC.cpp b/MultiMC.cpp
index 9179f0e0..17981755 100644
--- a/MultiMC.cpp
+++ b/MultiMC.cpp
@@ -328,8 +328,6 @@ void MultiMC::initGlobalSettings()
// The cat
m_settings->registerSetting(new Setting("TheCat", false));
- // Shall the main window hide on instance launch
- m_settings->registerSetting(new Setting("NoHide", false));
m_settings->registerSetting(new Setting("InstSortMode", "Name"));
@@ -345,6 +343,9 @@ void MultiMC::initGlobalSettings()
// Window state and geometry
m_settings->registerSetting(new Setting("MainWindowState", ""));
m_settings->registerSetting(new Setting("MainWindowGeometry", ""));
+
+ m_settings->registerSetting(new Setting("ConsoleWindowState", ""));
+ m_settings->registerSetting(new Setting("ConsoleWindowGeometry", ""));
}
void MultiMC::initHttpMetaCache()
diff --git a/depends/launcher/UseJava.cmake b/cmake/UseJava.cmake
index 1a5ef107..1a5ef107 100644
--- a/depends/launcher/UseJava.cmake
+++ b/cmake/UseJava.cmake
diff --git a/depends/launcher/UseJavaClassFilelist.cmake b/cmake/UseJavaClassFilelist.cmake
index c842bf71..c842bf71 100644
--- a/depends/launcher/UseJavaClassFilelist.cmake
+++ b/cmake/UseJavaClassFilelist.cmake
diff --git a/depends/launcher/UseJavaSymlinks.cmake b/cmake/UseJavaSymlinks.cmake
index c66ee1ea..c66ee1ea 100644
--- a/depends/launcher/UseJavaSymlinks.cmake
+++ b/cmake/UseJavaSymlinks.cmake
diff --git a/depends/javacheck/CMakeLists.txt b/depends/javacheck/CMakeLists.txt
new file mode 100644
index 00000000..e72c9552
--- /dev/null
+++ b/depends/javacheck/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 2.8.6)
+project(launcher Java)
+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
diff --git a/depends/javacheck/JavaCheck.java b/depends/javacheck/JavaCheck.java
new file mode 100644
index 00000000..73688082
--- /dev/null
+++ b/depends/javacheck/JavaCheck.java
@@ -0,0 +1,14 @@
+import java.lang.Integer;
+
+public class JavaCheck
+{
+ private static final String key = "os.arch";
+ public static void main (String [] args)
+ {
+ String property = System.getProperty(key);
+ System.out.println(key + "=" + property);
+ if (property != null)
+ System.exit(0);
+ System.exit(1);
+ }
+}
diff --git a/depends/launcher/CMakeLists.txt b/depends/launcher/CMakeLists.txt
index e5402ce7..e91d5bd6 100644
--- a/depends/launcher/CMakeLists.txt
+++ b/depends/launcher/CMakeLists.txt
@@ -1,13 +1,11 @@
cmake_minimum_required(VERSION 2.8.6)
project(launcher Java)
-set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}")
find_package(Java 1.6 REQUIRED COMPONENTS Development)
-
include(UseJava)
set(CMAKE_JAVA_JAR_ENTRY_POINT MultiMCLauncher)
set(CMAKE_JAVA_COMPILE_FLAGS -target 1.6 -source 1.6 -Xlint:deprecation -Xlint:unchecked)
-set(CMAKE_JAVA_TARGET_OUTPUT_DIR "${PROJECT_SOURCE_DIR}/../../resources")
+#set(CMAKE_JAVA_TARGET_OUTPUT_DIR "${PROJECT_SOURCE_DIR}/../../resources")
set(SRC
MultiMCLauncher.java
@@ -20,4 +18,4 @@ set(SRC
MCFrame.java
)
-add_jar(MultiMCLauncher ${SRC}) \ No newline at end of file
+add_jar(MultiMCLauncher ${SRC})
diff --git a/generated.qrc.in b/generated.qrc.in
new file mode 100644
index 00000000..82f4db99
--- /dev/null
+++ b/generated.qrc.in
@@ -0,0 +1,6 @@
+<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/multimc.qrc b/graphics.qrc
index 86f50b80..fe8892fe 100644
--- a/multimc.qrc
+++ b/graphics.qrc
@@ -40,9 +40,6 @@
<file alias="stone">resources/icons/instances/stone.png</file>
<file alias="tnt">resources/icons/instances/tnt.png</file>
</qresource>
- <qresource prefix="/launcher">
- <file alias="launcher.jar">resources/MultiMCLauncher.jar</file>
- </qresource>
<qresource prefix="/icons/multimc">
<file alias="scalable/apps/multimc.svg">resources/icons/multimc.svg</file>
<file alias="index.theme">resources/XdgIcon.theme</file>
diff --git a/gui/ConsoleWindow.cpp b/gui/ConsoleWindow.cpp
index ec25b9cf..d8a1b69d 100644
--- a/gui/ConsoleWindow.cpp
+++ b/gui/ConsoleWindow.cpp
@@ -15,6 +15,7 @@
#include "ConsoleWindow.h"
#include "ui_ConsoleWindow.h"
+#include "MultiMC.h"
#include <QScrollBar>
#include <QMessageBox>
@@ -22,16 +23,27 @@
#include <gui/Platform.h>
#include <gui/dialogs/CustomMessageBox.h>
-ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent) :
- QDialog(parent),
- ui(new Ui::ConsoleWindow),
- m_mayclose(true),
- proc(mcproc)
+ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent)
+ : QMainWindow(parent), ui(new Ui::ConsoleWindow), proc(mcproc)
{
MultiMCPlatform::fixWM_CLASS(this);
ui->setupUi(this);
- this->setWindowFlags(Qt::Window);
- connect(mcproc, SIGNAL(ended(BaseInstance*)), this, SLOT(onEnded(BaseInstance*)));
+ connect(mcproc, SIGNAL(log(QString, MessageLevel::Enum)), this,
+ 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,
+ SLOT(onEnded(BaseInstance *, int, QProcess::ExitStatus)));
+ 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()));
+
+ if (mcproc->instance()->settings().get("ShowConsole").toBool())
+ {
+ show();
+ }
}
ConsoleWindow::~ConsoleWindow()
@@ -54,32 +66,32 @@ void ConsoleWindow::writeColor(QString text, const char *color)
void ConsoleWindow::write(QString data, MessageLevel::Enum mode)
{
if (data.endsWith('\n'))
- data = data.left(data.length()-1);
+ data = data.left(data.length() - 1);
QStringList paragraphs = data.split('\n');
- for(QString &paragraph : paragraphs)
+ for (QString &paragraph : paragraphs)
{
paragraph = paragraph.trimmed();
}
QListIterator<QString> iter(paragraphs);
if (mode == MessageLevel::MultiMC)
- while(iter.hasNext())
+ while (iter.hasNext())
writeColor(iter.next(), "blue");
else if (mode == MessageLevel::Error)
- while(iter.hasNext())
+ while (iter.hasNext())
writeColor(iter.next(), "red");
else if (mode == MessageLevel::Warning)
- while(iter.hasNext())
+ while (iter.hasNext())
writeColor(iter.next(), "orange");
else if (mode == MessageLevel::Fatal)
- while(iter.hasNext())
+ while (iter.hasNext())
writeColor(iter.next(), "pink");
else if (mode == MessageLevel::Debug)
- while(iter.hasNext())
+ while (iter.hasNext())
writeColor(iter.next(), "green");
// TODO: implement other MessageLevels
else
- while(iter.hasNext())
+ while (iter.hasNext())
writeColor(iter.next());
}
@@ -102,34 +114,53 @@ void ConsoleWindow::setMayClose(bool mayclose)
ui->closeButton->setEnabled(false);
}
-void ConsoleWindow::closeEvent(QCloseEvent * event)
+void ConsoleWindow::closeEvent(QCloseEvent *event)
{
- if(!m_mayclose)
+ if (!m_mayclose)
event->ignore();
else
- QDialog::closeEvent(event);
+ {
+ MMC->settings()->set("ConsoleWindowState", saveState().toBase64());
+ MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
+
+ emit isClosing();
+ QMainWindow::closeEvent(event);
+ }
}
void ConsoleWindow::on_btnKillMinecraft_clicked()
{
ui->btnKillMinecraft->setEnabled(false);
- auto response = CustomMessageBox::selectable(this, tr("Kill Minecraft?"),
- tr("This can cause the instance to get corrupted and should only be used if Minecraft is frozen for some reason"),
- QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec();
+ auto response = CustomMessageBox::selectable(
+ this, tr("Kill Minecraft?"),
+ tr("This can cause the instance to get corrupted and should only be used if Minecraft "
+ "is frozen for some reason"),
+ QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec();
if (response == QMessageBox::Yes)
proc->killMinecraft();
else
ui->btnKillMinecraft->setEnabled(true);
}
-void ConsoleWindow::onEnded(BaseInstance *instance)
+void ConsoleWindow::onEnded(BaseInstance *instance, int code, QProcess::ExitStatus status)
{
ui->btnKillMinecraft->setEnabled(false);
- // TODO: Might need an option to forcefully close, even on an error
- if(instance->settings().get("AutoCloseConsole").toBool())
+ if (instance->settings().get("AutoCloseConsole").toBool())
{
- // TODO: Check why this doesn't work
- if (!proc->exitCode()) this->close();
+ if (code == 0 && status != QProcess::CrashExit)
+ {
+ this->close();
+ return;
+ }
}
+ if(!isVisible())
+ show();
+}
+
+void ConsoleWindow::onLaunchFailed(BaseInstance *instance)
+{
+ ui->btnKillMinecraft->setEnabled(false);
+ if(!isVisible())
+ show();
}
diff --git a/gui/ConsoleWindow.h b/gui/ConsoleWindow.h
index 0ed35554..e0a47bc6 100644
--- a/gui/ConsoleWindow.h
+++ b/gui/ConsoleWindow.h
@@ -15,7 +15,7 @@
#pragma once
-#include <QDialog>
+#include <QMainWindow>
#include "logic/MinecraftProcess.h"
namespace Ui
@@ -23,7 +23,7 @@ namespace Ui
class ConsoleWindow;
}
-class ConsoleWindow : public QDialog
+class ConsoleWindow : public QMainWindow
{
Q_OBJECT
@@ -38,6 +38,9 @@ public:
*/
void setMayClose(bool mayclose);
+signals:
+ void isClosing();
+
public
slots:
/**
@@ -66,14 +69,17 @@ private
slots:
void on_closeButton_clicked();
void on_btnKillMinecraft_clicked();
- void onEnded(BaseInstance *instance);
+ void onEnded(BaseInstance *instance, int code, QProcess::ExitStatus status);
+ void onLaunchFailed(BaseInstance *instance);
+
+ // FIXME: add handlers for the other MinecraftProcess signals (pre/post launch command
+ // failures)
protected:
void closeEvent(QCloseEvent *);
private:
- Ui::ConsoleWindow *ui;
- MinecraftProcess *proc;
- bool m_mayclose;
+ Ui::ConsoleWindow *ui = nullptr;
+ MinecraftProcess *proc = nullptr;
+ bool m_mayclose = true;
};
-
diff --git a/gui/ConsoleWindow.ui b/gui/ConsoleWindow.ui
index 472c7c8d..ed1b627b 100644
--- a/gui/ConsoleWindow.ui
+++ b/gui/ConsoleWindow.ui
@@ -1,99 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConsoleWindow</class>
- <widget class="QDialog" name="ConsoleWindow">
+ <widget class="QMainWindow" name="ConsoleWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>610</width>
- <height>391</height>
+ <width>640</width>
+ <height>440</height>
</rect>
</property>
<property name="windowTitle">
<string>MultiMC Console</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>6</number>
- </property>
- <item>
- <widget class="QPlainTextEdit" name="text">
- <property name="font">
- <font>
- <pointsize>10</pointsize>
- </font>
- </property>
- <property name="undoRedoEnabled">
- <bool>false</bool>
- </property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
- <property name="plainText">
- <string notr="true"/>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- <property name="centerOnScroll">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="leftMargin">
- <number>6</number>
- </property>
- <property name="rightMargin">
- <number>6</number>
- </property>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="btnKillMinecraft">
- <property name="text">
- <string>&amp;Kill Minecraft</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="closeButton">
- <property name="text">
- <string>&amp;Close</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QPlainTextEdit" name="text">
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="undoRedoEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ <property name="plainText">
+ <string notr="true"/>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ <property name="centerOnScroll">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnKillMinecraft">
+ <property name="text">
+ <string>&amp;Kill Minecraft</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="closeButton">
+ <property name="text">
+ <string>&amp;Close</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
</widget>
- <tabstops>
- <tabstop>text</tabstop>
- <tabstop>closeButton</tabstop>
- <tabstop>btnKillMinecraft</tabstop>
- </tabstops>
<resources/>
<connections/>
</ui>
diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp
index 7ea67764..6ae41f50 100644
--- a/gui/MainWindow.cpp
+++ b/gui/MainWindow.cpp
@@ -127,8 +127,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
view->installEventFilter(this);
proxymodel = new InstanceProxyModel(this);
-// proxymodel->setSortRole(KCategorizedSortFilterProxyModel::CategorySortRole);
- //proxymodel->setFilterRole(KCategorizedSortFilterProxyModel::CategorySortRole);
+ // proxymodel->setSortRole(KCategorizedSortFilterProxyModel::CategorySortRole);
+ // proxymodel->setFilterRole(KCategorizedSortFilterProxyModel::CategorySortRole);
// proxymodel->setDynamicSortFilter ( true );
// FIXME: instList should be global-ish, or at least not tied to the main window...
@@ -176,6 +176,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
{
MMC->lwjgllist()->loadList();
}
+
assets_downloader = new OneSixAssets();
connect(assets_downloader, SIGNAL(indexStarted()), SLOT(assetsIndexStarted()));
connect(assets_downloader, SIGNAL(filesStarted()), SLOT(assetsFilesStarted()));
@@ -418,7 +419,7 @@ void MainWindow::on_actionSettings_triggered()
{
SettingsDialog dialog(this);
dialog.exec();
- //FIXME: quick HACK to make this work. improve, optimize.
+ // FIXME: quick HACK to make this work. improve, optimize.
proxymodel->invalidate();
proxymodel->sort(0);
}
@@ -598,7 +599,7 @@ void MainWindow::doLogin(const QString &errorMsg)
void MainWindow::prepareLaunch(BaseInstance* instance, MojangAccountPtr account)
{
- BaseUpdate *updateTask = instance->doUpdate();
+ Task *updateTask = instance->doUpdate();
if (!updateTask)
{
launchInstance(instance, account);
@@ -606,7 +607,7 @@ void MainWindow::prepareLaunch(BaseInstance* instance, MojangAccountPtr account)
else
{
ProgressDialog tDialog(this);
- connect(updateTask, &BaseUpdate::succeeded, [this, instance, account] { launchInstance(instance, account); });
+ connect(updateTask, &Task::succeeded, [this, instance, account] { launchInstance(instance, account); });
connect(updateTask, SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString)));
tDialog.exec(updateTask);
delete updateTask;
@@ -667,29 +668,15 @@ void MainWindow::launchInstance(BaseInstance *instance, MojangAccountPtr account
if (!proc)
return;
- // Prepare GUI: If it shall stay open disable the required parts
- if (MMC->settings()->get("NoHide").toBool())
- {
- ui->actionLaunchInstance->setEnabled(false);
- }
- else
- {
- this->hide();
- }
+ this->hide();
console = new ConsoleWindow(proc);
-
- connect(proc, SIGNAL(log(QString, MessageLevel::Enum)), console,
- SLOT(write(QString, MessageLevel::Enum)));
- connect(proc, SIGNAL(ended(BaseInstance *)), this, SLOT(instanceEnded(BaseInstance *)));
-
- if (instance->settings().get("ShowConsole").toBool())
- {
- console->show();
- }
+ connect(console, SIGNAL(isClosing()), this, SLOT(instanceEnded()));
// I think this will work...
- proc->setLogin(account->username(), account->accessToken());
+ QString username = account->username();
+ QString session_id = account->accessToken();
+ proc->setLogin(username, session_id);
proc->launch();
}
@@ -845,15 +832,9 @@ void MainWindow::on_actionEditInstNotes_triggered()
}
}
-void MainWindow::instanceEnded(BaseInstance *instance)
+void MainWindow::instanceEnded()
{
this->show();
- ui->actionLaunchInstance->setEnabled(m_selectedInstance);
-
- if (instance->settings().get("AutoCloseConsole").toBool())
- {
- console->close();
- }
}
void MainWindow::checkSetDefaultJava()
diff --git a/gui/MainWindow.h b/gui/MainWindow.h
index f88905bf..3b8d4668 100644
--- a/gui/MainWindow.h
+++ b/gui/MainWindow.h
@@ -16,6 +16,7 @@
#pragma once
#include <QMainWindow>
+#include <QProcess>
#include "logic/lists/InstanceList.h"
#include "logic/net/LoginTask.h"
@@ -125,7 +126,7 @@ slots:
void on_actionChangeInstLWJGLVersion_triggered();
- void instanceEnded(BaseInstance *instance);
+ void instanceEnded();
void on_actionInstanceSettings_triggered();
diff --git a/gui/dialogs/AboutDialog.ui b/gui/dialogs/AboutDialog.ui
index 0a189d9c..f674eb61 100644
--- a/gui/dialogs/AboutDialog.ui
+++ b/gui/dialogs/AboutDialog.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>450</width>
- <height>429</height>
+ <width>637</width>
+ <height>579</height>
</rect>
</property>
<property name="minimumSize">
@@ -59,7 +59,7 @@
<string/>
</property>
<property name="pixmap">
- <pixmap resource="../../multimc.qrc">:/icons/multimc/scalable/apps/multimc.svg</pixmap>
+ <pixmap resource="../../graphics.qrc">:/icons/multimc/scalable/apps/multimc.svg</pixmap>
</property>
</widget>
</item>
@@ -100,8 +100,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>432</width>
- <height>179</height>
+ <width>619</width>
+ <height>329</height>
</rect>
</property>
<attribute name="label">
@@ -159,8 +159,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>98</width>
- <height>120</height>
+ <width>619</width>
+ <height>329</height>
</rect>
</property>
<attribute name="label">
@@ -203,8 +203,8 @@ p, li { white-space: pre-wrap; }
<rect>
<x>0</x>
<y>0</y>
- <width>98</width>
- <height>88</height>
+ <width>619</width>
+ <height>329</height>
</rect>
</property>
<attribute name="label">
@@ -227,6 +227,7 @@ p, li { white-space: pre-wrap; }
&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:'Bitstream Vera Sans'; 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-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-family:'Ubuntu'; font-size:10pt;&quot;&gt;Copyright 2012 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-family:'Ubuntu'; 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-family:'Ubuntu'; font-size:10pt;&quot;&gt;you may not use this file except in compliance with the License.&lt;/span&gt;&lt;/p&gt;
@@ -240,31 +241,124 @@ 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; font-size:10pt;&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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; font-size:10pt;&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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; font-size:10pt;&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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; 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-family:'Ubuntu'; font-size:10pt;&quot;&gt;OF THE POSSIBILITY OF SUCH DAMAGE.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&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;-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 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-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: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 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;-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;-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;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;-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 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-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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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-size:18pt; font-weight:600;&quot;&gt;Pack200&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;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: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;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: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;+ &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: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;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:10pt;&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:10pt;&quot;&gt;only where Oracle has expressly included in the particular source file'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:10pt;&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:10pt;&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: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; 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:10pt;&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:10pt;&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: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; 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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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-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:10pt;&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: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 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:10pt;&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:10pt;&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:10pt;&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: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 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:10pt;&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:10pt;&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:10pt;&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: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;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:10pt;&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:10pt;&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: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;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: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;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:10pt;&quot;&gt;quazip/(un)zip.h files for details, basically it'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;&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:10pt;&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-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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&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:10pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
@@ -309,8 +403,8 @@ p, li { white-space: pre-wrap; }
</layout>
</widget>
<resources>
- <include location="../../multimc.qrc"/>
- <include location="../../multimc.qrc"/>
+ <include location="../../graphics.qrc"/>
+ <include location="../../graphics.qrc"/>
</resources>
<connections/>
</ui>
diff --git a/gui/dialogs/CopyInstanceDialog.ui b/gui/dialogs/CopyInstanceDialog.ui
index dd7ce641..4aa1cb27 100644
--- a/gui/dialogs/CopyInstanceDialog.ui
+++ b/gui/dialogs/CopyInstanceDialog.ui
@@ -17,7 +17,7 @@
<string>Copy Instance</string>
</property>
<property name="windowIcon">
- <iconset resource="../../multimc.qrc">
+ <iconset resource="../../graphics.qrc">
<normaloff>:/icons/toolbar/copy</normaloff>:/icons/toolbar/copy</iconset>
</property>
<property name="modal">
@@ -42,7 +42,7 @@
<item>
<widget class="QToolButton" name="iconButton">
<property name="icon">
- <iconset resource="../../multimc.qrc">
+ <iconset resource="../../graphics.qrc">
<normaloff>:/icons/instances/infinity</normaloff>:/icons/instances/infinity</iconset>
</property>
<property name="iconSize">
@@ -95,7 +95,7 @@
</layout>
</widget>
<resources>
- <include location="../../multimc.qrc"/>
+ <include location="../../graphics.qrc"/>
</resources>
<connections>
<connection>
diff --git a/gui/dialogs/LoginDialog.ui b/gui/dialogs/LoginDialog.ui
index d15679dd..45f319ed 100644
--- a/gui/dialogs/LoginDialog.ui
+++ b/gui/dialogs/LoginDialog.ui
@@ -50,7 +50,7 @@
<string/>
</property>
<property name="pixmap">
- <pixmap resource="../../multimc.qrc">:/icons/instances/steve</pixmap>
+ <pixmap resource="../../graphics.qrc">:/icons/instances/steve</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
@@ -146,7 +146,7 @@
</layout>
</widget>
<resources>
- <include location="../../multimc.qrc"/>
+ <include location="../../graphics.qrc"/>
<include location="../multimc.qrc"/>
</resources>
<connections>
diff --git a/gui/dialogs/NewInstanceDialog.ui b/gui/dialogs/NewInstanceDialog.ui
index b4b8723e..00544463 100644
--- a/gui/dialogs/NewInstanceDialog.ui
+++ b/gui/dialogs/NewInstanceDialog.ui
@@ -17,7 +17,7 @@
<string>New Instance</string>
</property>
<property name="windowIcon">
- <iconset resource="../../multimc.qrc">
+ <iconset resource="../../graphics.qrc">
<normaloff>:/icons/toolbar/new</normaloff>:/icons/toolbar/new</iconset>
</property>
<property name="modal">
@@ -42,7 +42,7 @@
<item>
<widget class="QToolButton" name="iconButton">
<property name="icon">
- <iconset resource="../../multimc.qrc">
+ <iconset resource="../../graphics.qrc">
<normaloff>:/icons/instances/infinity</normaloff>:/icons/instances/infinity</iconset>
</property>
<property name="iconSize">
@@ -140,7 +140,7 @@
</layout>
</widget>
<resources>
- <include location="../../multimc.qrc"/>
+ <include location="../../graphics.qrc"/>
</resources>
<connections>
<connection>
diff --git a/gui/dialogs/SettingsDialog.cpp b/gui/dialogs/SettingsDialog.cpp
index e4f22d83..57e15a5b 100644
--- a/gui/dialogs/SettingsDialog.cpp
+++ b/gui/dialogs/SettingsDialog.cpp
@@ -25,6 +25,7 @@
#include "logic/JavaUtils.h"
#include "logic/NagUtils.h"
#include "logic/lists/JavaVersionList.h"
+#include <logic/JavaChecker.h>
#include <settingsobject.h>
#include <pathutils.h>
@@ -98,12 +99,6 @@ void SettingsDialog::on_lwjglDirBrowseBtn_clicked()
}
}
-void SettingsDialog::on_compatModeCheckBox_clicked(bool checked)
-{
- Q_UNUSED(checked);
- updateCheckboxStuff();
-}
-
void SettingsDialog::on_maximizedCheckBox_clicked(bool checked)
{
Q_UNUSED(checked);
@@ -235,7 +230,7 @@ void SettingsDialog::loadSettings(SettingsObject *s)
ui->postExitCmdTextBox->setText(s->get("PostExitCommand").toString());
}
-void SettingsDialog::on_pushButton_clicked()
+void SettingsDialog::on_javaDetectBtn_clicked()
{
JavaVersionPtr java;
@@ -250,7 +245,7 @@ void SettingsDialog::on_pushButton_clicked()
}
}
-void SettingsDialog::on_btnBrowse_clicked()
+void SettingsDialog::on_javaBrowseBtn_clicked()
{
QString dir = QFileDialog::getOpenFileName(this, tr("Find Java executable"));
if (!dir.isNull())
@@ -258,3 +253,32 @@ void SettingsDialog::on_btnBrowse_clicked()
ui->javaPathTextBox->setText(dir);
}
}
+
+void SettingsDialog::on_javaTestBtn_clicked()
+{
+ checker.reset(new JavaChecker());
+ connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
+ SLOT(checkFinished(JavaCheckResult)));
+ checker->performCheck(ui->javaPathTextBox->text());
+}
+
+void SettingsDialog::checkFinished(JavaCheckResult result)
+{
+ if (result.valid)
+ {
+ QString text;
+ text += "Java test succeeded!\n";
+ if (result.is_64bit)
+ text += "Using 64bit java.\n";
+ text += "\n";
+ text += "Platform reported: " + result.realPlatform;
+ QMessageBox::information(this, tr("Java test success"), text);
+ }
+ else
+ {
+ QMessageBox::information(
+ this, tr("Java test failure"),
+ tr("The specified java binary didn't work. You should use the auto-detect feature, "
+ "or set the path to the java executable."));
+ }
+}
diff --git a/gui/dialogs/SettingsDialog.h b/gui/dialogs/SettingsDialog.h
index e24047c3..0cb8fa38 100644
--- a/gui/dialogs/SettingsDialog.h
+++ b/gui/dialogs/SettingsDialog.h
@@ -15,8 +15,11 @@
#pragma once
+#include <memory>
#include <QDialog>
+#include "logic/JavaChecker.h"
+
class SettingsObject;
namespace Ui
@@ -48,16 +51,18 @@ slots:
void on_lwjglDirBrowseBtn_clicked();
- void on_compatModeCheckBox_clicked(bool checked);
-
void on_maximizedCheckBox_clicked(bool checked);
void on_buttonBox_accepted();
- void on_pushButton_clicked();
+ void on_javaDetectBtn_clicked();
+
+ void on_javaTestBtn_clicked();
- void on_btnBrowse_clicked();
+ void on_javaBrowseBtn_clicked();
+ void checkFinished(JavaCheckResult result);
private:
Ui::SettingsDialog *ui;
+ std::shared_ptr<JavaChecker> checker;
};
diff --git a/gui/dialogs/SettingsDialog.ui b/gui/dialogs/SettingsDialog.ui
index 53a41d6e..6a44a631 100644
--- a/gui/dialogs/SettingsDialog.ui
+++ b/gui/dialogs/SettingsDialog.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>502</width>
+ <width>526</width>
<height>599</height>
</rect>
</property>
@@ -20,7 +20,7 @@
<string>Settings</string>
</property>
<property name="windowIcon">
- <iconset resource="../../multimc.qrc">
+ <iconset resource="../../graphics.qrc">
<normaloff>:/icons/toolbar/settings</normaloff>:/icons/toolbar/settings</iconset>
</property>
<property name="modal">
@@ -407,8 +407,14 @@
</property>
</widget>
</item>
- <item row="1" column="3">
- <widget class="QPushButton" name="btnBrowse">
+ <item row="0" column="1" colspan="5">
+ <widget class="QLineEdit" name="javaPathTextBox"/>
+ </item>
+ <item row="2" column="1" colspan="5">
+ <widget class="QLineEdit" name="jvmArgsTextBox"/>
+ </item>
+ <item row="1" column="5">
+ <widget class="QPushButton" name="javaTestBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -416,15 +422,25 @@
</sizepolicy>
</property>
<property name="text">
- <string>Browse...</string>
+ <string>Test</string>
</property>
</widget>
</item>
- <item row="0" column="1" colspan="3">
- <widget class="QLineEdit" name="javaPathTextBox"/>
+ <item row="1" column="4">
+ <widget class="QPushButton" name="javaBrowseBtn">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Browse...</string>
+ </property>
+ </widget>
</item>
- <item row="1" column="2">
- <widget class="QPushButton" name="pushButton">
+ <item row="1" column="3">
+ <widget class="QPushButton" name="javaDetectBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -436,9 +452,6 @@
</property>
</widget>
</item>
- <item row="2" column="1" colspan="3">
- <widget class="QLineEdit" name="jvmArgsTextBox"/>
- </item>
</layout>
</widget>
</item>
@@ -528,14 +541,12 @@
<tabstop>maxMemSpinBox</tabstop>
<tabstop>permGenSpinBox</tabstop>
<tabstop>javaPathTextBox</tabstop>
- <tabstop>pushButton</tabstop>
- <tabstop>btnBrowse</tabstop>
<tabstop>jvmArgsTextBox</tabstop>
<tabstop>preLaunchCmdTextBox</tabstop>
<tabstop>postExitCmdTextBox</tabstop>
</tabstops>
<resources>
- <include location="../../multimc.qrc"/>
+ <include location="../../graphics.qrc"/>
</resources>
<connections>
<connection>
diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h
index b92d50cc..cf86fda6 100644
--- a/logic/BaseInstance.h
+++ b/logic/BaseInstance.h
@@ -25,7 +25,7 @@
#include "logic/auth/MojangAccount.h"
class QDialog;
-class BaseUpdate;
+class Task;
class MinecraftProcess;
class OneSixUpdate;
class InstanceList;
@@ -151,7 +151,7 @@ public:
virtual SettingsObject &settings() const;
/// returns a valid update task if update is needed, NULL otherwise
- virtual BaseUpdate *doUpdate() = 0;
+ virtual Task *doUpdate() = 0;
/// returns a valid minecraft process, ready for launch with the given account.
virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account) = 0;
diff --git a/logic/BaseUpdate.cpp b/logic/BaseUpdate.cpp
deleted file mode 100644
index 5aeb12ef..00000000
--- a/logic/BaseUpdate.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright 2013 MultiMC Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BaseUpdate.h"
-
-BaseUpdate::BaseUpdate(BaseInstance *inst, QObject *parent) : Task(parent)
-{
- m_inst = inst;
-}
-
-void BaseUpdate::updateDownloadProgress(qint64 current, qint64 total)
-{
- emit progress(current, total);
-} \ No newline at end of file
diff --git a/logic/BaseUpdate.h b/logic/BaseUpdate.h
deleted file mode 100644
index ddeefa97..00000000
--- a/logic/BaseUpdate.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright 2013 MultiMC Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <QObject>
-#include <QList>
-#include <QUrl>
-
-#include "net/NetJob.h"
-
-#include "tasks/Task.h"
-
-class MinecraftVersion;
-class BaseInstance;
-
-/*!
- * The game update task is the task that handles downloading instances' files.
- */
-class BaseUpdate : public Task
-{
- Q_OBJECT
-public:
- explicit BaseUpdate(BaseInstance *inst, QObject *parent = 0);
-
- virtual void executeTask() = 0;
-
-protected
-slots:
- // virtual void error(const QString &msg);
- void updateDownloadProgress(qint64 current, qint64 total);
-
-protected:
- BaseInstance *m_inst;
-};
diff --git a/logic/InstanceLauncher.cpp b/logic/InstanceLauncher.cpp
index c4df8220..0ef0f045 100644
--- a/logic/InstanceLauncher.cpp
+++ b/logic/InstanceLauncher.cpp
@@ -50,12 +50,9 @@ void InstanceLauncher::onLoginComplete()
return;
}
console = new ConsoleWindow(proc);
- console->show();
-
- connect(proc, SIGNAL(ended()), SLOT(onTerminated()));
- connect(proc, SIGNAL(log(QString, MessageLevel::Enum)), console,
- SLOT(write(QString, MessageLevel::Enum)));
+ connect(console, SIGNAL(isClosing()), this, SLOT(onTerminated()));
+ proc->setLogin(result.username, result.session_id);
proc->launch();
*/
}
@@ -66,7 +63,7 @@ void InstanceLauncher::doLogin(const QString &errorMsg)
loginDlg->exec();
if (loginDlg->result() == QDialog::Accepted)
{
- UserInfo uInfo{loginDlg->getUsername(), loginDlg->getPassword()};
+ PasswordLogin uInfo{loginDlg->getUsername(), loginDlg->getPassword()};
ProgressDialog *tDialog = new ProgressDialog(nullptr);
LoginTask *loginTask = new LoginTask(uInfo, tDialog);
diff --git a/logic/JavaChecker.cpp b/logic/JavaChecker.cpp
new file mode 100644
index 00000000..10b84fe1
--- /dev/null
+++ b/logic/JavaChecker.cpp
@@ -0,0 +1,89 @@
+#include "JavaChecker.h"
+#include <QFile>
+#include <QProcess>
+
+#define CHECKER_FILE "JavaChecker.jar"
+
+JavaChecker::JavaChecker(QObject *parent) : QObject(parent)
+{
+}
+
+int JavaChecker::performCheck(QString path)
+{
+ if(QFile::exists(CHECKER_FILE))
+ {
+ QFile::remove(CHECKER_FILE);
+ }
+ // extract the checker
+ QFile(":/java/checker.jar").copy(CHECKER_FILE);
+
+ QStringList args = {"-jar", CHECKER_FILE};
+
+ process.reset(new QProcess());
+ process->setArguments(args);
+ process->setProgram(path);
+ process->setProcessChannelMode(QProcess::SeparateChannels);
+
+ connect(process.get(), SIGNAL(finished(int, QProcess::ExitStatus)), this,
+ SLOT(finished(int, QProcess::ExitStatus)));
+ connect(process.get(), SIGNAL(error(QProcess::ProcessError)), this,
+ SLOT(error(QProcess::ProcessError)));
+ connect(&killTimer, SIGNAL(timeout()), SLOT(timeout()));
+ killTimer.setSingleShot(true);
+ killTimer.start(5000);
+ process->start();
+}
+
+void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
+{
+ killTimer.stop();
+ QProcessPtr _process;
+ _process.swap(process);
+
+ if (status == QProcess::CrashExit || exitcode == 1)
+ {
+ emit checkFinished({});
+ return;
+ }
+
+ QString p_stdout = _process->readAllStandardOutput();
+ auto parts = p_stdout.split('=', QString::SkipEmptyParts);
+ if (parts.size() != 2 || parts[0] != "os.arch")
+ {
+ emit checkFinished({});
+ return;
+ }
+
+ auto os_arch = parts[1].remove('\n').remove('\r');
+ bool is_64 = os_arch == "x86_64" || os_arch == "amd64";
+
+ JavaCheckResult result;
+ {
+ result.valid = true;
+ result.is_64bit = is_64;
+ result.mojangPlatform = is_64 ? "64" : "32";
+ result.realPlatform = os_arch;
+ }
+ emit checkFinished(result);
+}
+
+void JavaChecker::error(QProcess::ProcessError err)
+{
+ if(err == QProcess::FailedToStart)
+ {
+ killTimer.stop();
+ emit checkFinished({});
+ return;
+ }
+}
+
+void JavaChecker::timeout()
+{
+ // NO MERCY. NO ABUSE.
+ if(process)
+ {
+ process->kill();
+ process.reset();
+ emit checkFinished({});
+ }
+}
diff --git a/logic/JavaChecker.h b/logic/JavaChecker.h
new file mode 100644
index 00000000..60f8b56f
--- /dev/null
+++ b/logic/JavaChecker.h
@@ -0,0 +1,32 @@
+#pragma once
+#include <QProcess>
+#include <QTimer>
+#include <memory>
+
+struct JavaCheckResult
+{
+ QString mojangPlatform;
+ QString realPlatform;
+ bool valid = false;
+ bool is_64bit = false;
+};
+typedef std::shared_ptr<QProcess> QProcessPtr;
+
+class JavaChecker : public QObject
+{
+ Q_OBJECT
+public:
+ explicit JavaChecker(QObject *parent = 0);
+ int performCheck(QString path);
+
+signals:
+ void checkFinished(JavaCheckResult result);
+private:
+ QProcessPtr process;
+ QTimer killTimer;
+public
+slots:
+ void timeout();
+ void finished(int exitcode, QProcess::ExitStatus);
+ void error(QProcess::ProcessError);
+};
diff --git a/logic/JavaUtils.h b/logic/JavaUtils.h
index 8d7550d0..44f576b4 100644
--- a/logic/JavaUtils.h
+++ b/logic/JavaUtils.h
@@ -33,7 +33,6 @@ public:
QList<JavaVersionPtr> FindJavaPaths();
JavaVersionPtr GetDefaultJava();
-
private:
#if WINDOWS
diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp
index 3a337140..ab6536d0 100644
--- a/logic/LegacyInstance.cpp
+++ b/logic/LegacyInstance.cpp
@@ -44,7 +44,7 @@ LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings,
settings->registerSetting(new Setting("IntendedJarVersion", ""));
}
-BaseUpdate *LegacyInstance::doUpdate()
+Task *LegacyInstance::doUpdate()
{
auto list = jarModList();
return new LegacyUpdate(this, this);
@@ -59,7 +59,7 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account)
pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG");
// extract the legacy launcher
- QFile(":/launcher/launcher.jar").copy(PathCombine(minecraftRoot(), LAUNCHER_FILE));
+ QFile(":/java/launcher.jar").copy(PathCombine(minecraftRoot(), LAUNCHER_FILE));
// set the process arguments
{
@@ -104,15 +104,15 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account)
args << "-jar" << LAUNCHER_FILE;
args << account->currentProfile()->name();
- args << account->accessToken();
+ args << account->sessionId();
args << windowTitle;
args << windowSize;
args << lwjgl;
- proc->setMinecraftArguments(args);
+ proc->setArguments(args);
}
// set the process work path
- proc->setMinecraftWorkdir(minecraftRoot());
+ proc->setWorkdir(minecraftRoot());
return proc;
}
@@ -227,56 +227,18 @@ QString LegacyInstance::instanceConfigFolder() const
return PathCombine(minecraftRoot(), "config");
}
-/*
-bool LegacyInstance::shouldUpdateCurrentVersion() const
-{
- QFileInfo jar(runnableJar());
- return jar.lastModified().toUTC().toMSecsSinceEpoch() != lastCurrentVersionUpdate();
-}
-
-void LegacyInstance::updateCurrentVersion(bool keepCurrent)
-{
- QFileInfo jar(runnableJar());
-
- if(!jar.exists())
- {
- setLastCurrentVersionUpdate(0);
- setCurrentVersionId("Unknown");
- return;
- }
-
- qint64 time = jar.lastModified().toUTC().toMSecsSinceEpoch();
-
- setLastCurrentVersionUpdate(time);
- if (!keepCurrent)
- {
- // TODO: Implement GetMinecraftJarVersion function.
- QString newVersion =
-"Unknown";//javautils::GetMinecraftJarVersion(jar.absoluteFilePath());
- setCurrentVersionId(newVersion);
- }
-}
-qint64 LegacyInstance::lastCurrentVersionUpdate() const
-{
- I_D(LegacyInstance);
- return d->m_settings->get ( "lastVersionUpdate" ).value<qint64>();
-}
-void LegacyInstance::setLastCurrentVersionUpdate ( qint64 val )
-{
- I_D(LegacyInstance);
- d->m_settings->set ( "lastVersionUpdate", val );
-}
-*/
bool LegacyInstance::shouldRebuild() const
{
I_D(LegacyInstance);
return d->m_settings->get("NeedsRebuild").toBool();
}
+
void LegacyInstance::setShouldRebuild(bool val)
{
I_D(LegacyInstance);
d->m_settings->set("NeedsRebuild", val);
}
+
QString LegacyInstance::currentVersionId() const
{
I_D(LegacyInstance);
@@ -294,22 +256,26 @@ QString LegacyInstance::lwjglVersion() const
I_D(LegacyInstance);
return d->m_settings->get("LwjglVersion").toString();
}
+
void LegacyInstance::setLWJGLVersion(QString val)
{
I_D(LegacyInstance);
d->m_settings->set("LwjglVersion", val);
}
+
QString LegacyInstance::intendedVersionId() const
{
I_D(LegacyInstance);
return d->m_settings->get("IntendedJarVersion").toString();
}
+
bool LegacyInstance::setIntendedVersionId(QString version)
{
settings().set("IntendedJarVersion", version);
setShouldUpdate(true);
return true;
}
+
bool LegacyInstance::shouldUpdate() const
{
I_D(LegacyInstance);
@@ -320,6 +286,7 @@ bool LegacyInstance::shouldUpdate() const
}
return true;
}
+
void LegacyInstance::setShouldUpdate(bool val)
{
settings().set("ShouldUpdate", val);
diff --git a/logic/LegacyInstance.h b/logic/LegacyInstance.h
index e78bfd73..3d35521e 100644
--- a/logic/LegacyInstance.h
+++ b/logic/LegacyInstance.h
@@ -18,7 +18,7 @@
#include "BaseInstance.h"
class ModList;
-class BaseUpdate;
+class Task;
class LegacyInstance : public BaseInstance
{
@@ -78,7 +78,7 @@ public:
virtual bool shouldUpdate() const;
virtual void setShouldUpdate(bool val);
- virtual BaseUpdate *doUpdate();
+ virtual Task *doUpdate();
virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account);
virtual void cleanupAfterRun();
diff --git a/logic/LegacyUpdate.cpp b/logic/LegacyUpdate.cpp
index 8ba97827..05442917 100644
--- a/logic/LegacyUpdate.cpp
+++ b/logic/LegacyUpdate.cpp
@@ -26,7 +26,7 @@
#include <JlCompress.h>
#include "logger/QsLog.h"
-LegacyUpdate::LegacyUpdate(BaseInstance *inst, QObject *parent) : BaseUpdate(inst, parent)
+LegacyUpdate::LegacyUpdate(BaseInstance *inst, QObject *parent) : Task(parent), m_inst(inst)
{
}
diff --git a/logic/LegacyUpdate.h b/logic/LegacyUpdate.h
index b30fa0b3..8ffdb0f0 100644
--- a/logic/LegacyUpdate.h
+++ b/logic/LegacyUpdate.h
@@ -21,14 +21,13 @@
#include "logic/net/NetJob.h"
#include "logic/tasks/Task.h"
-#include "logic/BaseUpdate.h"
class MinecraftVersion;
class BaseInstance;
class QuaZip;
class Mod;
-class LegacyUpdate : public BaseUpdate
+class LegacyUpdate : public Task
{
Q_OBJECT
public:
@@ -72,4 +71,5 @@ private:
private:
NetJobPtr legacyDownloadJob;
+ BaseInstance *m_inst;
};
diff --git a/logic/MinecraftProcess.cpp b/logic/MinecraftProcess.cpp
index ff122628..e4a26054 100644
--- a/logic/MinecraftProcess.cpp
+++ b/logic/MinecraftProcess.cpp
@@ -59,12 +59,12 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst)
connect(this, SIGNAL(readyReadStandardOutput()), SLOT(on_stdOut()));
}
-void MinecraftProcess::setMinecraftArguments(QStringList args)
+void MinecraftProcess::setArguments(QStringList args)
{
m_args = args;
}
-void MinecraftProcess::setMinecraftWorkdir(QString path)
+void MinecraftProcess::setWorkdir(QString path)
{
QDir mcDir(path);
this->setWorkingDirectory(mcDir.absolutePath());
@@ -101,7 +101,7 @@ void MinecraftProcess::on_stdOut()
for (int i = 0; i < lines.size() - 1; i++)
{
QString &line = lines[i];
- emit log(line /*.replace(username, "<Username>").replace(sessionID, "<Session ID>")*/,
+ emit log(line.replace(username, "<Username>").replace(sessionID, "<Session ID>"),
getLevel(line, MessageLevel::Message));
}
if (!complete)
@@ -111,19 +111,24 @@ void MinecraftProcess::on_stdOut()
// exit handler
void MinecraftProcess::finish(int code, ExitStatus status)
{
- if (status != NormalExit)
+ if (!killed)
{
- // TODO: error handling
+ if (status == NormalExit)
+ {
+ //: Message displayed on instance exit
+ emit log(tr("Minecraft exited with exitcode %1.").arg(code));
+ }
+ else
+ {
+ //: Message displayed on instance crashed
+ emit log(tr("Minecraft crashed with exitcode %1.").arg(code));
+ }
}
-
- // TODO: Localization
-
- if (!killed)
- //: Message displayed on instance exit
- emit log(tr("Minecraft exited with exitcode %1.").arg(status));
else
+ {
//: Message displayed after the instance exits due to kill request
emit log(tr("Minecraft was killed by user."), MessageLevel::Error);
+ }
m_prepostlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(code));
@@ -134,11 +139,12 @@ void MinecraftProcess::finish(int code, ExitStatus status)
m_prepostlaunchprocess.waitForFinished();
if (m_prepostlaunchprocess.exitStatus() != NormalExit)
{
- // TODO: error handling
+ emit postlaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(),
+ m_prepostlaunchprocess.exitStatus());
}
}
m_instance->cleanupAfterRun();
- emit ended(m_instance);
+ emit ended(m_instance, code, status);
}
void MinecraftProcess::killMinecraft()
@@ -155,7 +161,9 @@ void MinecraftProcess::launch()
m_prepostlaunchprocess.waitForFinished();
if (m_prepostlaunchprocess.exitStatus() != NormalExit)
{
- // TODO: error handling
+ m_instance->cleanupAfterRun();
+ emit prelaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(),
+ m_prepostlaunchprocess.exitStatus());
return;
}
}
@@ -166,15 +174,15 @@ void MinecraftProcess::launch()
QString JavaPath = m_instance->settings().get("JavaPath").toString();
emit log(QString("Java path: '%1'").arg(JavaPath));
emit log(QString("Arguments: '%1'").arg(
- m_args.join("' '") /*.replace(username, "<Username>").replace(sessionID, "<Session
-ID>")*/));
+ m_args.join("' '").replace(username, "<Username>").replace(sessionID, "<Session ID>")));
start(JavaPath, m_args);
if (!waitForStarted())
{
//: Error message displayed if instace can't start
- emit log(tr("Could not launch minecraft!"));
+ emit log(tr("Could not launch minecraft!"), MessageLevel::Error);
+ m_instance->cleanupAfterRun();
+ emit launch_failed(m_instance);
return;
- // TODO: error handling
}
}
diff --git a/logic/MinecraftProcess.h b/logic/MinecraftProcess.h
index ad887c5b..e38d2f83 100644
--- a/logic/MinecraftProcess.h
+++ b/logic/MinecraftProcess.h
@@ -58,9 +58,14 @@ public:
*/
void launch();
- void setMinecraftWorkdir(QString path);
+ BaseInstance *instance()
+ {
+ return m_instance;
+ }
+
+ void setWorkdir(QString path);
- void setMinecraftArguments(QStringList args);
+ void setArguments(QStringList args);
void killMinecraft();
@@ -72,9 +77,24 @@ public:
signals:
/**
+ * @brief emitted when Minecraft immediately fails to run
+ */
+ void launch_failed(BaseInstance *);
+
+ /**
+ * @brief emitted when the PreLaunchCommand fails
+ */
+ void prelaunch_failed(BaseInstance *, int code, QProcess::ExitStatus status);
+
+ /**
+ * @brief emitted when the PostLaunchCommand fails
+ */
+ void postlaunch_failed(BaseInstance *, int code, QProcess::ExitStatus status);
+
+ /**
* @brief emitted when mc has finished and the PostLaunchCommand was run
*/
- void ended(BaseInstance *);
+ void ended(BaseInstance *, int code, QProcess::ExitStatus status);
/**
* @brief emitted when we want to log something
diff --git a/logic/OneSixAssets.cpp b/logic/OneSixAssets.cpp
index dbc42262..400aff2c 100644
--- a/logic/OneSixAssets.cpp
+++ b/logic/OneSixAssets.cpp
@@ -22,6 +22,8 @@
#include "net/S3ListBucket.h"
#include "MultiMC.h"
+#define ASSETS_URL "http://resources.download.minecraft.net/"
+
class ThreadedDeleter : public QThread
{
Q_OBJECT
@@ -69,7 +71,7 @@ void OneSixAssets::downloadFinished()
void OneSixAssets::S3BucketFinished()
{
- QString prefix("http://s3.amazonaws.com/Minecraft.Resources/");
+ QString prefix(ASSETS_URL);
nuke_whitelist.clear();
emit filesStarted();
@@ -114,7 +116,7 @@ void OneSixAssets::S3BucketFinished()
void OneSixAssets::start()
{
auto job = new NetJob("Assets index");
- job->addNetAction(S3ListBucket::make(QUrl("http://s3.amazonaws.com/Minecraft.Resources/")));
+ job->addNetAction(S3ListBucket::make(QUrl(ASSETS_URL)));
connect(job, SIGNAL(succeeded()), SLOT(S3BucketFinished()));
connect(job, SIGNAL(failed()), SIGNAL(failed()));
emit indexStarted();
diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp
index 5a83bafc..a947b7c0 100644
--- a/logic/OneSixInstance.cpp
+++ b/logic/OneSixInstance.cpp
@@ -18,6 +18,7 @@
#include "OneSixUpdate.h"
#include "MinecraftProcess.h"
#include "OneSixVersion.h"
+#include "JavaChecker.h"
#include <setting.h>
#include <pathutils.h>
@@ -36,7 +37,7 @@ OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_o
reloadFullVersion();
}
-BaseUpdate *OneSixInstance::doUpdate()
+Task *OneSixInstance::doUpdate()
{
return new OneSixUpdate(this);
}
@@ -74,7 +75,7 @@ QStringList OneSixInstance::processMinecraftArgs(MojangAccountPtr account)
QMap<QString, QString> token_mapping;
// yggdrasil!
token_mapping["auth_username"] = account->username();
- //token_mapping["auth_session"] = response.session_id;
+ token_mapping["auth_session"] = account->sessionId();
token_mapping["auth_access_token"] = account->accessToken();
token_mapping["auth_player_name"] = account->currentProfile()->name();
token_mapping["auth_uuid"] = account->currentProfile()->id();
@@ -93,6 +94,8 @@ QStringList OneSixInstance::processMinecraftArgs(MojangAccountPtr account)
token_mapping["game_directory"] = absRootDir;
QString absAssetsDir = QDir("assets/").absolutePath();
token_mapping["game_assets"] = absAssetsDir;
+ //TODO: this is something new and not even fully implemented in the vanilla launcher.
+ token_mapping["user_properties"] = "{ }";
QStringList parts = args_pattern.split(' ', QString::SkipEmptyParts);
for (int i = 0; i < parts.length(); i++)
@@ -120,6 +123,11 @@ MinecraftProcess *OneSixInstance::prepareForLaunch(MojangAccountPtr account)
for (auto lib : libs_to_extract)
{
+ QString storage = lib->storagePath();
+ if(storage.contains("${arch}"))
+ {
+ storage.replace("${arch}", "64");
+ }
QString path = "libraries/" + lib->storagePath();
QLOG_INFO() << "Will extract " << path.toLocal8Bit();
if (JlCompress::extractWithExceptions(path, natives_dir_raw, lib->extract_excludes)
@@ -186,8 +194,8 @@ MinecraftProcess *OneSixInstance::prepareForLaunch(MojangAccountPtr account)
// create the process and set its parameters
MinecraftProcess *proc = new MinecraftProcess(this);
- proc->setMinecraftArguments(args);
- proc->setMinecraftWorkdir(minecraftRoot());
+ proc->setArguments(args);
+ proc->setWorkdir(minecraftRoot());
return proc;
}
diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h
index c1c742a8..e30ca7ca 100644
--- a/logic/OneSixInstance.h
+++ b/logic/OneSixInstance.h
@@ -20,7 +20,7 @@
#include "BaseInstance.h"
class OneSixVersion;
-class BaseUpdate;
+class Task;
class ModList;
class OneSixInstance : public BaseInstance
@@ -39,8 +39,9 @@ public:
QString loaderModsDir() const;
virtual QString instanceConfigFolder() const;
- virtual BaseUpdate *doUpdate();
+ virtual Task *doUpdate();
virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account);
+
virtual void cleanupAfterRun();
virtual QString intendedVersionId() const;
diff --git a/logic/OneSixRule.h b/logic/OneSixRule.h
index 9cd1a226..5a13cbd9 100644
--- a/logic/OneSixRule.h
+++ b/logic/OneSixRule.h
@@ -16,7 +16,6 @@
#pragma once
#include <QString>
-#include <QSharedPointer>
#include "logic/OneSixLibrary.h"
diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp
index 2d8a167c..c69ff155 100644
--- a/logic/OneSixUpdate.cpp
+++ b/logic/OneSixUpdate.cpp
@@ -28,10 +28,11 @@
#include "OneSixVersion.h"
#include "OneSixLibrary.h"
#include "OneSixInstance.h"
+#include "net/ForgeMirrors.h"
#include "pathutils.h"
-OneSixUpdate::OneSixUpdate(BaseInstance *inst, QObject *parent) : BaseUpdate(inst, parent)
+OneSixUpdate::OneSixUpdate(BaseInstance *inst, QObject *parent) : Task(parent), m_inst(inst)
{
}
@@ -142,7 +143,7 @@ void OneSixUpdate::jarlibStart()
bool successful = inst->reloadFullVersion();
if (!successful)
{
- emitFailed("Failed to load the version description file (version.json). It might be "
+ emitFailed("Failed to load the version description file. It might be "
"corrupted, missing or simply too new.");
return;
}
@@ -163,20 +164,53 @@ void OneSixUpdate::jarlibStart()
libs.append(version->getActiveNormalLibs());
auto metacache = MMC->metacache();
+ QList<ForgeXzDownloadPtr> ForgeLibs;
+ bool already_forge_xz = false;
for (auto lib : libs)
{
if (lib->hint() == "local")
continue;
- QString download_path = lib->downloadUrl();
- auto entry = metacache->resolveEntry("libraries", lib->storagePath());
+ QString storage = lib->storagePath();
+ QString dl = lib->downloadUrl();
+ if (lib->isNative() && storage.contains("${arch}"))
+ {
+ auto storage64 = storage, storage32 = storage;
+ auto dl64 = dl, dl32 = dl;
+ storage64.replace("${arch}", "64");
+ storage32.replace("${arch}", "32");
+ dl32.replace("${arch}", "32");
+ dl64.replace("${arch}", "64");
+
+ auto entry64 = metacache->resolveEntry("libraries", storage64);
+ if (entry64->stale)
+ jarlibDownloadJob->addNetAction(CacheDownload::make(dl64, entry64));
+
+ auto entry32 = metacache->resolveEntry("libraries", storage32);
+ if (entry32->stale)
+ jarlibDownloadJob->addNetAction(CacheDownload::make(dl32, entry32));
+ continue;
+ }
+ auto entry = metacache->resolveEntry("libraries", storage);
if (entry->stale)
{
if (lib->hint() == "forge-pack-xz")
- jarlibDownloadJob->addNetAction(ForgeXzDownload::make(download_path, entry));
+ {
+ ForgeLibs.append(ForgeXzDownload::make(storage, entry));
+ }
else
- jarlibDownloadJob->addNetAction(CacheDownload::make(download_path, entry));
+ {
+ jarlibDownloadJob->addNetAction(CacheDownload::make(dl, entry));
+ }
}
}
+ // TODO: think about how to propagate this from the original json file... or IF AT ALL
+ QString forgeMirrorList = "http://files.minecraftforge.net/mirror-brand.list";
+ if (!ForgeLibs.empty())
+ {
+ jarlibDownloadJob->addNetAction(
+ ForgeMirrors::make(ForgeLibs, jarlibDownloadJob, forgeMirrorList));
+ }
+
connect(jarlibDownloadJob.get(), SIGNAL(succeeded()), SLOT(jarlibFinished()));
connect(jarlibDownloadJob.get(), SIGNAL(failed()), SLOT(jarlibFailed()));
connect(jarlibDownloadJob.get(), SIGNAL(progress(qint64, qint64)),
diff --git a/logic/OneSixUpdate.h b/logic/OneSixUpdate.h
index e5f553c7..a66da067 100644
--- a/logic/OneSixUpdate.h
+++ b/logic/OneSixUpdate.h
@@ -21,12 +21,11 @@
#include "logic/net/NetJob.h"
#include "logic/tasks/Task.h"
-#include "logic/BaseUpdate.h"
class MinecraftVersion;
class BaseInstance;
-class OneSixUpdate : public BaseUpdate
+class OneSixUpdate : public Task
{
Q_OBJECT
public:
@@ -49,4 +48,5 @@ private:
// target version, determined during this task
std::shared_ptr<MinecraftVersion> targetVersion;
+ BaseInstance *m_inst;
};
diff --git a/logic/OneSixVersion.cpp b/logic/OneSixVersion.cpp
index 01bf41f4..4e2bbda5 100644
--- a/logic/OneSixVersion.cpp
+++ b/logic/OneSixVersion.cpp
@@ -151,7 +151,7 @@ std::shared_ptr<OneSixVersion> OneSixVersion::fromJson(QJsonObject root)
root.value("minimumLauncherVersion").toDouble();
// ADD MORE HERE :D
- if (launcher_ver > 0 && launcher_ver <= 9)
+ if (launcher_ver > 0 && launcher_ver <= 10)
return fromJsonV4(root, readVersion);
else
{
diff --git a/logic/auth/MojangAccount.cpp b/logic/auth/MojangAccount.cpp
index 4875e5f7..4f3839bc 100644
--- a/logic/auth/MojangAccount.cpp
+++ b/logic/auth/MojangAccount.cpp
@@ -82,6 +82,10 @@ void MojangAccount::setAccessToken(const QString& accessToken)
m_accessToken = accessToken;
}
+QString MojangAccount::sessionId() const
+{
+ return "token:" + m_accessToken + ":" + currentProfile()->id();
+}
const QList<AccountProfile> MojangAccount::profiles() const
{
diff --git a/logic/auth/MojangAccount.h b/logic/auth/MojangAccount.h
index e5684b77..062b8aa2 100644
--- a/logic/auth/MojangAccount.h
+++ b/logic/auth/MojangAccount.h
@@ -110,13 +110,18 @@ public:
* If the user has not chosen to stay logged in, this will be an empty string.
*/
QString accessToken() const;
-
+
/**
* Changes this MojangAccount's access token to the given value.
*/
void setAccessToken(const QString& token);
/**
+ * Get full session ID
+ */
+ QString sessionId() const;
+
+ /**
* Returns a list of the available account profiles.
*/
const ProfileList profiles() const;
diff --git a/logic/lists/BaseVersionList.h b/logic/lists/BaseVersionList.h
index 5ac9369b..21b44e8d 100644
--- a/logic/lists/BaseVersionList.h
+++ b/logic/lists/BaseVersionList.h
@@ -18,7 +18,6 @@
#include <QObject>
#include <QVariant>
#include <QAbstractListModel>
-#include <QSharedPointer>
#include "logic/BaseVersion.h"
diff --git a/logic/lists/ForgeVersionList.h b/logic/lists/ForgeVersionList.h
index 0d10e1f3..bf9e87b2 100644
--- a/logic/lists/ForgeVersionList.h
+++ b/logic/lists/ForgeVersionList.h
@@ -17,7 +17,6 @@
#include <QObject>
#include <QAbstractListModel>
-#include <QSharedPointer>
#include <QUrl>
#include <QNetworkReply>
diff --git a/logic/lists/InstanceList.h b/logic/lists/InstanceList.h
index c3e3561d..d08501eb 100644
--- a/logic/lists/InstanceList.h
+++ b/logic/lists/InstanceList.h
@@ -16,7 +16,6 @@
#pragma once
#include <QObject>
-#include <QSharedPointer>
#include <QAbstractListModel>
#include "categorizedsortfilterproxymodel.h"
#include <QIcon>
diff --git a/logic/lists/JavaVersionList.h b/logic/lists/JavaVersionList.h
index 4826ca0c..f816c932 100644
--- a/logic/lists/JavaVersionList.h
+++ b/logic/lists/JavaVersionList.h
@@ -17,7 +17,6 @@
#include <QObject>
#include <QAbstractListModel>
-#include <QSharedPointer>
#include "BaseVersionList.h"
#include "logic/tasks/Task.h"
diff --git a/logic/lists/MinecraftVersionList.h b/logic/lists/MinecraftVersionList.h
index 90b1ae86..82af1009 100644
--- a/logic/lists/MinecraftVersionList.h
+++ b/logic/lists/MinecraftVersionList.h
@@ -18,7 +18,6 @@
#include <QObject>
#include <QList>
#include <QSet>
-#include <QSharedPointer>
#include "BaseVersionList.h"
#include "logic/tasks/Task.h"
diff --git a/logic/net/CacheDownload.cpp b/logic/net/CacheDownload.cpp
index 4fe4e68e..873d3a2e 100644
--- a/logic/net/CacheDownload.cpp
+++ b/logic/net/CacheDownload.cpp
@@ -29,7 +29,6 @@ CacheDownload::CacheDownload(QUrl url, MetaEntryPtr entry)
m_entry = entry;
m_target_path = entry->getFullPath();
m_status = Job_NotStarted;
- m_opened_for_saving = false;
}
void CacheDownload::start()
@@ -87,7 +86,7 @@ void CacheDownload::downloadFinished()
// nothing went wrong...
m_status = Job_Finished;
- if (m_opened_for_saving)
+ if (m_output_file.isOpen())
{
// save the data to the downloadable if we aren't saving to file
m_output_file.close();
@@ -133,7 +132,7 @@ void CacheDownload::downloadFinished()
void CacheDownload::downloadReadyRead()
{
- if (!m_opened_for_saving)
+ if (!m_output_file.isOpen())
{
if (!m_output_file.open(QIODevice::WriteOnly))
{
@@ -144,7 +143,6 @@ void CacheDownload::downloadReadyRead()
emit failed(index_within_job);
return;
}
- m_opened_for_saving = true;
}
QByteArray ba = m_reply->readAll();
md5sum.addData(ba);
diff --git a/logic/net/CacheDownload.h b/logic/net/CacheDownload.h
index 2b9a5dd8..e25aecd2 100644
--- a/logic/net/CacheDownload.h
+++ b/logic/net/CacheDownload.h
@@ -26,8 +26,6 @@ class CacheDownload : public NetAction
Q_OBJECT
public:
MetaEntryPtr m_entry;
- /// is the saving file already open?
- bool m_opened_for_saving;
/// if saving to file, use the one specified in this string
QString m_target_path;
/// this is the output file, if any
diff --git a/logic/net/FileDownload.cpp b/logic/net/FileDownload.cpp
index 6b2aa66f..239af351 100644
--- a/logic/net/FileDownload.cpp
+++ b/logic/net/FileDownload.cpp
@@ -25,7 +25,6 @@ FileDownload::FileDownload(QUrl url, QString target_path) : NetAction()
m_target_path = target_path;
m_check_md5 = false;
m_status = Job_NotStarted;
- m_opened_for_saving = false;
}
void FileDownload::start()
@@ -113,7 +112,7 @@ void FileDownload::downloadFinished()
void FileDownload::downloadReadyRead()
{
- if (!m_opened_for_saving)
+ if (!m_output_file.isOpen())
{
if (!m_output_file.open(QIODevice::WriteOnly))
{
@@ -124,7 +123,6 @@ void FileDownload::downloadReadyRead()
emit failed(index_within_job);
return;
}
- m_opened_for_saving = true;
}
m_output_file.write(m_reply->readAll());
}
diff --git a/logic/net/FileDownload.h b/logic/net/FileDownload.h
index 31e0259c..58380e86 100644
--- a/logic/net/FileDownload.h
+++ b/logic/net/FileDownload.h
@@ -29,8 +29,6 @@ public:
bool m_check_md5;
/// the expected md5 checksum
QString m_expected_md5;
- /// is the saving file already open?
- bool m_opened_for_saving;
/// if saving to file, use the one specified in this string
QString m_target_path;
/// this is the output file, if any
diff --git a/logic/net/ForgeMirror.h b/logic/net/ForgeMirror.h
new file mode 100644
index 00000000..2518dffe
--- /dev/null
+++ b/logic/net/ForgeMirror.h
@@ -0,0 +1,10 @@
+#pragma once
+#include <QString>
+
+struct ForgeMirror
+{
+ QString name;
+ QString logo_url;
+ QString website_url;
+ QString mirror_url;
+}; \ No newline at end of file
diff --git a/logic/net/ForgeMirrors.cpp b/logic/net/ForgeMirrors.cpp
new file mode 100644
index 00000000..fd7eccca
--- /dev/null
+++ b/logic/net/ForgeMirrors.cpp
@@ -0,0 +1,116 @@
+#include "MultiMC.h"
+#include "ForgeMirrors.h"
+#include "logger/QsLog.h"
+#include <algorithm>
+#include <random>
+
+ForgeMirrors::ForgeMirrors(QList<ForgeXzDownloadPtr> &libs, NetJobPtr parent_job,
+ QString mirrorlist)
+{
+ m_libs = libs;
+ m_parent_job = parent_job;
+ m_url = QUrl(mirrorlist);
+ m_status = Job_NotStarted;
+}
+
+void ForgeMirrors::start()
+{
+ QLOG_INFO() << "Downloading " << m_url.toString();
+ QNetworkRequest request(m_url);
+ request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)");
+ auto worker = MMC->qnam();
+ QNetworkReply *rep = worker->get(request);
+
+ m_reply = std::shared_ptr<QNetworkReply>(rep);
+ connect(rep, SIGNAL(downloadProgress(qint64, qint64)),
+ SLOT(downloadProgress(qint64, qint64)));
+ connect(rep, SIGNAL(finished()), SLOT(downloadFinished()));
+ connect(rep, SIGNAL(error(QNetworkReply::NetworkError)),
+ SLOT(downloadError(QNetworkReply::NetworkError)));
+ connect(rep, SIGNAL(readyRead()), SLOT(downloadReadyRead()));
+}
+
+void ForgeMirrors::downloadError(QNetworkReply::NetworkError error)
+{
+ // error happened during download.
+ QLOG_ERROR() << "Error getting URL:" << m_url.toString().toLocal8Bit()
+ << "Network error: " << error;
+ m_status = Job_Failed;
+}
+
+void ForgeMirrors::downloadFinished()
+{
+ // if the download succeeded
+ if (m_status != Job_Failed)
+ {
+ // nothing went wrong... ?
+ parseMirrorList();
+ return;
+ }
+ // else the download failed, we use a fixed list
+ else
+ {
+ m_status = Job_Finished;
+ m_reply.reset();
+ deferToFixedList();
+ return;
+ }
+}
+
+void ForgeMirrors::deferToFixedList()
+{
+ m_mirrors.clear();
+ m_mirrors.append(
+ {"Minecraft Forge", "http://files.minecraftforge.net/forge_logo.png",
+ "http://files.minecraftforge.net/", "http://files.minecraftforge.net/maven/"});
+ m_mirrors.append({"Creeper Host",
+ "http://files.minecraftforge.net/forge_logo.png",
+ "https://www.creeperhost.net/link.php?id=1",
+ "http://new.creeperrepo.net/forge/maven/"});
+ injectDownloads();
+ emit succeeded(index_within_job);
+}
+
+void ForgeMirrors::parseMirrorList()
+{
+ m_status = Job_Finished;
+ auto data = m_reply->readAll();
+ m_reply.reset();
+ auto dataLines = data.split('\n');
+ for(auto line: dataLines)
+ {
+ auto elements = line.split('!');
+ if (elements.size() == 4)
+ {
+ m_mirrors.append({elements[0],elements[1],elements[2],elements[3]});
+ }
+ }
+ if(!m_mirrors.size())
+ deferToFixedList();
+ injectDownloads();
+ emit succeeded(index_within_job);
+}
+
+void ForgeMirrors::injectDownloads()
+{
+ // shuffle the mirrors randomly
+ std::random_device rd;
+ std::mt19937 rng(rd());
+ std::shuffle(m_mirrors.begin(), m_mirrors.end(), rng);
+
+ // tell parent to download the libs
+ for(auto lib: m_libs)
+ {
+ lib->setMirrors(m_mirrors);
+ m_parent_job->addNetAction(lib);
+ }
+}
+
+void ForgeMirrors::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
+{
+ emit progress(index_within_job, bytesReceived, bytesTotal);
+}
+
+void ForgeMirrors::downloadReadyRead()
+{
+}
diff --git a/logic/net/ForgeMirrors.h b/logic/net/ForgeMirrors.h
new file mode 100644
index 00000000..990e49d6
--- /dev/null
+++ b/logic/net/ForgeMirrors.h
@@ -0,0 +1,58 @@
+/* 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 "NetAction.h"
+#include "HttpMetaCache.h"
+#include "ForgeXzDownload.h"
+#include "NetJob.h"
+#include <QFile>
+#include <QTemporaryFile>
+typedef std::shared_ptr<class ForgeMirrors> ForgeMirrorsPtr;
+
+class ForgeMirrors : public NetAction
+{
+ Q_OBJECT
+public:
+ QList<ForgeXzDownloadPtr> m_libs;
+ NetJobPtr m_parent_job;
+ QList<ForgeMirror> m_mirrors;
+
+public:
+ explicit ForgeMirrors(QList<ForgeXzDownloadPtr> &libs, NetJobPtr parent_job,
+ QString mirrorlist);
+ static ForgeMirrorsPtr make(QList<ForgeXzDownloadPtr> &libs, NetJobPtr parent_job,
+ QString mirrorlist)
+ {
+ return ForgeMirrorsPtr(new ForgeMirrors(libs, parent_job, mirrorlist));
+ }
+
+protected
+slots:
+ virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
+ virtual void downloadError(QNetworkReply::NetworkError error);
+ virtual void downloadFinished();
+ virtual void downloadReadyRead();
+
+private:
+ void parseMirrorList();
+ void deferToFixedList();
+ void injectDownloads();
+
+public
+slots:
+ virtual void start();
+};
diff --git a/logic/net/ForgeXzDownload.cpp b/logic/net/ForgeXzDownload.cpp
index 6c9d7a60..f119878a 100644
--- a/logic/net/ForgeXzDownload.cpp
+++ b/logic/net/ForgeXzDownload.cpp
@@ -22,30 +22,45 @@
#include <QDateTime>
#include "logger/QsLog.h"
-ForgeXzDownload::ForgeXzDownload(QUrl url, MetaEntryPtr entry) : NetAction()
+ForgeXzDownload::ForgeXzDownload(QString relative_path, MetaEntryPtr entry) : NetAction()
{
- QString urlstr = url.toString();
- urlstr.append(".pack.xz");
- m_url = QUrl(urlstr);
m_entry = entry;
m_target_path = entry->getFullPath();
+ m_pack200_xz_file.setFileTemplate("./dl_temp.XXXXXX");
m_status = Job_NotStarted;
- m_opened_for_saving = false;
+ m_url_path = relative_path;
+}
+
+void ForgeXzDownload::setMirrors(QList<ForgeMirror> &mirrors)
+{
+ m_mirror_index = 0;
+ m_mirrors = mirrors;
+ updateUrl();
}
void ForgeXzDownload::start()
{
+ m_status = Job_InProgress;
if (!m_entry->stale)
{
+ m_status = Job_Finished;
emit succeeded(index_within_job);
return;
}
// can we actually create the real, final file?
if (!ensureFilePathExists(m_target_path))
{
+ m_status = Job_Failed;
+ emit failed(index_within_job);
+ return;
+ }
+ if (m_mirrors.empty())
+ {
+ m_status = Job_Failed;
emit failed(index_within_job);
return;
}
+
QLOG_INFO() << "Downloading " << m_url.toString();
QNetworkRequest request(m_url);
request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->etag.toLatin1());
@@ -75,14 +90,53 @@ void ForgeXzDownload::downloadError(QNetworkReply::NetworkError error)
m_status = Job_Failed;
}
+void ForgeXzDownload::failAndTryNextMirror()
+{
+ m_status = Job_Failed;
+ int next = m_mirror_index + 1;
+ if(m_mirrors.size() == next)
+ m_mirror_index = 0;
+ else
+ m_mirror_index = next;
+
+ updateUrl();
+ emit failed(index_within_job);
+}
+
+void ForgeXzDownload::updateUrl()
+{
+ QLOG_INFO() << "Updating URL for " << m_url_path;
+ for (auto possible : m_mirrors)
+ {
+ QLOG_INFO() << "Possible: " << possible.name << " : " << possible.mirror_url;
+ }
+ QString aggregate = m_mirrors[m_mirror_index].mirror_url + m_url_path + ".pack.xz";
+ m_url = QUrl(aggregate);
+}
+
void ForgeXzDownload::downloadFinished()
{
+ //TEST: defer to other possible mirrors (autofail the first one)
+ /*
+ QLOG_INFO() <<"dl " << index_within_job << " mirror " << m_mirror_index;
+ if( m_mirror_index == 0)
+ {
+ QLOG_INFO() <<"dl " << index_within_job << " AUTOFAIL";
+ m_status = Job_Failed;
+ m_pack200_xz_file.close();
+ m_pack200_xz_file.remove();
+ m_reply.reset();
+ failAndTryNextMirror();
+ return;
+ }
+ */
+
// if the download succeeded
if (m_status != Job_Failed)
{
// nothing went wrong...
m_status = Job_Finished;
- if (m_opened_for_saving)
+ if (m_pack200_xz_file.isOpen())
{
// we actually downloaded something! process and isntall it
decompressAndInstall();
@@ -90,7 +144,8 @@ void ForgeXzDownload::downloadFinished()
}
else
{
- // something bad happened
+ // something bad happened -- on the local machine!
+ m_status = Job_Failed;
m_pack200_xz_file.remove();
m_reply.reset();
emit failed(index_within_job);
@@ -100,10 +155,11 @@ void ForgeXzDownload::downloadFinished()
// else the download failed
else
{
+ m_status = Job_Failed;
m_pack200_xz_file.close();
m_pack200_xz_file.remove();
m_reply.reset();
- emit failed(index_within_job);
+ failAndTryNextMirror();
return;
}
}
@@ -111,7 +167,7 @@ void ForgeXzDownload::downloadFinished()
void ForgeXzDownload::downloadReadyRead()
{
- if (!m_opened_for_saving)
+ if (!m_pack200_xz_file.isOpen())
{
if (!m_pack200_xz_file.open())
{
@@ -122,7 +178,6 @@ void ForgeXzDownload::downloadReadyRead()
emit failed(index_within_job);
return;
}
- m_opened_for_saving = true;
}
m_pack200_xz_file.write(m_reply->readAll());
}
@@ -138,7 +193,7 @@ void ForgeXzDownload::decompressAndInstall()
// rewind the downloaded temp file
m_pack200_xz_file.seek(0);
// de-xz'd file
- QTemporaryFile pack200_file;
+ QTemporaryFile pack200_file("./dl_temp.XXXXXX");
pack200_file.open();
bool xz_success = false;
@@ -155,7 +210,7 @@ void ForgeXzDownload::decompressAndInstall()
if (s == nullptr)
{
xz_dec_end(s);
- emit failed(index_within_job);
+ failAndTryNextMirror();
return;
}
b.in = in;
@@ -180,7 +235,7 @@ void ForgeXzDownload::decompressAndInstall()
{
// msg = "Write error\n";
xz_dec_end(s);
- emit failed(index_within_job);
+ failAndTryNextMirror();
return;
}
@@ -214,42 +269,43 @@ void ForgeXzDownload::decompressAndInstall()
case XZ_MEM_ERROR:
QLOG_ERROR() << "Memory allocation failed\n";
xz_dec_end(s);
- emit failed(index_within_job);
+ failAndTryNextMirror();
return;
case XZ_MEMLIMIT_ERROR:
QLOG_ERROR() << "Memory usage limit reached\n";
xz_dec_end(s);
- emit failed(index_within_job);
+ failAndTryNextMirror();
return;
case XZ_FORMAT_ERROR:
QLOG_ERROR() << "Not a .xz file\n";
xz_dec_end(s);
- emit failed(index_within_job);
+ failAndTryNextMirror();
return;
case XZ_OPTIONS_ERROR:
QLOG_ERROR() << "Unsupported options in the .xz headers\n";
xz_dec_end(s);
- emit failed(index_within_job);
+ failAndTryNextMirror();
return;
case XZ_DATA_ERROR:
case XZ_BUF_ERROR:
QLOG_ERROR() << "File is corrupt\n";
xz_dec_end(s);
- emit failed(index_within_job);
+ failAndTryNextMirror();
return;
default:
QLOG_ERROR() << "Bug!\n";
xz_dec_end(s);
- emit failed(index_within_job);
+ failAndTryNextMirror();
return;
}
}
}
+ m_pack200_xz_file.remove();
// revert pack200
pack200_file.close();
@@ -260,20 +316,22 @@ void ForgeXzDownload::decompressAndInstall()
}
catch (std::runtime_error &err)
{
+ m_status = Job_Failed;
QLOG_ERROR() << "Error unpacking " << pack_name.toUtf8() << " : " << err.what();
QFile f(m_target_path);
if (f.exists())
f.remove();
- emit failed(index_within_job);
+ failAndTryNextMirror();
return;
}
+ pack200_file.remove();
QFile jar_file(m_target_path);
if (!jar_file.open(QIODevice::ReadOnly))
{
jar_file.remove();
- emit failed(index_within_job);
+ failAndTryNextMirror();
return;
}
m_entry->md5sum = QCryptographicHash::hash(jar_file.readAll(), QCryptographicHash::Md5)
diff --git a/logic/net/ForgeXzDownload.h b/logic/net/ForgeXzDownload.h
index 9f1bb029..990f91f0 100644
--- a/logic/net/ForgeXzDownload.h
+++ b/logic/net/ForgeXzDownload.h
@@ -19,6 +19,8 @@
#include "HttpMetaCache.h"
#include <QFile>
#include <QTemporaryFile>
+#include "ForgeMirror.h"
+
typedef std::shared_ptr<class ForgeXzDownload> ForgeXzDownloadPtr;
class ForgeXzDownload : public NetAction
@@ -26,19 +28,24 @@ class ForgeXzDownload : public NetAction
Q_OBJECT
public:
MetaEntryPtr m_entry;
- /// is the saving file already open?
- bool m_opened_for_saving;
/// if saving to file, use the one specified in this string
QString m_target_path;
/// this is the output file, if any
QTemporaryFile m_pack200_xz_file;
+ /// mirror index (NOT OPTICS, I SWEAR)
+ int m_mirror_index = 0;
+ /// list of mirrors to use. Mirror has the url base
+ QList<ForgeMirror> m_mirrors;
+ /// path relative to the mirror base
+ QString m_url_path;
public:
- explicit ForgeXzDownload(QUrl url, MetaEntryPtr entry);
- static ForgeXzDownloadPtr make(QUrl url, MetaEntryPtr entry)
+ explicit ForgeXzDownload(QString relative_path, MetaEntryPtr entry);
+ static ForgeXzDownloadPtr make(QString relative_path, MetaEntryPtr entry)
{
- return ForgeXzDownloadPtr(new ForgeXzDownload(url, entry));
+ return ForgeXzDownloadPtr(new ForgeXzDownload(relative_path, entry));
}
+ void setMirrors(QList<ForgeMirror> & mirrors);
protected
slots:
@@ -53,4 +60,6 @@ slots:
private:
void decompressAndInstall();
+ void failAndTryNextMirror();
+ void updateUrl();
};
diff --git a/logic/net/HttpMetaCache.h b/logic/net/HttpMetaCache.h
index e91d2684..08b39fe2 100644
--- a/logic/net/HttpMetaCache.h
+++ b/logic/net/HttpMetaCache.h
@@ -15,7 +15,6 @@
#pragma once
#include <QString>
-#include <QSharedPointer>
#include <QMap>
#include <qtimer.h>
diff --git a/logic/net/LoginTask.cpp b/logic/net/LoginTask.cpp
index 4a789bb4..5607447e 100644
--- a/logic/net/LoginTask.cpp
+++ b/logic/net/LoginTask.cpp
@@ -27,7 +27,8 @@
#include <QJsonParseError>
#include <QJsonObject>
-LoginTask::LoginTask(const UserInfo &uInfo, QObject *parent) : Task(parent), uInfo(uInfo)
+LoginTask::LoginTask(const PasswordLogin &loginInfo, QObject *parent)
+ : Task(parent), loginInfo(loginInfo)
{
}
@@ -49,8 +50,8 @@ void LoginTask::legacyLogin()
"application/x-www-form-urlencoded");
QUrlQuery params;
- params.addQueryItem("user", uInfo.username);
- params.addQueryItem("password", uInfo.password);
+ params.addQueryItem("user", loginInfo.username);
+ params.addQueryItem("password", loginInfo.password);
params.addQueryItem("version", "13");
netReply = worker->post(netRequest, params.query(QUrl::EncodeSpaces).toUtf8());
@@ -221,8 +222,8 @@ void LoginTask::yggdrasilLogin()
agent.insert("name", QString("Minecraft"));
agent.insert("version", QJsonValue(1));
root.insert("agent", agent);
- root.insert("username", uInfo.username);
- root.insert("password", uInfo.password);
+ root.insert("username", loginInfo.username);
+ root.insert("password", loginInfo.password);
root.insert("clientToken", clientToken);
QJsonDocument requestDoc(root);
netReply = worker->post(netRequest, requestDoc.toJson());
@@ -247,6 +248,7 @@ void LoginTask::yggdrasilLogin()
void LoginTask::parseYggdrasilReply(QByteArray data)
{
QJsonParseError jsonError;
+ QLOG_DEBUG() << data;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
if (jsonError.error != QJsonParseError::NoError)
{
@@ -273,6 +275,7 @@ void LoginTask::parseYggdrasilReply(QByteArray data)
playerID = selectedProfileO.value("id").toString();
playerName = selectedProfileO.value("name").toString();
}
+
QString sessionID = "token:" + accessToken + ":" + playerID;
/*
struct LoginResponse
@@ -285,6 +288,6 @@ void LoginTask::parseYggdrasilReply(QByteArray data)
};
*/
- result = {uInfo.username, sessionID, playerName, playerID, accessToken};
+ result = {loginInfo.username, sessionID, playerName, playerID, accessToken};
emitSucceeded();
}
diff --git a/logic/net/LoginTask.h b/logic/net/LoginTask.h
index 26ac0808..fe4e6d2f 100644
--- a/logic/net/LoginTask.h
+++ b/logic/net/LoginTask.h
@@ -16,14 +16,20 @@
#pragma once
#include "logic/tasks/Task.h"
-#include <QSharedPointer>
+#include <QMap>
-struct UserInfo
+struct PasswordLogin
{
QString username;
QString password;
};
+struct User
+{
+ QString id;
+ QMap<QString, QString> properties;
+};
+
struct LoginResponse
{
QString username;
@@ -31,6 +37,7 @@ struct LoginResponse
QString player_name;
QString player_id;
QString access_token;
+ User user; // FIXME: no idea what this really is yet. anything relevant?
};
class QNetworkReply;
@@ -39,7 +46,7 @@ class LoginTask : public Task
{
Q_OBJECT
public:
- explicit LoginTask(const UserInfo &uInfo, QObject *parent = 0);
+ explicit LoginTask(const PasswordLogin &loginInfo, QObject *parent = 0);
LoginResponse getResult()
{
return result;
@@ -65,5 +72,5 @@ protected:
LoginResponse result;
QNetworkReply *netReply;
- UserInfo uInfo;
+ PasswordLogin loginInfo;
};
diff --git a/logic/net/NetJob.cpp b/logic/net/NetJob.cpp
index 21c6d3f7..333cdcbf 100644
--- a/logic/net/NetJob.cpp
+++ b/logic/net/NetJob.cpp
@@ -89,6 +89,7 @@ void NetJob::partProgress(int index, qint64 bytesReceived, qint64 bytesTotal)
void NetJob::start()
{
QLOG_INFO() << m_job_name.toLocal8Bit() << " started.";
+ m_running = true;
for (auto iter : downloads)
{
connect(iter.get(), SIGNAL(succeeded(int)), SLOT(partSucceeded(int)));
diff --git a/logic/net/NetJob.h b/logic/net/NetJob.h
index c5c0d00c..021a1550 100644
--- a/logic/net/NetJob.h
+++ b/logic/net/NetJob.h
@@ -40,6 +40,16 @@ public:
downloads.append(action);
parts_progress.append(part_info());
total_progress++;
+ // if this is already running, the action needs to be started right away!
+ if (isRunning())
+ {
+ emit progress(current_progress, total_progress);
+ connect(base.get(), SIGNAL(succeeded(int)), SLOT(partSucceeded(int)));
+ connect(base.get(), SIGNAL(failed(int)), SLOT(partFailed(int)));
+ connect(base.get(), SIGNAL(progress(int, qint64, qint64)),
+ SLOT(partProgress(int, qint64, qint64)));
+ base->start();
+ }
return true;
}
diff --git a/package/linux/MultiMC b/package/linux/MultiMC
index 6e77a632..a2ef0c81 100755
--- a/package/linux/MultiMC
+++ b/package/linux/MultiMC
@@ -1,12 +1,18 @@
-#!/bin/sh
+#!/bin/bash
# Basic start script for running MultiMC with the libs packaged with it.
-MMC_DIR="$( cd "$( dirname "$0" )" && pwd )"
+MMC_DIR=`dirname "$0"`
cd "${MMC_DIR}"
echo "MultiMC Dir: ${MMC_DIR}"
+# Set up env
export LD_LIBRARY_PATH="${MMC_DIR}/bin":$LD_LIBRARY_PATH
export QT_PLUGIN_PATH="${MMC_DIR}/plugins"
export QT_FONTPATH="${MMC_DIR}/fonts"
-exec ${MMC_DIR}/bin/MultiMC -d ${MMC_DIR} $@
+
+# Just to be sure...
+chmod +x "${MMC_DIR}/bin/MultiMC"
+
+# run MultiMC
+"${MMC_DIR}/bin/MultiMC" -d "${MMC_DIR}" $@