Merge branch 'release-0.1'

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

View File

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

View File

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

View File

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

View File

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

17
changelog.yaml Normal file
View File

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

View File

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

View File

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

View File

@ -5,7 +5,6 @@ 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(SRC
MultiMCLauncher.java
@ -19,3 +18,5 @@ set(SRC
)
add_jar(MultiMCLauncher ${SRC})
INSTALL_JAR(MultiMCLauncher "${BINARY_DEST_DIR}/jars")

View File

@ -1,6 +1,8 @@
<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>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>526</width>
<height>639</height>
<height>723</height>
</rect>
</property>
<property name="sizePolicy">
@ -106,6 +106,9 @@
<property name="text">
<string>No channel selected.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
@ -424,6 +427,165 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="networkTab">
<property name="toolTip">
<string>Network settings.</string>
</property>
<attribute name="title">
<string>Network</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QGroupBox" name="proxySettingsBox">
<property name="title">
<string>Proxy</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QGroupBox" name="proxyTypeBox">
<property name="title">
<string>Type</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QRadioButton" name="proxyDefaultBtn">
<property name="toolTip">
<string>Uses your system's default proxy settings.</string>
</property>
<property name="text">
<string>Default</string>
</property>
<attribute name="buttonGroup">
<string notr="true">proxyGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="proxyNoneBtn">
<property name="text">
<string>None</string>
</property>
<attribute name="buttonGroup">
<string notr="true">proxyGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="proxySOCKS5Btn">
<property name="text">
<string>SOCKS5</string>
</property>
<attribute name="buttonGroup">
<string notr="true">proxyGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="proxyHTTPBtn">
<property name="text">
<string>HTTP</string>
</property>
<attribute name="buttonGroup">
<string notr="true">proxyGroup</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="proxyAddrBox">
<property name="title">
<string>Address and Port</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="proxyAddrEdit">
<property name="placeholderText">
<string>127.0.0.1</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="proxyPortEdit">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::PlusMinus</enum>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>8080</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="proxyAuthBox">
<property name="title">
<string>Authentication</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="1">
<widget class="QLineEdit" name="proxyUserEdit"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="proxyUsernameLabel">
<property name="text">
<string>Username:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="proxyPasswordLabel">
<property name="text">
<string>Password:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="proxyPassEdit">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="proxyPlainTextWarningLabel">
<property name="text">
<string>Note: Proxy username and password are stored in plain text inside MultiMC's configuration file!</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="javaTab">
<attribute name="title">
<string>Java</string>
@ -736,6 +898,7 @@
</connection>
</connections>
<buttongroups>
<buttongroup name="proxyGroup"/>
<buttongroup name="sortingModeGroup"/>
</buttongroups>
</ui>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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