summaryrefslogtreecommitdiffstats
path: root/application
diff options
context:
space:
mode:
Diffstat (limited to 'application')
-rw-r--r--application/CMakeLists.txt226
-rw-r--r--application/ColumnResizer.cpp2
-rw-r--r--application/GuiUtil.cpp23
-rw-r--r--application/GuiUtil.h1
-rw-r--r--application/HoeDown.h2
-rw-r--r--application/InstancePageProvider.h16
-rw-r--r--application/InstanceWindow.cpp30
-rw-r--r--application/InstanceWindow.h7
-rw-r--r--application/LaunchController.cpp16
-rw-r--r--application/MainWindow.cpp787
-rw-r--r--application/MainWindow.h21
-rw-r--r--application/MultiMC.cpp879
-rw-r--r--application/MultiMC.h28
-rw-r--r--application/VersionProxyModel.cpp18
-rw-r--r--application/VersionProxyModel.h1
-rw-r--r--application/dialogs/AboutDialog.cpp4
-rw-r--r--application/dialogs/AboutDialog.h2
-rw-r--r--application/dialogs/AboutDialog.ui4
-rw-r--r--application/dialogs/ChooseFtbPackDialog.cpp64
-rw-r--r--application/dialogs/ChooseFtbPackDialog.h32
-rw-r--r--application/dialogs/ChooseFtbPackDialog.ui163
-rw-r--r--application/dialogs/CopyInstanceDialog.cpp2
-rw-r--r--application/dialogs/CopyInstanceDialog.h2
-rw-r--r--application/dialogs/CustomMessageBox.cpp2
-rw-r--r--application/dialogs/CustomMessageBox.h2
-rw-r--r--application/dialogs/EditAccountDialog.cpp2
-rw-r--r--application/dialogs/EditAccountDialog.h2
-rw-r--r--application/dialogs/ExportInstanceDialog.cpp6
-rw-r--r--application/dialogs/ExportInstanceDialog.h2
-rw-r--r--application/dialogs/IconPickerDialog.cpp22
-rw-r--r--application/dialogs/IconPickerDialog.h3
-rw-r--r--application/dialogs/LoginDialog.cpp2
-rw-r--r--application/dialogs/LoginDialog.h2
-rw-r--r--application/dialogs/NewComponentDialog.cpp106
-rw-r--r--application/dialogs/NewComponentDialog.h48
-rw-r--r--application/dialogs/NewComponentDialog.ui101
-rw-r--r--application/dialogs/NewInstanceDialog.cpp65
-rw-r--r--application/dialogs/NewInstanceDialog.h16
-rw-r--r--application/dialogs/NewInstanceDialog.ui129
-rw-r--r--application/dialogs/NotificationDialog.cpp1
-rw-r--r--application/dialogs/ProfileSelectDialog.cpp2
-rw-r--r--application/dialogs/ProfileSelectDialog.h2
-rw-r--r--application/dialogs/ProgressDialog.cpp4
-rw-r--r--application/dialogs/ProgressDialog.h2
-rw-r--r--application/dialogs/SkinUploadDialog.cpp61
-rw-r--r--application/dialogs/UpdateDialog.cpp6
-rw-r--r--application/dialogs/UpdateDialog.h2
-rw-r--r--application/dialogs/VersionSelectDialog.cpp8
-rw-r--r--application/dialogs/VersionSelectDialog.h5
-rw-r--r--application/groupview/GroupView.cpp67
-rw-r--r--application/groupview/GroupView.h4
-rw-r--r--application/groupview/GroupedProxyModel.cpp2
-rw-r--r--application/groupview/GroupedProxyModel.h2
-rw-r--r--application/groupview/InstanceDelegate.cpp2
-rw-r--r--application/groupview/InstanceDelegate.h2
-rw-r--r--application/groupview/VisualGroup.cpp2
-rw-r--r--application/groupview/VisualGroup.h2
-rw-r--r--application/install_prereqs.cmake.in2
-rw-r--r--application/main.cpp1
-rwxr-xr-xapplication/package/linux/multimc.desktop3
-rw-r--r--application/pagedialog/PageDialog.cpp2
-rw-r--r--application/pagedialog/PageDialog.h2
-rw-r--r--application/pages/BasePage.h10
-rw-r--r--application/pages/BasePageContainer.h1
-rw-r--r--application/pages/BasePageProvider.h2
-rw-r--r--application/pages/InstanceSettingsPage.cpp57
-rw-r--r--application/pages/InstanceSettingsPage.h2
-rw-r--r--application/pages/InstanceSettingsPage.ui109
-rw-r--r--application/pages/LegacyJarModPage.cpp162
-rw-r--r--application/pages/LegacyJarModPage.h76
-rw-r--r--application/pages/LegacyJarModPage.ui162
-rw-r--r--application/pages/LegacyUpgradePage.cpp24
-rw-r--r--application/pages/LegacyUpgradePage.h14
-rw-r--r--application/pages/LegacyUpgradePage.ui12
-rw-r--r--application/pages/LogPage.cpp65
-rw-r--r--application/pages/LogPage.h11
-rw-r--r--application/pages/ModFolderPage.cpp13
-rw-r--r--application/pages/ModFolderPage.h4
-rw-r--r--application/pages/NotesPage.h2
-rw-r--r--application/pages/OtherLogsPage.cpp68
-rw-r--r--application/pages/OtherLogsPage.h7
-rw-r--r--application/pages/OtherLogsPage.ui76
-rw-r--r--application/pages/ScreenshotsPage.cpp2
-rw-r--r--application/pages/ScreenshotsPage.h2
-rw-r--r--application/pages/ScreenshotsPage.ui2
-rw-r--r--application/pages/VersionPage.cpp203
-rw-r--r--application/pages/VersionPage.h24
-rw-r--r--application/pages/VersionPage.ui34
-rw-r--r--application/pages/WorldListPage.cpp2
-rw-r--r--application/pages/WorldListPage.h4
-rw-r--r--application/pages/global/AccountListPage.cpp2
-rw-r--r--application/pages/global/AccountListPage.h2
-rw-r--r--application/pages/global/CustomCommandsPage.cpp50
-rw-r--r--application/pages/global/CustomCommandsPage.h55
-rw-r--r--application/pages/global/ExternalToolsPage.cpp6
-rw-r--r--application/pages/global/ExternalToolsPage.h2
-rw-r--r--application/pages/global/ExternalToolsPage.ui6
-rw-r--r--application/pages/global/JavaPage.cpp52
-rw-r--r--application/pages/global/JavaPage.h2
-rw-r--r--application/pages/global/JavaPage.ui79
-rw-r--r--application/pages/global/MinecraftPage.cpp2
-rw-r--r--application/pages/global/MinecraftPage.h2
-rw-r--r--application/pages/global/MultiMCPage.cpp86
-rw-r--r--application/pages/global/MultiMCPage.h6
-rw-r--r--application/pages/global/MultiMCPage.ui109
-rw-r--r--application/pages/global/PackagesPage.cpp25
-rw-r--r--application/pages/global/PackagesPage.h2
-rw-r--r--application/pages/global/PasteEEPage.cpp10
-rw-r--r--application/pages/global/PasteEEPage.h2
-rw-r--r--application/pages/global/PasteEEPage.ui16
-rw-r--r--application/pages/global/ProxyPage.cpp2
-rw-r--r--application/pages/global/ProxyPage.h2
-rw-r--r--application/resources/MultiMC.icnsbin437319 -> 782703 bytes
-rw-r--r--application/resources/MultiMC.icobin76126 -> 85182 bytes
-rw-r--r--application/resources/OSX/OSX.qrc2
-rw-r--r--application/resources/OSX/scalable/help.svg51
-rw-r--r--application/resources/OSX/scalable/worlds.svg58
-rw-r--r--application/resources/flat/flat.qrc44
-rw-r--r--application/resources/flat/index.theme11
-rw-r--r--application/resources/flat/scalable/about.svg3
-rw-r--r--application/resources/flat/scalable/accounts.svg3
-rw-r--r--application/resources/flat/scalable/bug.svg3
-rw-r--r--application/resources/flat/scalable/cat.svg3
-rw-r--r--application/resources/flat/scalable/centralmods.svg3
-rw-r--r--application/resources/flat/scalable/checkupdate.svg3
-rw-r--r--application/resources/flat/scalable/copy.svg3
-rw-r--r--application/resources/flat/scalable/coremods.svg3
-rw-r--r--application/resources/flat/scalable/discord.svg4
-rw-r--r--application/resources/flat/scalable/externaltools.svg3
-rw-r--r--application/resources/flat/scalable/help.svg17
-rw-r--r--application/resources/flat/scalable/instance-settings.svg3
-rw-r--r--application/resources/flat/scalable/jarmods.svg3
-rw-r--r--application/resources/flat/scalable/java.svg3
-rw-r--r--application/resources/flat/scalable/loadermods.svg3
-rw-r--r--application/resources/flat/scalable/log.svg3
-rw-r--r--application/resources/flat/scalable/minecraft.svg3
-rw-r--r--application/resources/flat/scalable/multimc.svg3
-rw-r--r--application/resources/flat/scalable/new.svg3
-rw-r--r--application/resources/flat/scalable/news.svg3
-rw-r--r--application/resources/flat/scalable/notes.svg3
-rw-r--r--application/resources/flat/scalable/packages.svg3
-rw-r--r--application/resources/flat/scalable/patreon.svg3
-rw-r--r--application/resources/flat/scalable/proxy.svg3
-rw-r--r--application/resources/flat/scalable/quickmods.svg3
-rw-r--r--application/resources/flat/scalable/reddit-alien.svg3
-rw-r--r--application/resources/flat/scalable/refresh.svg3
-rw-r--r--application/resources/flat/scalable/resourcepacks.svg3
-rw-r--r--application/resources/flat/scalable/screenshot-placeholder.svg3
-rw-r--r--application/resources/flat/scalable/screenshots.svg3
-rw-r--r--application/resources/flat/scalable/settings.svg3
-rw-r--r--application/resources/flat/scalable/star.svg3
-rw-r--r--application/resources/flat/scalable/status-bad.svg3
-rw-r--r--application/resources/flat/scalable/status-good.svg3
-rw-r--r--application/resources/flat/scalable/status-running.svg3
-rw-r--r--application/resources/flat/scalable/status-yellow.svg3
-rw-r--r--application/resources/flat/scalable/viewfolder.svg3
-rw-r--r--application/resources/flat/scalable/worlds.svg3
-rw-r--r--application/resources/iOS/iOS.qrc2
-rw-r--r--application/resources/iOS/scalable/help.svg38
-rw-r--r--application/resources/iOS/scalable/worlds.svg44
-rw-r--r--application/resources/multimc/128x128/instances/infinity.pngbin9237 -> 15151 bytes
-rw-r--r--application/resources/multimc/multimc.qrc8
-rw-r--r--application/resources/multimc/scalable/custom-commands.svg338
-rw-r--r--application/resources/multimc/scalable/logo.svg353
-rw-r--r--application/resources/multimc/scalable/multimc.svg2036
-rw-r--r--application/resources/pe_blue/pe_blue.qrc2
-rw-r--r--application/resources/pe_blue/scalable/help.svg40
-rw-r--r--application/resources/pe_blue/scalable/worlds.svg63
-rw-r--r--application/resources/pe_colored/pe_colored.qrc2
-rw-r--r--application/resources/pe_colored/scalable/help.svg46
-rw-r--r--application/resources/pe_colored/scalable/worlds.svg50
-rw-r--r--application/resources/pe_dark/pe_dark.qrc2
-rw-r--r--application/resources/pe_dark/scalable/help.svg34
-rw-r--r--application/resources/pe_dark/scalable/worlds.svg63
-rw-r--r--application/resources/pe_light/pe_light.qrc2
-rw-r--r--application/resources/pe_light/scalable/help.svg36
-rw-r--r--application/resources/pe_light/scalable/worlds.svg64
-rw-r--r--application/resources/sources/multimc-discord.svg265
-rw-r--r--application/setupwizard/JavaWizardPage.cpp393
-rw-r--r--application/setupwizard/JavaWizardPage.h64
-rw-r--r--application/setupwizard/SetupWizard.h2
-rw-r--r--application/themes/SystemTheme.cpp4
-rw-r--r--application/widgets/CustomCommands.cpp48
-rw-r--r--application/widgets/CustomCommands.h43
-rw-r--r--application/widgets/CustomCommands.ui98
-rw-r--r--application/widgets/FtbModpackListItem.cpp8
-rw-r--r--application/widgets/FtbModpackListItem.h15
-rw-r--r--application/widgets/JavaSettingsWidget.cpp428
-rw-r--r--application/widgets/JavaSettingsWidget.h102
-rw-r--r--application/widgets/LabeledToolButton.cpp33
-rw-r--r--application/widgets/LabeledToolButton.h5
-rw-r--r--application/widgets/MCModInfoFrame.cpp2
-rw-r--r--application/widgets/MCModInfoFrame.h2
-rw-r--r--application/widgets/ModListView.cpp2
-rw-r--r--application/widgets/ModListView.h2
-rw-r--r--application/widgets/PageContainer.cpp2
-rw-r--r--application/widgets/PageContainer.h17
-rw-r--r--application/widgets/PageContainer_p.h2
-rw-r--r--application/widgets/ProgressWidget.cpp4
-rw-r--r--application/widgets/ServerStatus.cpp10
-rw-r--r--application/widgets/VersionListView.cpp2
-rw-r--r--application/widgets/VersionListView.h2
-rw-r--r--application/widgets/VersionSelectWidget.cpp25
-rw-r--r--application/widgets/VersionSelectWidget.h6
204 files changed, 5386 insertions, 4414 deletions
diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt
index 5d3a964d..da9a42c6 100644
--- a/application/CMakeLists.txt
+++ b/application/CMakeLists.txt
@@ -1,44 +1,6 @@
project(application)
-######## Set URLs ########
-set(MultiMC_NEWS_RSS_URL "http://multimc.org/rss.xml" CACHE STRING "URL to fetch MultiMC's news RSS feed from.")
-
-######## Set version numbers ########
-set(MultiMC_VERSION_MAJOR 0)
-set(MultiMC_VERSION_MINOR 6)
-set(MultiMC_VERSION_HOTFIX 0)
-
-# Build number
-set(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
-
-# 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.")
-
-# Channel list URL
-set(MultiMC_CHANLIST_URL "" CACHE STRING "URL for the channel list.")
-
-# Notification URL
-set(MultiMC_NOTIFICATION_URL "" CACHE STRING "URL for checking for notifications.")
-
-# paste.ee API key
-set(MultiMC_PASTE_EE_API_KEY "" CACHE STRING "API key you can get from paste.ee when you register an account")
-
-# Google analytics ID
-set(MultiMC_ANALYTICS_ID "" CACHE STRING "ID you can get from Google analytics")
-
-#### Check the current Git commit and branch
-include(GetGitRevisionDescription)
-get_git_head_revision(MultiMC_GIT_REFSPEC MultiMC_GIT_COMMIT)
-
-message(STATUS "Git commit: ${MultiMC_GIT_COMMIT}")
-message(STATUS "Git refspec: ${MultiMC_GIT_REFSPEC}")
-
-set(MultiMC_RELEASE_VERSION_NAME "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_HOTFIX}")
-
-#### Custom target to just print the version.
-add_custom_target(version echo "Version: ${MultiMC_RELEASE_VERSION_NAME}")
-
-######## Configure header ########
+######## Configure the file with build properties ########
configure_file("${PROJECT_SOURCE_DIR}/BuildConfig.cpp.in" "${PROJECT_BINARY_DIR}/BuildConfig.cpp")
################################ FILES ################################
@@ -131,8 +93,6 @@ SET(MULTIMC_SOURCES
pages/ScreenshotsPage.h
pages/OtherLogsPage.cpp
pages/OtherLogsPage.h
- pages/LegacyJarModPage.cpp
- pages/LegacyJarModPage.h
pages/LegacyUpgradePage.cpp
pages/LegacyUpgradePage.h
pages/WorldListPage.cpp
@@ -141,6 +101,8 @@ SET(MULTIMC_SOURCES
# GUI - global settings pages
pages/global/AccountListPage.cpp
pages/global/AccountListPage.h
+ pages/global/CustomCommandsPage.cpp
+ pages/global/CustomCommandsPage.h
pages/global/ExternalToolsPage.cpp
pages/global/ExternalToolsPage.h
pages/global/JavaPage.cpp
@@ -175,6 +137,8 @@ SET(MULTIMC_SOURCES
dialogs/LoginDialog.h
dialogs/ModEditDialogCommon.cpp
dialogs/ModEditDialogCommon.h
+ dialogs/NewComponentDialog.cpp
+ dialogs/NewComponentDialog.h
dialogs/NewInstanceDialog.cpp
dialogs/NewInstanceDialog.h
dialogs/NotificationDialog.cpp
@@ -189,14 +153,21 @@ SET(MULTIMC_SOURCES
dialogs/VersionSelectDialog.h
dialogs/SkinUploadDialog.cpp
dialogs/SkinUploadDialog.h
+ dialogs/ChooseFtbPackDialog.cpp
+ dialogs/ChooseFtbPackDialog.h
+
# GUI - widgets
widgets/Common.cpp
widgets/Common.h
+ widgets/CustomCommands.cpp
+ widgets/CustomCommands.h
widgets/FocusLineEdit.cpp
widgets/FocusLineEdit.h
widgets/IconLabel.cpp
widgets/IconLabel.h
+ widgets/JavaSettingsWidget.cpp
+ widgets/JavaSettingsWidget.h
widgets/LabeledToolButton.cpp
widgets/LabeledToolButton.h
widgets/LineSeparator.cpp
@@ -218,7 +189,8 @@ SET(MULTIMC_SOURCES
widgets/VersionSelectWidget.h
widgets/ProgressWidget.h
widgets/ProgressWidget.cpp
-
+ widgets/FtbModpackListItem.h
+ widgets/FtbModpackListItem.cpp
# GUI - instance group view
groupview/GroupedProxyModel.cpp
@@ -233,7 +205,7 @@ SET(MULTIMC_SOURCES
######## UIs ########
SET(MULTIMC_UIS
- # Option pages
+ # Instance pages
pages/VersionPage.ui
pages/ModFolderPage.ui
pages/LogPage.ui
@@ -241,7 +213,6 @@ SET(MULTIMC_UIS
pages/NotesPage.ui
pages/ScreenshotsPage.ui
pages/OtherLogsPage.ui
- pages/LegacyJarModPage.ui
pages/LegacyUpgradePage.ui
pages/WorldListPage.ui
@@ -257,6 +228,7 @@ SET(MULTIMC_UIS
# Dialogs
dialogs/CopyInstanceDialog.ui
+ dialogs/NewComponentDialog.ui
dialogs/NewInstanceDialog.ui
dialogs/AboutDialog.ui
dialogs/ProgressDialog.ui
@@ -268,8 +240,10 @@ SET(MULTIMC_UIS
dialogs/UpdateDialog.ui
dialogs/NotificationDialog.ui
dialogs/SkinUploadDialog.ui
+ dialogs/ChooseFtbPackDialog.ui
# Widgets/other
+ widgets/CustomCommands.ui
widgets/MCModInfoFrame.ui
)
@@ -282,6 +256,7 @@ set(MULTIMC_QRCS
resources/pe_blue/pe_blue.qrc
resources/OSX/OSX.qrc
resources/iOS/iOS.qrc
+ resources/flat/flat.qrc
resources/documents/documents.qrc
)
@@ -297,167 +272,26 @@ qt5_add_resources(MULTIMC_RESOURCES ${MULTIMC_QRCS})
# Add executable
add_executable(MultiMC MACOSX_BUNDLE WIN32 ${MULTIMC_SOURCES} ${MULTIMC_UI} ${MULTIMC_RESOURCES} ${MULTIMC_RCS})
target_link_libraries(MultiMC MultiMC_gui ${QUAZIP_LIBRARIES} hoedown MultiMC_rainbow LocalPeer ganalytics)
-
-################################ INSTALLATION AND PACKAGING ################################
-
-######## Packaging/install paths setup ########
-
-# How to install the build results
-set(MultiMC_LAYOUT "auto" CACHE STRING "The layout for MultiMC installation (auto, win-bundle, lin-bundle, lin-nodeps, lin-system, mac-bundle)")
-set_property(CACHE MultiMC_LAYOUT PROPERTY STRINGS auto win-bundle lin-bundle lin-nodeps lin-system mac-bundle)
-
-if(MultiMC_LAYOUT STREQUAL "auto")
- if(UNIX AND APPLE)
- set(MultiMC_LAYOUT_REAL "mac-bundle")
- elseif(UNIX)
- set(MultiMC_LAYOUT_REAL "lin-bundle")
- elseif(WIN32)
- set(MultiMC_LAYOUT_REAL "win-bundle")
- else()
- message(FATAL_ERROR "Cannot choose a sensible install layout for your platform.")
- endif()
-else()
- set(MultiMC_LAYOUT_REAL ${MultiMC_LAYOUT})
+if(DEFINED MultiMC_APP_BINARY_NAME)
+ set_target_properties(MultiMC PROPERTIES OUTPUT_NAME "${MultiMC_APP_BINARY_NAME}")
endif()
-
-if(MultiMC_LAYOUT_REAL STREQUAL "mac-bundle")
- set(BINARY_DEST_DIR "MultiMC.app/Contents/MacOS")
- set(LIBRARY_DEST_DIR "MultiMC.app/Contents/MacOS")
- set(PLUGIN_DEST_DIR "MultiMC.app/Contents/MacOS")
- set(RESOURCES_DEST_DIR "MultiMC.app/Contents/Resources")
- set(JARS_DEST_DIR "MultiMC.app/Contents/MacOS")
-
- set(BUNDLE_DEST_DIR ".")
-
- # Apps to bundle
- set(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app")
-
- # Mac bundle settings
- 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_HOTFIX}.${MultiMC_VERSION_BUILD}")
- set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_HOTFIX}.${MultiMC_VERSION_BUILD}")
- set(MACOSX_BUNDLE_LONG_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_HOTFIX}.${MultiMC_VERSION_BUILD}")
- set(MACOSX_BUNDLE_ICON_FILE MultiMC.icns)
- set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2015-2017 MultiMC Contributors")
-
- # directories to look for dependencies
- set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
-
- # install as bundle
- set(INSTALL_BUNDLE "full")
-
- # Add the icon
- install(FILES resources/MultiMC.icns DESTINATION ${RESOURCES_DEST_DIR})
-
-elseif(MultiMC_LAYOUT_REAL STREQUAL "lin-bundle")
- set(BINARY_DEST_DIR "bin")
- set(LIBRARY_DEST_DIR "bin")
- set(PLUGIN_DEST_DIR "plugins")
- set(BUNDLE_DEST_DIR ".")
- set(RESOURCES_DEST_DIR ".")
- set(JARS_DEST_DIR "bin")
-
- # Apps to bundle
- set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC")
-
- # directories to look for dependencies
- set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
-
- # install as bundle
- set(INSTALL_BUNDLE "full")
-
- # Set RPATH
- SET_TARGET_PROPERTIES(MultiMC PROPERTIES INSTALL_RPATH "$ORIGIN/")
-
- # Install basic runner script
- install(PROGRAMS package/linux/MultiMC DESTINATION ${BUNDLE_DEST_DIR})
-
-elseif(MultiMC_LAYOUT_REAL STREQUAL "lin-nodeps")
- set(BINARY_DEST_DIR "bin")
- set(LIBRARY_DEST_DIR "bin")
- set(PLUGIN_DEST_DIR "plugins")
- set(BUNDLE_DEST_DIR ".")
- set(RESOURCES_DEST_DIR ".")
- set(JARS_DEST_DIR "bin")
-
- # install as bundle with no dependencies included
- set(INSTALL_BUNDLE "nodeps")
-
- # Set RPATH
- SET_TARGET_PROPERTIES(MultiMC PROPERTIES INSTALL_RPATH "$ORIGIN/")
-
- # Install basic runner script
- install(PROGRAMS package/linux/MultiMC DESTINATION ${BUNDLE_DEST_DIR})
-
-elseif(MultiMC_LAYOUT_REAL STREQUAL "lin-system")
- set(MultiMC_BINARY_DEST_DIR "usr/bin" CACHE STRING "Relative path from packaging root to the binary directory")
- set(MultiMC_LIBRARY_DEST_DIR "usr/lib" CACHE STRING "Relative path from packaging root to the library directory")
- set(MultiMC_SHARE_DEST_DIR "usr/share/multimc" CACHE STRING "Relative path from packaging root to the shared data directory")
- set(MultiMC_APP_BINARY_NAME "multimc" CACHE STRING "Name of the MultiMC binary for the purposes of linux packaging")
- set(JARS_DEST_DIR "${MultiMC_SHARE_DEST_DIR}")
-
- set(BINARY_DEST_DIR ${MultiMC_BINARY_DEST_DIR})
- set(LIBRARY_DEST_DIR ${MultiMC_LIBRARY_DEST_DIR})
-
- MESSAGE(STATUS "Compiling for linux system with ${MultiMC_SHARE_DEST_DIR} and MULTIMC_LINUX_DATADIR")
- set_target_properties(MultiMC PROPERTIES OUTPUT_NAME ${MultiMC_APP_BINARY_NAME})
- target_compile_definitions(MultiMC PRIVATE "-DMULTIMC_JARS_LOCATION=/${MultiMC_SHARE_DEST_DIR}/jars" "-DMULTIMC_LINUX_DATADIR"
- )
-
- # install as bundle with no dependencies included
- set(INSTALL_BUNDLE "nodeps")
-
-elseif(MultiMC_LAYOUT_REAL STREQUAL "win-bundle")
- set(BINARY_DEST_DIR ".")
- set(LIBRARY_DEST_DIR ".")
- set(PLUGIN_DEST_DIR ".")
- set(BUNDLE_DEST_DIR ".")
- set(RESOURCES_DEST_DIR ".")
- set(JARS_DEST_DIR ".")
-
- # Apps to bundle
- set(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.exe")
-
- # directories to look for dependencies
- set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
-
- # install as bundle
- set(INSTALL_BUNDLE "full")
-else()
- message(FATAL_ERROR "No sensible install layout set.")
+if(DEFINED MultiMC_BINARY_RPATH)
+ SET_TARGET_PROPERTIES(MultiMC PROPERTIES INSTALL_RPATH "${MultiMC_BINARY_RPATH}")
+endif()
+if(DEFINED MultiMC_APP_BINARY_DEFS)
+ target_compile_definitions(MultiMC PRIVATE ${MultiMC_APP_BINARY_DEFS})
endif()
-######## Install files ########
-
-#### Executable ####
install(TARGETS MultiMC
BUNDLE DESTINATION ${BUNDLE_DEST_DIR} COMPONENT Runtime
LIBRARY DESTINATION ${LIBRARY_DEST_DIR} COMPONENT Runtime
RUNTIME DESTINATION ${BINARY_DEST_DIR} COMPONENT Runtime
)
-install_jar(JavaCheck "${JARS_DEST_DIR}/jars")
-install_jar(NewLaunch "${JARS_DEST_DIR}/jars")
-
-#### Dependency installations ####
-if(INSTALL_BUNDLE STREQUAL "nodeps")
- # Just our own stuff
- # FIXME: this does not remove RPATH.
- install(
- FILES
- $<TARGET_FILE:MultiMC_gui>
- $<TARGET_FILE:MultiMC_logic>
- $<TARGET_FILE:MultiMC_rainbow>
- $<TARGET_FILE:MultiMC_quazip>
- $<TARGET_FILE:MultiMC_iconfix>
- $<TARGET_FILE:MultiMC_unpack200>
- $<TARGET_FILE:MultiMC_nbt++>
- DESTINATION
- ${LIBRARY_DEST_DIR}
- )
-elseif(INSTALL_BUNDLE STREQUAL "full")
+#### The MultiMC bundle mess! ####
+# Bundle utilities are used to complete the portable packages - they add all the libraries that would otherwise be missing on the target system.
+# NOTE: it seems that this absolutely has to be here, and nowhere else.
+if(INSTALL_BUNDLE STREQUAL "full")
# Add qt.conf - this makes Qt stop looking for things outside the bundle
install(
CODE "file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${RESOURCES_DEST_DIR}/qt.conf\" \" \")"
diff --git a/application/ColumnResizer.cpp b/application/ColumnResizer.cpp
index 49440830..ee99bf40 100644
--- a/application/ColumnResizer.cpp
+++ b/application/ColumnResizer.cpp
@@ -197,5 +197,3 @@ void ColumnResizer::addWidgetsFromFormLayout(QFormLayout* layout, QFormLayout::I
d->m_wrWidgetItemList << newItem;
}
}
-
-#include <ColumnResizer.moc> \ No newline at end of file
diff --git a/application/GuiUtil.cpp b/application/GuiUtil.cpp
index 054fc0be..b05fc57c 100644
--- a/application/GuiUtil.cpp
+++ b/application/GuiUtil.cpp
@@ -33,7 +33,7 @@ QString GuiUtil::uploadPaste(const QString &text, QWidget *parentWidget)
}
dialog.execWithTask(paste.get());
- if (!paste->successful())
+ if (!paste->wasSuccessful())
{
CustomMessageBox::selectable(parentWidget, QObject::tr("Upload failed"),
paste->failReason(), QMessageBox::Critical)->exec();
@@ -56,8 +56,7 @@ void GuiUtil::setClipboardText(const QString &text)
QApplication::clipboard()->setText(text);
}
-
-QStringList GuiUtil::BrowseForFiles(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget)
+static QStringList BrowseForFileInternal(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget, bool single)
{
static QMap<QString, QString> savedPaths;
@@ -82,7 +81,7 @@ QStringList GuiUtil::BrowseForFiles(QString context, QString caption, QString fi
}
urls.append(QUrl::fromLocalFile(defaultPath));
- w.setFileMode(QFileDialog::ExistingFiles);
+ w.setFileMode(single ? QFileDialog::ExistingFile : QFileDialog::ExistingFiles);
w.setAcceptMode(QFileDialog::AcceptOpen);
w.setNameFilter(filter);
@@ -114,3 +113,19 @@ QStringList GuiUtil::BrowseForFiles(QString context, QString caption, QString fi
savedPaths[context] = w.directory().absolutePath();
return {};
}
+
+QString GuiUtil::BrowseForFile(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget)
+{
+ auto resultList = BrowseForFileInternal(context, caption, filter, defaultPath, parentWidget, true);
+ if(resultList.size())
+ {
+ return resultList[0];
+ }
+ return QString();
+}
+
+
+QStringList GuiUtil::BrowseForFiles(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget)
+{
+ return BrowseForFileInternal(context, caption, filter, defaultPath, parentWidget, false);
+}
diff --git a/application/GuiUtil.h b/application/GuiUtil.h
index 52520c56..5e109383 100644
--- a/application/GuiUtil.h
+++ b/application/GuiUtil.h
@@ -7,4 +7,5 @@ namespace GuiUtil
QString uploadPaste(const QString &text, QWidget *parentWidget);
void setClipboardText(const QString &text);
QStringList BrowseForFiles(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget);
+QString BrowseForFile(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget);
}
diff --git a/application/HoeDown.h b/application/HoeDown.h
index 70a9e5cd..18c315c6 100644
--- a/application/HoeDown.h
+++ b/application/HoeDown.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/InstancePageProvider.h b/application/InstancePageProvider.h
index 1d6cc5d7..b13ce93d 100644
--- a/application/InstancePageProvider.h
+++ b/application/InstancePageProvider.h
@@ -1,5 +1,5 @@
#pragma once
-#include "minecraft/onesix/OneSixInstance.h"
+#include "minecraft/MinecraftInstance.h"
#include "minecraft/legacy/LegacyInstance.h"
#include <FileSystem.h>
#include "pages/BasePage.h"
@@ -13,7 +13,7 @@
#include "pages/InstanceSettingsPage.h"
#include "pages/OtherLogsPage.h"
#include "pages/BasePageProvider.h"
-#include "pages/LegacyJarModPage.h"
+#include "pages/LegacyUpgradePage.h"
#include "pages/WorldListPage.h"
@@ -31,7 +31,7 @@ public:
{
QList<BasePage *> values;
values.append(new LogPage(inst));
- std::shared_ptr<OneSixInstance> onesix = std::dynamic_pointer_cast<OneSixInstance>(inst);
+ std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst);
if(onesix)
{
values.append(new VersionPage(onesix.get()));
@@ -49,18 +49,10 @@ public:
std::shared_ptr<LegacyInstance> legacy = std::dynamic_pointer_cast<LegacyInstance>(inst);
if(legacy)
{
- // FIXME: actually implement the legacy instance upgrade, then enable this.
- //values.append(new LegacyUpgradePage(this));
- values.append(new LegacyJarModPage(legacy.get()));
- auto modsPage = new ModFolderPage(legacy.get(), legacy->loaderModList(), "mods", "loadermods", tr("Loader mods"), "Loader-mods");
- modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
- values.append(modsPage);
- values.append(new ModFolderPage(legacy.get(), legacy->coreModList(), "coremods", "coremods", tr("Core mods"), "Loader-mods"));
- values.append(new TexturePackPage(legacy.get()));
+ values.append(new LegacyUpgradePage(legacy));
values.append(new NotesPage(legacy.get()));
values.append(new WorldListPage(legacy.get(), legacy->worldList(), "worlds", "worlds", tr("Worlds"), "Worlds"));
values.append(new ScreenshotsPage(FS::PathCombine(legacy->minecraftRoot(), "screenshots")));
- values.append(new InstanceSettingsPage(legacy.get()));
}
auto logMatcher = inst->getLogFileMatcher();
if(logMatcher)
diff --git a/application/InstanceWindow.cpp b/application/InstanceWindow.cpp
index dd643f47..2e876fea 100644
--- a/application/InstanceWindow.cpp
+++ b/application/InstanceWindow.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,6 +48,7 @@ InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent)
{
auto provider = std::make_shared<InstancePageProvider>(m_instance);
m_container = new PageContainer(provider, "console", this);
+ m_container->setParentContainer(this);
setCentralWidget(m_container);
}
@@ -72,7 +73,7 @@ InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent)
m_launchOfflineButton = new QPushButton();
horizontalLayout->addWidget(m_launchOfflineButton);
m_launchOfflineButton->setText(tr("Launch Offline"));
- setKillButton(m_instance->isRunning());
+ updateLaunchButtons();
connect(m_launchOfflineButton, SIGNAL(clicked(bool)), SLOT(on_btnLaunchMinecraftOffline_clicked()));
m_closeButton = new QPushButton();
@@ -115,14 +116,21 @@ void InstanceWindow::on_instanceStatusChanged(BaseInstance::Status, BaseInstance
}
}
-void InstanceWindow::setKillButton(bool kill)
+void InstanceWindow::updateLaunchButtons()
{
- if(kill)
+ if(m_instance->isRunning())
{
m_launchOfflineButton->setEnabled(false);
m_killButton->setText(tr("Kill"));
m_killButton->setToolTip(tr("Kill the running instance"));
}
+ else if(!m_instance->canLaunch())
+ {
+ m_launchOfflineButton->setEnabled(false);
+ m_killButton->setText(tr("Launch"));
+ m_killButton->setToolTip(tr("Launch the instance"));
+ m_killButton->setEnabled(false);
+ }
else
{
m_launchOfflineButton->setEnabled(true);
@@ -141,9 +149,9 @@ void InstanceWindow::on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> p
m_proc = proc;
}
-void InstanceWindow::on_RunningState_changed(bool running)
+void InstanceWindow::on_RunningState_changed(bool)
{
- setKillButton(running);
+ updateLaunchButtons();
m_container->refreshContainer();
}
@@ -206,3 +214,13 @@ void InstanceWindow::refreshContainer()
InstanceWindow::~InstanceWindow()
{
}
+
+bool InstanceWindow::requestClose()
+{
+ if(m_container->prepareToClose())
+ {
+ close();
+ return true;
+ }
+ return false;
+}
diff --git a/application/InstanceWindow.h b/application/InstanceWindow.h
index 8e272e09..2b08644e 100644
--- a/application/InstanceWindow.h
+++ b/application/InstanceWindow.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,6 +40,9 @@ public:
// save all settings and changes (prepare for launch)
bool saveAll();
+ // request closing the window (from a page)
+ bool requestClose() override;
+
signals:
void isClosing();
@@ -57,7 +60,7 @@ protected:
void closeEvent(QCloseEvent *) override;
private:
- void setKillButton(bool kill);
+ void updateLaunchButtons();
private:
std::shared_ptr<LaunchTask> m_proc;
diff --git a/application/LaunchController.cpp b/application/LaunchController.cpp
index e8f369be..2e711933 100644
--- a/application/LaunchController.cpp
+++ b/application/LaunchController.cpp
@@ -23,18 +23,18 @@ LaunchController::LaunchController(QObject *parent) : Task(parent)
void LaunchController::executeTask()
{
- login();
-}
-
-// FIXME: minecraft specific
-void LaunchController::login()
-{
if (!m_instance)
{
emitFailed(tr("No instance specified"));
return;
}
+ login();
+}
+
+// FIXME: minecraft specific
+void LaunchController::login()
+{
JavaCommon::checkJVMArgs(m_instance->settings()->get("JvmArgs").toString(), m_parentWidget);
// Find an account to use.
@@ -103,7 +103,7 @@ void LaunchController::login()
progDialog.setSkipButton(true, tr("Play Offline"));
}
progDialog.execWithTask(task.get());
- if (!task->successful())
+ if (!task->wasSuccessful())
{
auto failReasonNew = task->failReason();
if(failReasonNew == "Invalid token.")
@@ -192,7 +192,7 @@ void LaunchController::launchInstance()
Q_ASSERT_X(m_instance != NULL, "launchInstance", "instance is NULL");
Q_ASSERT_X(m_session.get() != nullptr, "launchInstance", "session is NULL");
- if(!m_instance->reload())
+ if(!m_instance->reloadSettings())
{
QMessageBox::critical(m_parentWidget, tr("Error"), tr("Couldn't load the instance profile."));
emitFailed(tr("Couldn't load the instance profile."));
diff --git a/application/MainWindow.cpp b/application/MainWindow.cpp
index 9eba9c44..1d36ef8c 100644
--- a/application/MainWindow.cpp
+++ b/application/MainWindow.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Authors: Andrew Okin
* Peterix
@@ -54,7 +54,6 @@
#include <java/JavaUtils.h>
#include <java/JavaInstallList.h>
#include <launch/LaunchTask.h>
-#include <minecraft/legacy/LwjglVersionList.h>
#include <minecraft/auth/MojangAccountList.h>
#include <SkinUtils.h>
#include <net/URLConstants.h>
@@ -91,58 +90,150 @@
#include <InstanceImportTask.h>
#include "UpdateController.h"
+// WHY: to hold the pre-translation strings together with the T pointer, so it can be retranslated without a lot of ugly code
+template <typename T>
+class Translated
+{
+public:
+ Translated(){}
+ Translated(QWidget *parent)
+ {
+ m_contained = new T(parent);
+ }
+ void setTooltipId(const char * tooltip)
+ {
+ m_tooltip = tooltip;
+ }
+ void setTextId(const char * text)
+ {
+ m_text = text;
+ }
+ operator T*()
+ {
+ return m_contained;
+ }
+ T * operator->()
+ {
+ return m_contained;
+ }
+ void retranslate()
+ {
+ if(m_text)
+ {
+ m_contained->setText(QApplication::translate("MainWindow", m_text));
+ }
+ if(m_tooltip)
+ {
+ m_contained->setToolTip(QApplication::translate("MainWindow", m_tooltip));
+ }
+ }
+private:
+ T * m_contained = nullptr;
+ const char * m_text = nullptr;
+ const char * m_tooltip = nullptr;
+};
+using TranslatedAction = Translated<QAction>;
+using TranslatedToolButton = Translated<QToolButton>;
+
+class TranslatedToolbar
+{
+public:
+ TranslatedToolbar(){}
+ TranslatedToolbar(QWidget *parent)
+ {
+ m_contained = new QToolBar(parent);
+ }
+ void setWindowTitleId(const char * title)
+ {
+ m_title = title;
+ }
+ operator QToolBar*()
+ {
+ return m_contained;
+ }
+ QToolBar * operator->()
+ {
+ return m_contained;
+ }
+ void retranslate()
+ {
+ if(m_title)
+ {
+ m_contained->setWindowTitle(QApplication::translate("MainWindow", m_title));
+ }
+ }
+private:
+ QToolBar * m_contained = nullptr;
+ const char * m_title = nullptr;
+};
+
class MainWindow::Ui
{
public:
- QAction *actionAddInstance;
- QAction *actionViewInstanceFolder;
- QAction *actionRefresh;
- QAction *actionViewCentralModsFolder;
- QAction *actionCheckUpdate;
- QAction *actionSettings;
- QAction *actionReportBug;
- QAction *actionPatreon;
- QAction *actionMoreNews;
- QAction *actionAbout;
- QAction *actionLaunchInstance;
- QAction *actionRenameInstance;
- QAction *actionChangeInstGroup;
- QAction *actionChangeInstIcon;
- QAction *actionEditInstNotes;
- QAction *actionEditInstance;
- QAction *actionWorlds;
- QAction *actionViewSelectedInstFolder;
- QAction *actionDeleteInstance;
- QAction *actionConfig_Folder;
- QAction *actionCAT;
- QAction *actionREDDIT;
- QAction *actionDISCORD;
- QAction *actionCopyInstance;
- QAction *actionManageAccounts;
- QAction *actionLaunchInstanceOffline;
- QAction *actionScreenshots;
- QAction *actionInstanceSettings;
- QAction *actionExportInstance;
- QWidget *centralWidget;
- QHBoxLayout *horizontalLayout;
- QToolBar *mainToolBar;
- QStatusBar *statusBar;
- QToolBar *instanceToolBar;
- QToolBar *newsToolBar;
+ TranslatedAction actionAddInstance;
+ //TranslatedAction actionRefresh;
+ TranslatedAction actionCheckUpdate;
+ TranslatedAction actionSettings;
+ TranslatedAction actionPatreon;
+ TranslatedAction actionMoreNews;
+ TranslatedAction actionManageAccounts;
+ TranslatedAction actionLaunchInstance;
+ TranslatedAction actionRenameInstance;
+ TranslatedAction actionChangeInstGroup;
+ TranslatedAction actionChangeInstIcon;
+ TranslatedAction actionEditInstNotes;
+ TranslatedAction actionEditInstance;
+ TranslatedAction actionWorlds;
+ TranslatedAction actionViewSelectedInstFolder;
+ TranslatedAction actionDeleteInstance;
+ TranslatedAction actionConfig_Folder;
+ TranslatedAction actionCAT;
+ TranslatedAction actionCopyInstance;
+ TranslatedAction actionLaunchInstanceOffline;
+ TranslatedAction actionScreenshots;
+ TranslatedAction actionExportInstance;
+ QVector<TranslatedAction *> all_actions;
+
+ LabeledToolButton *renameButton = nullptr;
+ LabeledToolButton *changeIconButton = nullptr;
+
+ QMenu * foldersMenu = nullptr;
+ TranslatedToolButton foldersMenuButton;
+ TranslatedAction actionViewInstanceFolder;
+ TranslatedAction actionViewCentralModsFolder;
+
+ QMenu * helpMenu = nullptr;
+ TranslatedToolButton helpMenuButton;
+ TranslatedAction actionReportBug;
+ TranslatedAction actionDISCORD;
+ TranslatedAction actionREDDIT;
+ TranslatedAction actionAbout;
+
+ QVector<TranslatedToolButton *> all_toolbuttons;
+
+ QWidget *centralWidget = nullptr;
+ QHBoxLayout *horizontalLayout = nullptr;
+ QStatusBar *statusBar = nullptr;
+
+ TranslatedToolbar mainToolBar;
+ TranslatedToolbar instanceToolBar;
+ TranslatedToolbar newsToolBar;
+ QVector<TranslatedToolbar *> all_toolbars;
bool m_kill = false;
void updateLaunchAction()
{
if(m_kill)
{
- actionLaunchInstance->setText(tr("Kill"));
- actionLaunchInstance->setToolTip(tr("Kill the running instance"));
+ actionLaunchInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Kill"));
+ actionLaunchInstance.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Kill the running instance"));
}
else
{
- actionLaunchInstance->setText(tr("Launch"));
- actionLaunchInstance->setToolTip(tr("Launch the selected instance."));
+ actionLaunchInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Launch"));
+ actionLaunchInstance.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Launch the selected instance."));
}
+ actionLaunchInstance.retranslate();
}
void setLaunchAction(bool kill)
{
@@ -150,168 +241,349 @@ public:
updateLaunchAction();
}
- void setupUi(QMainWindow *MainWindow)
+ void createMainToolbar(QMainWindow *MainWindow)
{
- if (MainWindow->objectName().isEmpty())
- {
- MainWindow->setObjectName(QStringLiteral("MainWindow"));
- }
- MainWindow->resize(694, 563);
- MainWindow->setWindowIcon(MMC->getThemedIcon("multimc"));
- actionAddInstance = new QAction(MainWindow);
+ mainToolBar = TranslatedToolbar(MainWindow);
+ mainToolBar->setObjectName(QStringLiteral("mainToolBar"));
+ mainToolBar->setMovable(false);
+ mainToolBar->setAllowedAreas(Qt::TopToolBarArea);
+ mainToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ mainToolBar->setFloatable(false);
+ mainToolBar.setWindowTitleId(QT_TRANSLATE_NOOP("MainWindow", "Main Toolbar"));
+
+ actionAddInstance = TranslatedAction(MainWindow);
actionAddInstance->setObjectName(QStringLiteral("actionAddInstance"));
actionAddInstance->setIcon(MMC->getThemedIcon("new"));
- actionViewInstanceFolder = new QAction(MainWindow);
+ actionAddInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Add Instance"));
+ actionAddInstance.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Add a new instance."));
+ all_actions.append(&actionAddInstance);
+ mainToolBar->addAction(actionAddInstance);
+
+ mainToolBar->addSeparator();
+
+ foldersMenu = new QMenu(MainWindow);
+ foldersMenu->setToolTipsVisible(true);
+
+ actionViewInstanceFolder = TranslatedAction(MainWindow);
actionViewInstanceFolder->setObjectName(QStringLiteral("actionViewInstanceFolder"));
actionViewInstanceFolder->setIcon(MMC->getThemedIcon("viewfolder"));
- actionRefresh = new QAction(MainWindow);
- actionRefresh->setObjectName(QStringLiteral("actionRefresh"));
- actionRefresh->setIcon(MMC->getThemedIcon("refresh"));
- actionViewCentralModsFolder = new QAction(MainWindow);
+ actionViewInstanceFolder.setTextId(QT_TRANSLATE_NOOP("MainWindow", "View Instance Folder"));
+ actionViewInstanceFolder.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open the instance folder in a file browser."));
+ all_actions.append(&actionViewInstanceFolder);
+ foldersMenu->addAction(actionViewInstanceFolder);
+
+ actionViewCentralModsFolder = TranslatedAction(MainWindow);
actionViewCentralModsFolder->setObjectName(QStringLiteral("actionViewCentralModsFolder"));
actionViewCentralModsFolder->setIcon(MMC->getThemedIcon("centralmods"));
- if(BuildConfig.UPDATER_ENABLED)
- {
- actionCheckUpdate = new QAction(MainWindow);
- actionCheckUpdate->setObjectName(QStringLiteral("actionCheckUpdate"));
- actionCheckUpdate->setIcon(MMC->getThemedIcon("checkupdate"));
- }
- actionSettings = new QAction(MainWindow);
+ actionViewCentralModsFolder.setTextId(QT_TRANSLATE_NOOP("MainWindow", "View Central Mods Folder"));
+ actionViewCentralModsFolder.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open the central mods folder in a file browser."));
+ all_actions.append(&actionViewCentralModsFolder);
+ foldersMenu->addAction(actionViewCentralModsFolder);
+
+ foldersMenuButton = TranslatedToolButton(MainWindow);
+ foldersMenuButton.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Folders"));
+ foldersMenuButton.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open one of the folders shared between instances."));
+ foldersMenuButton->setMenu(foldersMenu);
+ foldersMenuButton->setPopupMode(QToolButton::InstantPopup);
+ foldersMenuButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ foldersMenuButton->setIcon(MMC->getThemedIcon("viewfolder"));
+ all_toolbuttons.append(&foldersMenuButton);
+ QWidgetAction* foldersButtonAction = new QWidgetAction(MainWindow);
+ foldersButtonAction->setDefaultWidget(foldersMenuButton);
+ mainToolBar->addAction(foldersButtonAction);
+
+ actionSettings = TranslatedAction(MainWindow);
actionSettings->setObjectName(QStringLiteral("actionSettings"));
actionSettings->setIcon(MMC->getThemedIcon("settings"));
actionSettings->setMenuRole(QAction::PreferencesRole);
- actionReportBug = new QAction(MainWindow);
+ actionSettings.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Settings"));
+ actionSettings.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Change settings."));
+ all_actions.append(&actionSettings);
+ mainToolBar->addAction(actionSettings);
+
+ helpMenu = new QMenu(MainWindow);
+ helpMenu->setToolTipsVisible(true);
+
+ actionReportBug = TranslatedAction(MainWindow);
actionReportBug->setObjectName(QStringLiteral("actionReportBug"));
actionReportBug->setIcon(MMC->getThemedIcon("bug"));
- actionPatreon = new QAction(MainWindow);
- actionPatreon->setObjectName(QStringLiteral("actionPatreon"));
- actionPatreon->setIcon(MMC->getThemedIcon("patreon"));
- actionMoreNews = new QAction(MainWindow);
- actionMoreNews->setObjectName(QStringLiteral("actionMoreNews"));
- actionMoreNews->setIcon(MMC->getThemedIcon("news"));
- actionAbout = new QAction(MainWindow);
+ actionReportBug.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Report a Bug"));
+ actionReportBug.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open the bug tracker to report a bug with MultiMC."));
+ all_actions.append(&actionReportBug);
+ helpMenu->addAction(actionReportBug);
+
+ actionDISCORD = TranslatedAction(MainWindow);
+ actionDISCORD->setObjectName(QStringLiteral("actionDISCORD"));
+ actionDISCORD->setIcon(MMC->getThemedIcon("discord"));
+ actionDISCORD.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Discord"));
+ actionDISCORD.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open MultiMC discord voice chat."));
+ all_actions.append(&actionDISCORD);
+ helpMenu->addAction(actionDISCORD);
+
+ actionREDDIT = TranslatedAction(MainWindow);
+ actionREDDIT->setObjectName(QStringLiteral("actionREDDIT"));
+ actionREDDIT->setIcon(MMC->getThemedIcon("reddit-alien"));
+ actionREDDIT.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Reddit"));
+ actionREDDIT.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open MultiMC subreddit."));
+ all_actions.append(&actionREDDIT);
+ helpMenu->addAction(actionREDDIT);
+
+ actionAbout = TranslatedAction(MainWindow);
actionAbout->setObjectName(QStringLiteral("actionAbout"));
actionAbout->setIcon(MMC->getThemedIcon("about"));
actionAbout->setMenuRole(QAction::AboutRole);
- actionLaunchInstance = new QAction(MainWindow);
- actionLaunchInstance->setObjectName(QStringLiteral("actionLaunchInstance"));
- actionRenameInstance = new QAction(MainWindow);
- actionRenameInstance->setObjectName(QStringLiteral("actionRenameInstance"));
- actionChangeInstGroup = new QAction(MainWindow);
- actionChangeInstGroup->setObjectName(QStringLiteral("actionChangeInstGroup"));
- actionChangeInstIcon = new QAction(MainWindow);
- actionChangeInstIcon->setObjectName(QStringLiteral("actionChangeInstIcon"));
- actionChangeInstIcon->setEnabled(true);
- actionChangeInstIcon->setIcon(QIcon(":/icons/instances/infinity"));
- actionChangeInstIcon->setIconVisibleInMenu(true);
- actionEditInstNotes = new QAction(MainWindow);
- actionEditInstNotes->setObjectName(QStringLiteral("actionEditInstNotes"));
- actionEditInstance = new QAction(MainWindow);
- actionEditInstance->setObjectName(QStringLiteral("actionEditInstance"));
- actionWorlds = new QAction(MainWindow);
- actionWorlds->setObjectName(QStringLiteral("actionWorlds"));
- actionViewSelectedInstFolder = new QAction(MainWindow);
- actionViewSelectedInstFolder->setObjectName(QStringLiteral("actionViewSelectedInstFolder"));
- actionDeleteInstance = new QAction(MainWindow);
- actionDeleteInstance->setObjectName(QStringLiteral("actionDeleteInstance"));
- actionConfig_Folder = new QAction(MainWindow);
- actionConfig_Folder->setObjectName(QStringLiteral("actionConfig_Folder"));
- actionCAT = new QAction(MainWindow);
+ actionAbout.setTextId(QT_TRANSLATE_NOOP("MainWindow", "About MultiMC"));
+ actionAbout.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "View information about MultiMC."));
+ all_actions.append(&actionAbout);
+ helpMenu->addAction(actionAbout);
+
+ helpMenuButton = TranslatedToolButton(MainWindow);
+ helpMenuButton.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Help"));
+ helpMenuButton.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Get help with MultiMC or Minecraft."));
+ helpMenuButton->setMenu(helpMenu);
+ helpMenuButton->setPopupMode(QToolButton::InstantPopup);
+ helpMenuButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ helpMenuButton->setIcon(MMC->getThemedIcon("help"));
+ all_toolbuttons.append(&helpMenuButton);
+ QWidgetAction* helpButtonAction = new QWidgetAction(MainWindow);
+ helpButtonAction->setDefaultWidget(helpMenuButton);
+ mainToolBar->addAction(helpButtonAction);
+
+ if(BuildConfig.UPDATER_ENABLED)
+ {
+ actionCheckUpdate = TranslatedAction(MainWindow);
+ actionCheckUpdate->setObjectName(QStringLiteral("actionCheckUpdate"));
+ actionCheckUpdate->setIcon(MMC->getThemedIcon("checkupdate"));
+ actionCheckUpdate.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Update"));
+ actionCheckUpdate.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Check for new updates for MultiMC."));
+ all_actions.append(&actionCheckUpdate);
+ mainToolBar->addAction(actionCheckUpdate);
+ }
+
+ mainToolBar->addSeparator();
+
+ actionPatreon = TranslatedAction(MainWindow);
+ actionPatreon->setObjectName(QStringLiteral("actionPatreon"));
+ actionPatreon->setIcon(MMC->getThemedIcon("patreon"));
+ actionPatreon.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Support MultiMC"));
+ actionPatreon.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open the MultiMC Patreon page."));
+ all_actions.append(&actionPatreon);
+ mainToolBar->addAction(actionPatreon);
+
+ actionCAT = TranslatedAction(MainWindow);
actionCAT->setObjectName(QStringLiteral("actionCAT"));
actionCAT->setCheckable(true);
actionCAT->setIcon(MMC->getThemedIcon("cat"));
- actionREDDIT = new QAction(MainWindow);
- actionREDDIT->setObjectName(QStringLiteral("actionREDDIT"));
- actionREDDIT->setIcon(MMC->getThemedIcon("reddit-alien"));
- actionDISCORD = new QAction(MainWindow);
- actionDISCORD->setObjectName(QStringLiteral("actionDISCORD"));
- actionDISCORD->setIcon(MMC->getThemedIcon("discord"));
- actionCopyInstance = new QAction(MainWindow);
- actionCopyInstance->setObjectName(QStringLiteral("actionCopyInstance"));
- actionCopyInstance->setIcon(MMC->getThemedIcon("copy"));
- actionManageAccounts = new QAction(MainWindow);
+ actionCAT.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Meow"));
+ actionCAT.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "It's a fluffy kitty :3"));
+ actionCAT->setPriority(QAction::LowPriority);
+ all_actions.append(&actionCAT);
+ mainToolBar->addAction(actionCAT);
+
+ // profile menu and its actions
+ actionManageAccounts = TranslatedAction(MainWindow);
actionManageAccounts->setObjectName(QStringLiteral("actionManageAccounts"));
- actionLaunchInstanceOffline = new QAction(MainWindow);
- actionLaunchInstanceOffline->setObjectName(QStringLiteral("actionLaunchInstanceOffline"));
- actionScreenshots = new QAction(MainWindow);
- actionScreenshots->setObjectName(QStringLiteral("actionScreenshots"));
- actionInstanceSettings = new QAction(MainWindow);
- actionInstanceSettings->setObjectName(QStringLiteral("actionInstanceSettings"));
- actionExportInstance = new QAction(MainWindow);
- actionExportInstance->setObjectName(QStringLiteral("actionExportInstance"));
- centralWidget = new QWidget(MainWindow);
- centralWidget->setObjectName(QStringLiteral("centralWidget"));
- horizontalLayout = new QHBoxLayout(centralWidget);
- horizontalLayout->setSpacing(0);
- horizontalLayout->setContentsMargins(11, 11, 11, 11);
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
- horizontalLayout->setSizeConstraint(QLayout::SetDefaultConstraint);
- horizontalLayout->setContentsMargins(0, 0, 0, 0);
- MainWindow->setCentralWidget(centralWidget);
- mainToolBar = new QToolBar(MainWindow);
- mainToolBar->setObjectName(QStringLiteral("mainToolBar"));
- mainToolBar->setMovable(false);
- mainToolBar->setAllowedAreas(Qt::TopToolBarArea);
- mainToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
- mainToolBar->setFloatable(false);
+ actionManageAccounts.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Manage Accounts"));
+ // FIXME: no tooltip!
+ actionManageAccounts->setCheckable(false);
+ actionManageAccounts->setIcon(MMC->getThemedIcon("accounts"));
+ all_actions.append(&actionManageAccounts);
+
+ all_toolbars.append(&mainToolBar);
MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar);
+ }
+
+ void createStatusBar(QMainWindow *MainWindow)
+ {
statusBar = new QStatusBar(MainWindow);
statusBar->setObjectName(QStringLiteral("statusBar"));
MainWindow->setStatusBar(statusBar);
- instanceToolBar = new QToolBar(MainWindow);
- instanceToolBar->setObjectName(QStringLiteral("instanceToolBar"));
- instanceToolBar->setEnabled(true);
- instanceToolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
- instanceToolBar->setIconSize(QSize(80, 80));
- instanceToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
- instanceToolBar->setFloatable(false);
- MainWindow->addToolBar(Qt::RightToolBarArea, instanceToolBar);
- newsToolBar = new QToolBar(MainWindow);
+ }
+
+ void createNewsToolbar(QMainWindow *MainWindow)
+ {
+ newsToolBar = TranslatedToolbar(MainWindow);
newsToolBar->setObjectName(QStringLiteral("newsToolBar"));
newsToolBar->setMovable(false);
newsToolBar->setAllowedAreas(Qt::BottomToolBarArea);
newsToolBar->setIconSize(QSize(16, 16));
newsToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
newsToolBar->setFloatable(false);
+ newsToolBar->setWindowTitle(QT_TRANSLATE_NOOP("MainWindow", "News Toolbar"));
+
+ actionMoreNews = TranslatedAction(MainWindow);
+ actionMoreNews->setObjectName(QStringLiteral("actionMoreNews"));
+ actionMoreNews->setIcon(MMC->getThemedIcon("news"));
+ actionMoreNews.setTextId(QT_TRANSLATE_NOOP("MainWindow", "More news..."));
+ actionMoreNews.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open the MultiMC development blog to read more news about MultiMC."));
+ all_actions.append(&actionMoreNews);
+ newsToolBar->addAction(actionMoreNews);
+
+ all_toolbars.append(&newsToolBar);
MainWindow->addToolBar(Qt::BottomToolBarArea, newsToolBar);
+ }
- mainToolBar->addAction(actionAddInstance);
- mainToolBar->addAction(actionCopyInstance);
- mainToolBar->addSeparator();
- mainToolBar->addAction(actionViewInstanceFolder);
- mainToolBar->addAction(actionViewCentralModsFolder);
- mainToolBar->addAction(actionRefresh);
- mainToolBar->addSeparator();
- if(BuildConfig.UPDATER_ENABLED)
- {
- mainToolBar->addAction(actionCheckUpdate);
- }
- mainToolBar->addAction(actionSettings);
- mainToolBar->addSeparator();
- mainToolBar->addAction(actionReportBug);
- mainToolBar->addAction(actionAbout);
- mainToolBar->addSeparator();
- mainToolBar->addAction(actionPatreon);
- mainToolBar->addAction(actionREDDIT);
- mainToolBar->addAction(actionDISCORD);
- mainToolBar->addAction(actionCAT);
- instanceToolBar->addAction(actionChangeInstIcon);
+ void createInstanceToolbar(QMainWindow *MainWindow)
+ {
+ instanceToolBar = TranslatedToolbar(MainWindow);
+ instanceToolBar->setObjectName(QStringLiteral("instanceToolBar"));
+ // disabled until we have an instance selected
+ instanceToolBar->setEnabled(false);
+ instanceToolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
+ instanceToolBar->setToolButtonStyle(Qt::ToolButtonTextOnly);
+ instanceToolBar->setFloatable(false);
+ instanceToolBar->setWindowTitle(QT_TRANSLATE_NOOP("MainWindow", "Instance Toolbar"));
+
+ // NOTE: not added to toolbar, but used for instance context menu (right click)
+ actionChangeInstIcon = TranslatedAction(MainWindow);
+ actionChangeInstIcon->setObjectName(QStringLiteral("actionChangeInstIcon"));
+ actionChangeInstIcon->setIcon(QIcon(":/icons/instances/infinity"));
+ actionChangeInstIcon->setIconVisibleInMenu(true);
+ actionChangeInstIcon.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Change Icon"));
+ actionChangeInstIcon.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Change the selected instance's icon."));
+ all_actions.append(&actionChangeInstIcon);
+
+ changeIconButton = new LabeledToolButton(MainWindow);
+ changeIconButton->setObjectName(QStringLiteral("changeIconButton"));
+ changeIconButton->setIcon(MMC->getThemedIcon("news"));
+ changeIconButton->setToolTip(actionChangeInstIcon->toolTip());
+ changeIconButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ instanceToolBar->addWidget(changeIconButton);
+
+ // NOTE: not added to toolbar, but used for instance context menu (right click)
+ actionRenameInstance = TranslatedAction(MainWindow);
+ actionRenameInstance->setObjectName(QStringLiteral("actionRenameInstance"));
+ actionRenameInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Rename"));
+ actionRenameInstance.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Rename the selected instance."));
+ all_actions.append(&actionRenameInstance);
+
+ // the rename label is inside the rename tool button
+ renameButton = new LabeledToolButton(MainWindow);
+ renameButton->setObjectName(QStringLiteral("renameButton"));
+ renameButton->setToolTip(actionRenameInstance->toolTip());
+ renameButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ instanceToolBar->addWidget(renameButton);
+
+ instanceToolBar->addSeparator();
+
+ actionLaunchInstance = TranslatedAction(MainWindow);
+ actionLaunchInstance->setObjectName(QStringLiteral("actionLaunchInstance"));
+ all_actions.append(&actionLaunchInstance);
instanceToolBar->addAction(actionLaunchInstance);
+
+ actionLaunchInstanceOffline = TranslatedAction(MainWindow);
+ actionLaunchInstanceOffline->setObjectName(QStringLiteral("actionLaunchInstanceOffline"));
+ actionLaunchInstanceOffline.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Launch Offline"));
+ actionLaunchInstanceOffline.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Launch the selected instance in offline mode."));
+ all_actions.append(&actionLaunchInstanceOffline);
instanceToolBar->addAction(actionLaunchInstanceOffline);
+
instanceToolBar->addSeparator();
+
+ actionEditInstance = TranslatedAction(MainWindow);
+ actionEditInstance->setObjectName(QStringLiteral("actionEditInstance"));
+ actionEditInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Edit Instance"));
+ actionEditInstance.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Change the instance settings, mods and versions."));
+ all_actions.append(&actionEditInstance);
instanceToolBar->addAction(actionEditInstance);
- instanceToolBar->addAction(actionInstanceSettings);
+
+ actionEditInstNotes = TranslatedAction(MainWindow);
+ actionEditInstNotes->setObjectName(QStringLiteral("actionEditInstNotes"));
+ actionEditInstNotes.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Edit Notes"));
+ actionEditInstNotes.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Edit the notes for the selected instance."));
+ all_actions.append(&actionEditInstNotes);
instanceToolBar->addAction(actionEditInstNotes);
+
+ actionWorlds = TranslatedAction(MainWindow);
+ actionWorlds->setObjectName(QStringLiteral("actionWorlds"));
+ actionWorlds.setTextId(QT_TRANSLATE_NOOP("MainWindow", "View Worlds"));
+ actionWorlds.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "View the worlds of this instance."));
+ all_actions.append(&actionWorlds);
instanceToolBar->addAction(actionWorlds);
+
+ actionScreenshots = TranslatedAction(MainWindow);
+ actionScreenshots->setObjectName(QStringLiteral("actionScreenshots"));
+ actionScreenshots.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Manage Screenshots"));
+ actionScreenshots.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "View and upload screenshots for this instance."));
+ all_actions.append(&actionScreenshots);
instanceToolBar->addAction(actionScreenshots);
+
+ actionChangeInstGroup = TranslatedAction(MainWindow);
+ actionChangeInstGroup->setObjectName(QStringLiteral("actionChangeInstGroup"));
+ actionChangeInstGroup.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Change Group"));
+ actionChangeInstGroup.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Change the selected instance's group."));
+ all_actions.append(&actionChangeInstGroup);
instanceToolBar->addAction(actionChangeInstGroup);
+
instanceToolBar->addSeparator();
+
+ actionViewSelectedInstFolder = TranslatedAction(MainWindow);
+ actionViewSelectedInstFolder->setObjectName(QStringLiteral("actionViewSelectedInstFolder"));
+ actionViewSelectedInstFolder.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Instance Folder"));
+ actionViewSelectedInstFolder.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open the selected instance's root folder in a file browser."));
+ all_actions.append(&actionViewSelectedInstFolder);
instanceToolBar->addAction(actionViewSelectedInstFolder);
+
+ actionConfig_Folder = TranslatedAction(MainWindow);
+ actionConfig_Folder->setObjectName(QStringLiteral("actionConfig_Folder"));
+ actionConfig_Folder.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Config Folder"));
+ actionConfig_Folder.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open the instance's config folder."));
+ all_actions.append(&actionConfig_Folder);
instanceToolBar->addAction(actionConfig_Folder);
+
instanceToolBar->addSeparator();
+
+ actionExportInstance = TranslatedAction(MainWindow);
+ actionExportInstance->setObjectName(QStringLiteral("actionExportInstance"));
+ actionExportInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Export Instance"));
+ // FIXME: missing tooltip
+ all_actions.append(&actionExportInstance);
instanceToolBar->addAction(actionExportInstance);
+
+ actionDeleteInstance = TranslatedAction(MainWindow);
+ actionDeleteInstance->setObjectName(QStringLiteral("actionDeleteInstance"));
+ actionDeleteInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Delete"));
+ actionDeleteInstance.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Delete the selected instance."));
+ all_actions.append(&actionDeleteInstance);
instanceToolBar->addAction(actionDeleteInstance);
- newsToolBar->addAction(actionMoreNews);
+
+ actionCopyInstance = TranslatedAction(MainWindow);
+ actionCopyInstance->setObjectName(QStringLiteral("actionCopyInstance"));
+ actionCopyInstance->setIcon(MMC->getThemedIcon("copy"));
+ actionCopyInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Copy Instance"));
+ actionCopyInstance.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Copy the selected instance."));
+ all_actions.append(&actionCopyInstance);
+ instanceToolBar->addAction(actionCopyInstance);
+
+ all_toolbars.append(&instanceToolBar);
+ MainWindow->addToolBar(Qt::RightToolBarArea, instanceToolBar);
+ }
+
+ void setupUi(QMainWindow *MainWindow)
+ {
+ if (MainWindow->objectName().isEmpty())
+ {
+ MainWindow->setObjectName(QStringLiteral("MainWindow"));
+ }
+ MainWindow->resize(694, 563);
+ MainWindow->setWindowIcon(MMC->getThemedIcon("logo"));
+ MainWindow->setWindowTitle("MultiMC 5");
+
+ createMainToolbar(MainWindow);
+
+ centralWidget = new QWidget(MainWindow);
+ centralWidget->setObjectName(QStringLiteral("centralWidget"));
+ horizontalLayout = new QHBoxLayout(centralWidget);
+ horizontalLayout->setSpacing(0);
+ horizontalLayout->setContentsMargins(11, 11, 11, 11);
+ horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setSizeConstraint(QLayout::SetDefaultConstraint);
+ horizontalLayout->setContentsMargins(0, 0, 0, 0);
+ MainWindow->setCentralWidget(centralWidget);
+
+ createStatusBar(MainWindow);
+ createNewsToolbar(MainWindow);
+ createInstanceToolbar(MainWindow);
retranslateUi(MainWindow);
@@ -320,69 +592,28 @@ public:
void retranslateUi(QMainWindow *MainWindow)
{
- MainWindow->setWindowTitle("MultiMC 5");
- actionAddInstance->setText(tr("Add Instance"));
- actionAddInstance->setToolTip(tr("Add a new instance."));
- actionViewInstanceFolder->setText(tr("View Instance Folder"));
- actionViewInstanceFolder->setToolTip(tr("Open the instance folder in a file browser."));
- actionRefresh->setText(tr("Refresh"));
- actionRefresh->setToolTip(tr("Reload the instance list."));
- actionViewCentralModsFolder->setText(tr("View Central Mods Folder"));
- actionViewCentralModsFolder->setToolTip(tr("Open the central mods folder in a file browser."));
- if(BuildConfig.UPDATER_ENABLED)
+ QString winTitle = tr("MultiMC 5 - Version %1").arg(BuildConfig.printableVersionString());
+ if (!BuildConfig.BUILD_PLATFORM.isEmpty())
{
- actionCheckUpdate->setText(tr("Check for Updates"));
- actionCheckUpdate->setToolTip(tr("Check for new updates for MultiMC."));
+ winTitle += tr(" on %1", "on platform, as in operating system").arg(BuildConfig.BUILD_PLATFORM);
}
- actionSettings->setText(tr("Settings"));
- actionSettings->setToolTip(tr("Change settings."));
- actionReportBug->setText(tr("Report a Bug"));
- actionReportBug->setToolTip(tr("Open the bug tracker to report a bug with MultiMC."));
- actionPatreon->setText(tr("Support us on Patreon!"));
- actionPatreon->setToolTip(tr("Open the MultiMC Patreon page."));
- actionMoreNews->setText(tr("More news..."));
- actionMoreNews->setToolTip(tr("Open the MultiMC development blog to read more news about MultiMC."));
- actionAbout->setText(tr("About MultiMC"));
- actionAbout->setToolTip(tr("View information about MultiMC."));
- updateLaunchAction();
- actionRenameInstance->setText(tr("Instance Name"));
- actionRenameInstance->setToolTip(tr("Rename the selected instance."));
- actionChangeInstGroup->setText(tr("Change Group"));
- actionChangeInstGroup->setToolTip(tr("Change the selected instance's group."));
- actionChangeInstIcon->setText(tr("Change Icon"));
- actionChangeInstIcon->setToolTip(tr("Change the selected instance's icon."));
- actionEditInstNotes->setText(tr("Edit Notes"));
- actionEditInstNotes->setToolTip(tr("Edit the notes for the selected instance."));
- actionWorlds->setText(tr("View Worlds"));
- actionWorlds->setToolTip(tr("View the worlds of this instance."));
- actionEditInstance->setText(tr("Edit Instance"));
- actionEditInstance->setToolTip(tr("Change the instance settings, mods and versions."));
- actionViewSelectedInstFolder->setText(tr("Instance Folder"));
- actionViewSelectedInstFolder->setToolTip(tr("Open the selected instance's root folder in a file browser."));
- actionDeleteInstance->setText(tr("Delete"));
- actionDeleteInstance->setToolTip(tr("Delete the selected instance."));
- actionConfig_Folder->setText(tr("Config Folder"));
- actionConfig_Folder->setToolTip(tr("Open the instance's config folder."));
- actionCAT->setText(tr("Meow"));
- actionCAT->setToolTip(tr("It's a fluffy kitty :3"));
- actionREDDIT->setText(tr("Reddit"));
- actionREDDIT->setToolTip(tr("Open MultiMC subreddit."));
- actionDISCORD->setText(tr("Discord"));
- actionDISCORD->setToolTip(tr("Open MultiMC discord voice chat."));
- actionCopyInstance->setText(tr("Copy Instance"));
- actionCopyInstance->setToolTip(tr("Copy the selected instance."));
- actionManageAccounts->setText(tr("Manage Accounts"));
- actionManageAccounts->setToolTip(tr("Manage your Mojang or Minecraft accounts."));
- actionLaunchInstanceOffline->setText(tr("Launch Offline"));
- actionLaunchInstanceOffline->setToolTip(tr("Launch the selected instance in offline mode."));
- actionScreenshots->setText(tr("Manage Screenshots"));
- actionScreenshots->setToolTip(tr("View and upload screenshots for this instance."));
- actionInstanceSettings->setText(tr("Instance Settings"));
- actionInstanceSettings->setToolTip(tr("Change the settings specific to the instance."));
- actionExportInstance->setText(tr("Export Instance"));
- mainToolBar->setWindowTitle(tr("Main Toolbar"));
- instanceToolBar->setWindowTitle(tr("Instance Toolbar"));
- newsToolBar->setWindowTitle(tr("News Toolbar"));
+ MainWindow->setWindowTitle(winTitle);
+ // all the actions
+ for(auto * item: all_actions)
+ {
+ item->retranslate();
+ }
+ for(auto * item: all_toolbars)
+ {
+ item->retranslate();
+ }
+ for(auto * item: all_toolbuttons)
+ {
+ item->retranslate();
+ }
+ // submenu buttons
+ foldersMenuButton->setText(tr("Folders"));
+ helpMenuButton->setText(tr("Help"));
} // retranslateUi
};
@@ -390,13 +621,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
{
ui->setupUi(this);
- QString winTitle = tr("MultiMC 5 - Version %1").arg(BuildConfig.printableVersionString());
- if (!BuildConfig.BUILD_PLATFORM.isEmpty())
- {
- winTitle += tr(" on %1", "on platform, as in operating system").arg(BuildConfig.BUILD_PLATFORM);
- }
- setWindowTitle(winTitle);
-
// OSX magic.
setUnifiedTitleAndToolBarOnMac(true);
@@ -407,21 +631,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
connect(q, SIGNAL(activated()), qApp, SLOT(quit()));
}
- // The instance action toolbar customizations
- {
- // disabled until we have an instance selected
- ui->instanceToolBar->setEnabled(false);
-
- // the rename label is inside the rename tool button
- renameButton = new LabeledToolButton();
- renameButton->setText("Instance Name");
- renameButton->setToolTip(ui->actionRenameInstance->toolTip());
- connect(renameButton, SIGNAL(clicked(bool)), SLOT(on_actionRenameInstance_triggered()));
- ui->instanceToolBar->insertWidget(ui->actionLaunchInstance, renameButton);
- ui->instanceToolBar->insertSeparator(ui->actionLaunchInstance);
- renameButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
- }
-
// Add the news label to the news toolbar.
{
m_newsChecker.reset(new NewsChecker(BuildConfig.NEWS_RSS_URL));
@@ -489,10 +698,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
ui->mainToolBar->addWidget(spacer);
accountMenu = new QMenu(this);
- manageAccountsAction = new QAction(tr("Manage Accounts"), this);
- manageAccountsAction->setCheckable(false);
- manageAccountsAction->setIcon(MMC->getThemedIcon("accounts"));
- connect(manageAccountsAction, SIGNAL(triggered(bool)), this, SLOT(on_actionManageAccounts_triggered()));
repopulateAccountsMenu();
@@ -566,6 +771,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
{
bool updatesAllowed = MMC->updatesAreAllowed();
updatesAllowedChanged(updatesAllowed);
+
+ connect(ui->actionCheckUpdate, &QAction::triggered, this, &MainWindow::checkForUpdates);
+
// set up the updater object.
auto updater = MMC->updateChecker();
connect(updater.get(), &UpdateChecker::updateAvailable, this, &MainWindow::updateAvailable);
@@ -616,22 +824,17 @@ void MainWindow::showInstanceContextMenu(const QPoint &pos)
{
actions = ui->instanceToolBar->actions();
- QAction *actionVoid = new QAction(m_selectedInstance->name(), this);
- actionVoid->setEnabled(false);
-
- QAction *actionRename = new QAction(tr("Rename"), this);
- actionRename->setToolTip(ui->actionRenameInstance->toolTip());
+ // replace the change icon widget with an actual action
+ actions.replace(0, ui->actionChangeInstIcon);
- QAction *actionCopyInstance = new QAction(tr("Copy instance"), this);
- actionCopyInstance->setToolTip(ui->actionCopyInstance->toolTip());
+ // replace the rename widget with an actual action
+ actions.replace(1, ui->actionRenameInstance);
- connect(actionRename, SIGNAL(triggered(bool)), SLOT(on_actionRenameInstance_triggered()));
- connect(actionCopyInstance, SIGNAL(triggered(bool)), SLOT(on_actionCopyInstance_triggered()));
-
- actions.replace(1, actionRename);
+ // add header
actions.prepend(actionSep);
+ QAction *actionVoid = new QAction(m_selectedInstance->name(), this);
+ actionVoid->setEnabled(false);
actions.prepend(actionVoid);
- actions.append(actionCopyInstance);
}
else
{
@@ -660,14 +863,16 @@ void MainWindow::showInstanceContextMenu(const QPoint &pos)
QVariantMap data;
data["group"] = group;
actionDeleteGroup->setData(data);
- connect(actionDeleteGroup, SIGNAL(triggered(bool)), SLOT(on_actionDeleteGroup_triggered()));
+ connect(actionDeleteGroup, SIGNAL(triggered(bool)), SLOT(deleteGroup()));
actions.append(actionDeleteGroup);
}
}
QMenu myMenu;
myMenu.addActions(actions);
+ /*
if (onInstance)
myMenu.setEnabled(m_selectedInstance->canLaunch());
+ */
myMenu.exec(view->mapToGlobal(pos));
}
@@ -795,7 +1000,7 @@ void MainWindow::repopulateAccountsMenu()
connect(action, SIGNAL(triggered(bool)), SLOT(changeActiveAccount()));
accountMenu->addSeparator();
- accountMenu->addAction(manageAccountsAction);
+ accountMenu->addAction(ui->actionManageAccounts);
}
void MainWindow::updatesAllowedChanged(bool allowed)
@@ -870,7 +1075,7 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *ev)
on_actionDeleteInstance_triggered();
return true;
case Qt::Key_F5:
- on_actionRefresh_triggered();
+ refreshInstances();
return true;
case Qt::Key_F2:
on_actionRenameInstance_triggered();
@@ -1034,7 +1239,15 @@ void MainWindow::runModalTask(Task *task)
{
connect(task, &Task::failed, [this](QString reason)
{
- CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Warning)->show();
+ CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show();
+ });
+ connect(task, &Task::succeeded, [this, task]()
+ {
+ QStringList warnings = task->warnings();
+ if(warnings.count())
+ {
+ CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show();
+ }
});
ProgressDialog loadDialog(this);
loadDialog.setSkipButton(true, tr("Abort"));
@@ -1059,6 +1272,14 @@ void MainWindow::instanceFromVersion(QString instName, QString instGroup, QStrin
// finalizeInstance(newInstance);
}
+void MainWindow::instanceFromFtbPack(FtbPackDownloader *downloader, QString instName, QString instGroup, QString instIcon) {
+ std::unique_ptr<Task> task(MMC->folderProvider()->ftbCreationTask(downloader, instName, instGroup, instIcon));
+ runModalTask(task.get());
+
+ // FIXME: handle instance selection after creation
+ // finalizeInstance(newInstance);
+}
+
void MainWindow::on_actionCopyInstance_triggered()
{
if (!m_selectedInstance)
@@ -1083,7 +1304,7 @@ void MainWindow::finalizeInstance(InstancePtr inst)
if (MMC->accounts()->anyAccountIsValid())
{
ProgressDialog loadDialog(this);
- auto update = inst->createUpdateTask();
+ auto update = inst->createUpdateTask(Net::Mode::Online);
connect(update.get(), &Task::failed, [this](QString reason)
{
QString error = QString("Instance load failed: %1").arg(reason);
@@ -1134,7 +1355,10 @@ void MainWindow::addInstance(QString url)
const QUrl modpackUrl = newInstDlg.modpackUrl();
- if (modpackUrl.isValid())
+ if(newInstDlg.isFtbModpackRequested()) {
+ instanceFromFtbPack(newInstDlg.getFtbPackDownloader(), newInstDlg.instName(), newInstDlg.instGroup(), newInstDlg.iconKey());
+ }
+ else if (modpackUrl.isValid())
{
instanceFromZipPack(newInstDlg.instName(), newInstDlg.instGroup(), newInstDlg.iconKey(), modpackUrl);
}
@@ -1186,8 +1410,9 @@ void MainWindow::on_actionChangeInstIcon_triggered()
if (dlg.result() == QDialog::Accepted)
{
m_selectedInstance->setIconKey(dlg.selectedIconKey);
- auto ico = MMC->icons()->getBigIcon(dlg.selectedIconKey);
- ui->actionChangeInstIcon->setIcon(ico);
+ auto icon = MMC->icons()->getIcon(dlg.selectedIconKey);
+ ui->actionChangeInstIcon->setIcon(icon);
+ ui->changeIconButton->setIcon(icon);
}
}
@@ -1195,14 +1420,18 @@ void MainWindow::iconUpdated(QString icon)
{
if (icon == m_currentInstIcon)
{
- ui->actionChangeInstIcon->setIcon(MMC->icons()->getBigIcon(m_currentInstIcon));
+ auto icon = MMC->icons()->getIcon(m_currentInstIcon);
+ ui->actionChangeInstIcon->setIcon(icon);
+ ui->changeIconButton->setIcon(icon);
}
}
void MainWindow::updateInstanceToolIcon(QString new_icon)
{
m_currentInstIcon = new_icon;
- ui->actionChangeInstIcon->setIcon(MMC->icons()->getBigIcon(m_currentInstIcon));
+ auto icon = MMC->icons()->getIcon(m_currentInstIcon);
+ ui->actionChangeInstIcon->setIcon(icon);
+ ui->changeIconButton->setIcon(icon);
}
void MainWindow::setSelectedInstanceById(const QString &id)
@@ -1235,7 +1464,7 @@ void MainWindow::on_actionChangeInstGroup_triggered()
m_selectedInstance->setGroupPost(name);
}
-void MainWindow::on_actionDeleteGroup_triggered()
+void MainWindow::deleteGroup()
{
QObject* obj = sender();
if(!obj)
@@ -1259,7 +1488,7 @@ void MainWindow::on_actionViewInstanceFolder_triggered()
DesktopServices::openDirectory(str);
}
-void MainWindow::on_actionRefresh_triggered()
+void MainWindow::refreshInstances()
{
MMC->instances()->loadList(true);
}
@@ -1278,7 +1507,7 @@ void MainWindow::on_actionConfig_Folder_triggered()
}
}
-void MainWindow::on_actionCheckUpdate_triggered()
+void MainWindow::checkForUpdates()
{
if(BuildConfig.UPDATER_ENABLED)
{
@@ -1379,11 +1608,13 @@ void MainWindow::on_actionDeleteInstance_triggered()
{
return;
}
- auto response = CustomMessageBox::selectable(this, tr("CAREFUL!"), tr("About to delete: %1\nThis is permanent and will completely erase "
- "all data, even for tracked instances!\nAre you sure?")
- .arg(m_selectedInstance->name()),
- QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No)
- ->exec();
+ auto response = CustomMessageBox::selectable(
+ this,
+ tr("CAREFUL!"),
+ tr("About to delete: %1\nThis is permanent and will completely delete the instance.\n\nAre you sure?").arg(m_selectedInstance->name()),
+ QMessageBox::Warning,
+ QMessageBox::Yes | QMessageBox::No
+ )->exec();
if (response == QMessageBox::Yes)
{
m_selectedInstance->nuke();
@@ -1413,7 +1644,7 @@ void MainWindow::on_actionRenameInstance_triggered()
if (ok && name.length())
{
m_selectedInstance->setName(name);
- renameButton->setText(name);
+ ui->renameButton->setText(name);
}
}
}
@@ -1528,7 +1759,7 @@ void MainWindow::instanceChanged(const QModelIndex &current, const QModelIndex &
}
ui->actionLaunchInstanceOffline->setEnabled(m_selectedInstance->canLaunch());
ui->actionExportInstance->setEnabled(m_selectedInstance->canExport());
- renameButton->setText(m_selectedInstance->name());
+ ui->renameButton->setText(m_selectedInstance->name());
m_statusLeft->setText(m_selectedInstance->getStatusbarDescription());
updateInstanceToolIcon(m_selectedInstance->iconKey());
@@ -1562,7 +1793,7 @@ void MainWindow::selectionBad()
statusBar()->clearMessage();
ui->instanceToolBar->setEnabled(false);
- renameButton->setText(tr("Rename Instance"));
+ ui->renameButton->setText(tr("Rename Instance"));
updateInstanceToolIcon("infinity");
// ...and then see if we can enable the previously selected instance
diff --git a/application/MainWindow.h b/application/MainWindow.h
index 2a70f17c..e4c281dc 100644
--- a/application/MainWindow.h
+++ b/application/MainWindow.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
#include "minecraft/auth/MojangAccount.h"
#include "net/NetJob.h"
#include "updater/GoUpdate.h"
+#include <modplatform/FtbPackDownloader.h>
class LaunchController;
class NewsChecker;
@@ -74,6 +75,10 @@ private slots:
void on_actionChangeInstGroup_triggered();
void on_actionChangeInstIcon_triggered();
+ void on_changeIconButton_clicked(bool)
+ {
+ on_actionChangeInstIcon_triggered();
+ }
void on_actionViewInstanceFolder_triggered();
@@ -81,11 +86,11 @@ private slots:
void on_actionViewSelectedInstFolder_triggered();
- void on_actionRefresh_triggered();
+ void refreshInstances();
void on_actionViewCentralModsFolder_triggered();
- void on_actionCheckUpdate_triggered();
+ void checkForUpdates();
void on_actionSettings_triggered();
@@ -109,11 +114,15 @@ private slots:
void on_actionDeleteInstance_triggered();
- void on_actionDeleteGroup_triggered();
+ void deleteGroup();
void on_actionExportInstance_triggered();
void on_actionRenameInstance_triggered();
+ void on_renameButton_clicked(bool)
+ {
+ on_actionRenameInstance_triggered();
+ }
void on_actionEditInstance_triggered();
@@ -177,6 +186,7 @@ private:
void runModalTask(Task *task);
void instanceFromVersion(QString instName, QString instGroup, QString instIcon, BaseVersionPtr version);
void instanceFromZipPack(QString instName, QString instGroup, QString instIcon, QUrl url);
+ void instanceFromFtbPack(FtbPackDownloader *downloader, QString instName, QString instGroup, QString instIcon);
void finalizeInstance(InstancePtr inst);
private:
@@ -185,14 +195,11 @@ private:
// these are managed by Qt's memory management model!
GroupView *view = nullptr;
InstanceProxyModel *proxymodel = nullptr;
- LabeledToolButton *renameButton = nullptr;
- QToolButton *changeIconButton = nullptr;
QToolButton *newsLabel = nullptr;
QLabel *m_statusLeft = nullptr;
ServerStatus *m_statusRight = nullptr;
QMenu *accountMenu = nullptr;
QToolButton *accountMenuButton = nullptr;
- QAction *manageAccountsAction = nullptr;
unique_qobject_ptr<NetJob> skin_download_job;
unique_qobject_ptr<NewsChecker> m_newsChecker;
diff --git a/application/MultiMC.cpp b/application/MultiMC.cpp
index c78a536e..f928d11b 100644
--- a/application/MultiMC.cpp
+++ b/application/MultiMC.cpp
@@ -11,6 +11,7 @@
#include "pages/global/AccountListPage.h"
#include "pages/global/PasteEEPage.h"
#include "pages/global/PackagesPage.h"
+#include "pages/global/CustomCommandsPage.h"
#include "themes/ITheme.h"
#include "themes/SystemTheme.h"
@@ -36,13 +37,9 @@
#include "dialogs/CustomMessageBox.h"
#include "InstanceList.h"
#include "FolderInstanceProvider.h"
-#include "minecraft/ftb/FTBInstanceProvider.h"
#include <minecraft/auth/MojangAccountList.h>
#include "icons/IconList.h"
-//FIXME: get rid of this
-#include "minecraft/legacy/LwjglVersionList.h"
-
#include "net/HttpMetaCache.h"
#include "net/URLConstants.h"
#include "Env.h"
@@ -61,8 +58,6 @@
#include "translations/TranslationsModel.h"
-#include "minecraft/ftb/FTBPlugin.h"
-
#include <Commandline.h>
#include <FileSystem.h>
#include <DesktopServices.h>
@@ -71,6 +66,7 @@
#include <ganalytics.h>
#include <sys.h>
+
#if defined Q_OS_WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
@@ -90,6 +86,26 @@ using namespace Commandline;
"This usually fixes the problem and you can move the application elsewhere afterwards.\n"\
"\n"
+static void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+{
+ const char *levels = "DWCFIS";
+ const QString format("%1 %2 %3\n");
+
+ qint64 msecstotal = MMC->timeSinceStart();
+ qint64 seconds = msecstotal / 1000;
+ qint64 msecs = msecstotal % 1000;
+ QString foo;
+ char buf[1025] = {0};
+ ::snprintf(buf, 1024, "%5lld.%03lld", seconds, msecs);
+
+ QString out = format.arg(buf).arg(levels[type]).arg(msg);
+
+ MMC->logFile->write(out.toUtf8());
+ MMC->logFile->flush();
+ QTextStream(stderr) << out.toLocal8Bit();
+ fflush(stderr);
+}
+
MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
{
#if defined Q_OS_WIN32
@@ -207,10 +223,7 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
if (xdgDataHome.isEmpty())
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
dataPath = xdgDataHome + "/multimc";
- printf("BLAH %s", xdgDataHome.toStdString().c_str());
-
adjustedBy += "XDG standard " + dataPath;
-
#else
dataPath = applicationDirPath();
adjustedBy += "Fallback to binary path " + dataPath;
@@ -247,23 +260,70 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
);
return;
}
+
+ /*
+ * Establish the mechanism for communication with an already running MultiMC that uses the same data path.
+ * If there is one, tell it what the user actually wanted to do and exit.
+ * We want to initialize this before logging to avoid messing with the log of a potential already running copy.
+ */
auto appID = ApplicationId::fromPathAndVersion(QDir::currentPath(), BuildConfig.printableVersionString());
- m_peerInstance = new LocalPeer(this, appID);
- connect(m_peerInstance, &LocalPeer::messageReceived, this, &MultiMC::messageReceived);
- if(m_peerInstance->isClient())
{
- if(m_instanceIdToLaunch.isEmpty())
+ // FIXME: you can run the same binaries with multiple data dirs and they won't clash. This could cause issues for updates.
+ m_peerInstance = new LocalPeer(this, appID);
+ connect(m_peerInstance, &LocalPeer::messageReceived, this, &MultiMC::messageReceived);
+ if(m_peerInstance->isClient())
{
- m_peerInstance->sendMessage("activate", 2000);
+ if(m_instanceIdToLaunch.isEmpty())
+ {
+ m_peerInstance->sendMessage("activate", 2000);
+ }
+ else
+ {
+ m_peerInstance->sendMessage(m_instanceIdToLaunch, 2000);
+ }
+ m_status = MultiMC::Succeeded;
+ return;
}
- else
+ }
+
+ // init the logger
+ {
+ static const QString logBase = "MultiMC-%0.log";
+ auto moveFile = [](const QString &oldName, const QString &newName)
+ {
+ QFile::remove(newName);
+ QFile::copy(oldName, newName);
+ QFile::remove(oldName);
+ };
+
+ moveFile(logBase.arg(3), logBase.arg(4));
+ moveFile(logBase.arg(2), logBase.arg(3));
+ moveFile(logBase.arg(1), logBase.arg(2));
+ moveFile(logBase.arg(0), logBase.arg(1));
+
+ logFile = std::unique_ptr<QFile>(new QFile(logBase.arg(0)));
+ if(!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
{
- m_peerInstance->sendMessage(m_instanceIdToLaunch, 2000);
+ showFatalErrorMessage(
+ "MultiMC data folder is not writable!",
+ "MultiMC couldn't create a log file - the MultiMC data folder is not writable.\n"
+ "\n"
+ #if defined(Q_OS_MAC)
+ MACOS_HINT
+ #endif
+ "Make sure you have write permissions to the MultiMC data folder.\n"
+ "\n"
+ "MultiMC cannot continue until you fix this problem."
+ );
+ return;
}
- m_status = MultiMC::Succeeded;
- return;
+ qInstallMessageHandler(appDebugOutput);
+ qDebug() << "<> Log initialized.";
}
+ // Set up paths
+ {
+ // Root path is used for updates.
#ifdef Q_OS_LINUX
QDir foo(FS::PathCombine(binPath, ".."));
m_rootPath = foo.absolutePath();
@@ -272,48 +332,36 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
#elif defined(Q_OS_MAC)
QDir foo(FS::PathCombine(binPath, "../.."));
m_rootPath = foo.absolutePath();
+ // on macOS, touch the root to force Finder to reload the .app metadata (and fix any icon change issues)
+ FS::updateTimestamp(m_rootPath);
#endif
- // init the logger
- if(!initLogger())
- {
- showFatalErrorMessage(
- "MultiMC data folder is not writable!",
- "MultiMC couldn't create a log file - the MultiMC data folder is not writable.\n"
- "\n"
-#if defined(Q_OS_MAC)
- MACOS_HINT
+#ifdef MULTIMC_JARS_LOCATION
+ ENV.setJarsPath( TOSTRING(MULTIMC_JARS_LOCATION) );
#endif
- "Make sure you have write permissions to the MultiMC data folder.\n"
- "\n"
- "MultiMC cannot continue until you fix this problem."
- );
- return;
- }
- qDebug() << "MultiMC 5, (c) 2013-2017 MultiMC Contributors";
- qDebug() << "Version : " << BuildConfig.printableVersionString();
- qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
- qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC;
- if (adjustedBy.size())
- {
- qDebug() << "Work dir before adjustment : " << origcwdPath;
- qDebug() << "Work dir after adjustment : " << QDir::currentPath();
- qDebug() << "Adjusted by : " << adjustedBy;
- }
- else
- {
- qDebug() << "Work dir : " << QDir::currentPath();
- }
- qDebug() << "Binary path : " << binPath;
- qDebug() << "Application root path : " << m_rootPath;
- if(!m_instanceIdToLaunch.isEmpty())
- {
- qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch;
+ qDebug() << "MultiMC 5, (c) 2013-2018 MultiMC Contributors";
+ qDebug() << "Version : " << BuildConfig.printableVersionString();
+ qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
+ qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC;
+ if (adjustedBy.size())
+ {
+ qDebug() << "Work dir before adjustment : " << origcwdPath;
+ qDebug() << "Work dir after adjustment : " << QDir::currentPath();
+ qDebug() << "Adjusted by : " << adjustedBy;
+ }
+ else
+ {
+ qDebug() << "Work dir : " << QDir::currentPath();
+ }
+ qDebug() << "Binary path : " << binPath;
+ qDebug() << "Application root path : " << m_rootPath;
+ if(!m_instanceIdToLaunch.isEmpty())
+ {
+ qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch;
+ }
+ qDebug() << "<> Paths set.";
}
-#ifdef MULTIMC_JARS_LOCATION
- ENV.setJarsPath( TOSTRING(MULTIMC_JARS_LOCATION) );
-#endif
do // once
{
@@ -336,24 +384,251 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
}
} while(false);
- // load settings
- initGlobalSettings();
+ // Initialize application settings
+ {
+ m_settings.reset(new INISettingsObject("multimc.cfg", this));
+ // Updates
+ m_settings->registerSetting("UpdateChannel", BuildConfig.VERSION_CHANNEL);
+ m_settings->registerSetting("AutoUpdate", true);
+
+ // Theming
+ m_settings->registerSetting("IconTheme", QString("multimc"));
+ m_settings->registerSetting("ApplicationTheme", QString("system"));
+
+ // Notifications
+ m_settings->registerSetting("ShownNotifications", QString());
+
+ // Remembered state
+ m_settings->registerSetting("LastUsedGroupForNewInstance", QString());
+
+ QString defaultMonospace;
+ int defaultSize = 11;
+#ifdef Q_OS_WIN32
+ defaultMonospace = "Courier";
+ defaultSize = 10;
+#elif defined(Q_OS_MAC)
+ defaultMonospace = "Menlo";
+#else
+ defaultMonospace = "Monospace";
+#endif
+
+ // resolve the font so the default actually matches
+ QFont consoleFont;
+ consoleFont.setFamily(defaultMonospace);
+ consoleFont.setStyleHint(QFont::Monospace);
+ consoleFont.setFixedPitch(true);
+ QFontInfo consoleFontInfo(consoleFont);
+ QString resolvedDefaultMonospace = consoleFontInfo.family();
+ QFont resolvedFont(resolvedDefaultMonospace);
+ qDebug() << "Detected default console font:" << resolvedDefaultMonospace
+ << ", substitutions:" << resolvedFont.substitutions().join(',');
+
+ m_settings->registerSetting("ConsoleFont", resolvedDefaultMonospace);
+ m_settings->registerSetting("ConsoleFontSize", defaultSize);
+ m_settings->registerSetting("ConsoleMaxLines", 100000);
+ m_settings->registerSetting("ConsoleOverflowStop", true);
+
+ // Folders
+ m_settings->registerSetting("InstanceDir", "instances");
+ m_settings->registerSetting({"CentralModsDir", "ModsDir"}, "mods");
+ m_settings->registerSetting("IconsDir", "icons");
+
+ // Editors
+ m_settings->registerSetting("JsonEditor", QString());
+
+ // Language
+ m_settings->registerSetting("Language", QString());
+
+ // Console
+ m_settings->registerSetting("ShowConsole", false);
+ m_settings->registerSetting("AutoCloseConsole", false);
+ m_settings->registerSetting("ShowConsoleOnError", true);
+ m_settings->registerSetting("LogPrePostOutput", true);
+
+ // Window Size
+ m_settings->registerSetting({"LaunchMaximized", "MCWindowMaximize"}, false);
+ m_settings->registerSetting({"MinecraftWinWidth", "MCWindowWidth"}, 854);
+ m_settings->registerSetting({"MinecraftWinHeight", "MCWindowHeight"}, 480);
+
+ // Proxy Settings
+ m_settings->registerSetting("ProxyType", "None");
+ 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);
+ m_settings->registerSetting("PermGen", 128);
+
+ // Java Settings
+ m_settings->registerSetting("JavaPath", "");
+ m_settings->registerSetting("JavaTimestamp", 0);
+ m_settings->registerSetting("JavaArchitecture", "");
+ m_settings->registerSetting("JavaVersion", "");
+ m_settings->registerSetting("LastHostname", "");
+ m_settings->registerSetting("JvmArgs", "");
+
+ // Minecraft launch method
+ m_settings->registerSetting("MCLaunchMethod", "LauncherPart");
+
+ // Wrapper command for launch
+ m_settings->registerSetting("WrapperCommand", "");
+
+ // Custom Commands
+ m_settings->registerSetting({"PreLaunchCommand", "PreLaunchCmd"}, "");
+ m_settings->registerSetting({"PostExitCommand", "PostExitCmd"}, "");
+
+ // The cat
+ m_settings->registerSetting("TheCat", false);
+
+ m_settings->registerSetting("InstSortMode", "Name");
+ m_settings->registerSetting("SelectedInstance", QString());
+
+ // Window state and geometry
+ m_settings->registerSetting("MainWindowState", "");
+ m_settings->registerSetting("MainWindowGeometry", "");
+
+ m_settings->registerSetting("ConsoleWindowState", "");
+ m_settings->registerSetting("ConsoleWindowGeometry", "");
+
+ m_settings->registerSetting("SettingsGeometry", "");
+
+ m_settings->registerSetting("PagedGeometry", "");
+
+ m_settings->registerSetting("UpdateDialogGeometry", "");
+
+ // paste.ee API key
+ m_settings->registerSetting("PasteEEAPIKey", "multimc");
+
+ if(!BuildConfig.ANALYTICS_ID.isEmpty())
+ {
+ // Analytics
+ m_settings->registerSetting("Analytics", true);
+ m_settings->registerSetting("AnalyticsSeen", 0);
+ m_settings->registerSetting("AnalyticsClientID", QString());
+ }
+
+ // Init page provider
+ {
+ m_globalSettingsProvider = std::make_shared<GenericPageProvider>(tr("Settings"));
+ m_globalSettingsProvider->addPage<MultiMCPage>();
+ m_globalSettingsProvider->addPage<MinecraftPage>();
+ m_globalSettingsProvider->addPage<JavaPage>();
+ m_globalSettingsProvider->addPage<CustomCommandsPage>();
+ m_globalSettingsProvider->addPage<ProxyPage>();
+ // m_globalSettingsProvider->addPage<PackagesPage>();
+ m_globalSettingsProvider->addPage<ExternalToolsPage>();
+ m_globalSettingsProvider->addPage<AccountListPage>();
+ m_globalSettingsProvider->addPage<PasteEEPage>();
+ }
+ qDebug() << "<> Settings loaded.";
+ }
// load translations
- initTranslations();
+ {
+ m_translations.reset(new TranslationsModel("translations"));
+ auto bcp47Name = m_settings->get("Language").toString();
+ m_translations->selectLanguage(bcp47Name);
+ qDebug() << "Your language is" << bcp47Name;
+ qDebug() << "<> Translations loaded.";
+ }
// initialize the updater
if(BuildConfig.UPDATER_ENABLED)
{
m_updateChecker.reset(new UpdateChecker(BuildConfig.CHANLIST_URL, BuildConfig.VERSION_CHANNEL, BuildConfig.VERSION_BUILD));
+ qDebug() << "<> Updater started.";
}
- initIcons();
- initThemes();
- initInstances();
- initAccounts();
- initNetwork();
- initLegacyLwjgl();
+ // Instance icons
+ {
+ auto setting = MMC->settings()->getSetting("IconsDir");
+ QStringList instFolders =
+ {
+ ":/icons/multimc/32x32/instances/",
+ ":/icons/multimc/50x50/instances/",
+ ":/icons/multimc/128x128/instances/"
+ };
+ m_icons.reset(new IconList(instFolders, setting->get().toString()));
+ connect(setting.get(), &Setting::SettingChanged,[&](const Setting &, QVariant value)
+ {
+ m_icons->directoryChanged(value.toString());
+ });
+ ENV.registerIconList(m_icons);
+ qDebug() << "<> Instance icons intialized.";
+ }
+
+ // Icon themes
+ {
+ // TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies!
+ // set icon theme search path!
+ auto searchPaths = QIcon::themeSearchPaths();
+ searchPaths.append("iconthemes");
+ QIcon::setThemeSearchPaths(searchPaths);
+ qDebug() << "<> Icon themes initialized.";
+ }
+
+ // Initialize widget themes
+ {
+ auto insertTheme = [this](ITheme * theme)
+ {
+ m_themes.insert(std::make_pair(theme->id(), std::unique_ptr<ITheme>(theme)));
+ };
+ auto darkTheme = new DarkTheme();
+ insertTheme(new SystemTheme());
+ insertTheme(darkTheme);
+ insertTheme(new BrightTheme());
+ insertTheme(new CustomTheme(darkTheme, "custom"));
+ qDebug() << "<> Widget themes initialized.";
+ }
+
+ // initialize and load all instances
+ {
+ auto InstDirSetting = m_settings->getSetting("InstanceDir");
+ // instance path: check for problems with '!' in instance path and warn the user in the log
+ // and rememer that we have to show him a dialog when the gui starts (if it does so)
+ QString instDir = InstDirSetting->get().toString();
+ qDebug() << "Instance path : " << instDir;
+ if (FS::checkProblemticPathJava(QDir(instDir)))
+ {
+ qWarning() << "Your instance path contains \'!\' and this is known to cause java problems";
+ }
+ m_instances.reset(new InstanceList(this));
+ m_instanceFolder = new FolderInstanceProvider(m_settings, instDir);
+ connect(InstDirSetting.get(), &Setting::SettingChanged, m_instanceFolder, &FolderInstanceProvider::on_InstFolderChanged);
+ m_instances->addInstanceProvider(m_instanceFolder);
+ qDebug() << "Loading Instances...";
+ m_instances->loadList(true);
+ qDebug() << "<> Instances loaded.";
+ }
+
+ // and accounts
+ {
+ m_accounts.reset(new MojangAccountList(this));
+ qDebug() << "Loading accounts...";
+ m_accounts->setListFilePath("accounts.json", true);
+ m_accounts->loadList();
+ qDebug() << "<> Accounts loaded.";
+ }
+
+ // init the http meta cache
+ {
+ ENV.initHttpMetaCache();
+ qDebug() << "<> Cache initialized.";
+ }
+
+ // init proxy settings
+ {
+ QString proxyTypeStr = settings()->get("ProxyType").toString();
+ 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();
+ ENV.updateProxySettings(proxyTypeStr, addr, port, user, pass);
+ qDebug() << "<> Proxy settings done.";
+ }
// now we have network, download translation updates
m_translations->downloadIndex();
@@ -366,14 +641,69 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
profiler->registerSettings(m_settings);
}
- initMCEdit();
+ // Create the MCEdit thing... why is this here?
+ {
+ m_mcedit.reset(new MCEditTool(m_settings));
+ }
+
+ connect(this, &MultiMC::aboutToQuit, [this](){
+ if(m_instances)
+ {
+ // save any remaining instance state
+ m_instances->saveNow();
+ }
+ if(logFile)
+ {
+ logFile->flush();
+ logFile->close();
+ }
+ });
+
+ {
+ setIconTheme(settings()->get("IconTheme").toString());
+ qDebug() << "<> Icon theme set.";
+ setApplicationTheme(settings()->get("ApplicationTheme").toString(), true);
+ qDebug() << "<> Application theme set.";
+ }
+
+ // Initialize analytics
+ [this]()
+ {
+ const int analyticsVersion = 2;
+ if(BuildConfig.ANALYTICS_ID.isEmpty())
+ {
+ return;
+ }
- connect(this, SIGNAL(aboutToQuit()), SLOT(onExit()));
+ auto analyticsSetting = m_settings->getSetting("Analytics");
+ connect(analyticsSetting.get(), &Setting::SettingChanged, this, &MultiMC::analyticsSettingChanged);
+ QString clientID = m_settings->get("AnalyticsClientID").toString();
+ if(clientID.isEmpty())
+ {
+ clientID = QUuid::createUuid().toString();
+ clientID.remove(QLatin1Char('{'));
+ clientID.remove(QLatin1Char('}'));
+ m_settings->set("AnalyticsClientID", clientID);
+ }
+ m_analytics = new GAnalytics(BuildConfig.ANALYTICS_ID, clientID, analyticsVersion, this);
+ m_analytics->setLogLevel(GAnalytics::Debug);
+ m_analytics->setAnonymizeIPs(true);
+ m_analytics->setNetworkAccessManager(&ENV.qnam());
- setIconTheme(settings()->get("IconTheme").toString());
- setApplicationTheme(settings()->get("ApplicationTheme").toString(), true);
+ if(m_settings->get("AnalyticsSeen").toInt() < m_analytics->version())
+ {
+ qDebug() << "Analytics info not seen by user yet (or old version).";
+ return;
+ }
+ if(!m_settings->get("Analytics").toBool())
+ {
+ qDebug() << "Analytics disabled by user.";
+ return;
+ }
- initAnalytics();
+ m_analytics->enable();
+ qDebug() << "<> Initialized analytics with tid" << BuildConfig.ANALYTICS_ID;
+ }();
if(createSetupWizard())
{
@@ -461,6 +791,7 @@ void MultiMC::performMainStartupAction()
auto inst = instances()->getInstanceById(m_instanceIdToLaunch);
if(inst)
{
+ qDebug() << "<> Instance launching:" << m_instanceIdToLaunch;
launch(inst, true, nullptr);
return;
}
@@ -469,6 +800,7 @@ void MultiMC::performMainStartupAction()
{
// normal main window
showMainWindow(false);
+ qDebug() << "<> Main window shown.";
}
}
@@ -481,17 +813,22 @@ void MultiMC::showFatalErrorMessage(const QString& title, const QString& content
MultiMC::~MultiMC()
{
+ // kill the other globals.
+ Env::dispose();
+
+ // Shut down logger by setting the logger function to nothing
+ qInstallMessageHandler(nullptr);
+
#if defined Q_OS_WIN32
+ // Detach from Windows console
if(consoleAttached)
{
- const char * endline = "\n";
- auto out = GetStdHandle (STD_OUTPUT_HANDLE);
- DWORD written;
- WriteConsole(out, endline, strlen(endline), &written, NULL);
+ fclose(stdout);
+ fclose(stdin);
+ fclose(stderr);
+ FreeConsole();
}
#endif
- shutdownLogger();
- Env::dispose();
}
void MultiMC::messageReceived(const QString& message)
@@ -515,149 +852,6 @@ void MultiMC::messageReceived(const QString& message)
}
}
-void MultiMC::initNetwork()
-{
- // init the http meta cache
- ENV.initHttpMetaCache();
-
- // init proxy settings
- {
- QString proxyTypeStr = settings()->get("ProxyType").toString();
- 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();
- ENV.updateProxySettings(proxyTypeStr, addr, port, user, pass);
- }
-}
-
-void MultiMC::initTranslations()
-{
- m_translations.reset(new TranslationsModel("translations"));
- auto bcp47Name = m_settings->get("Language").toString();
- m_translations->selectLanguage(bcp47Name);
- qDebug() << "Your language is" << bcp47Name;
-}
-
-void MultiMC::initIcons()
-{
- auto setting = MMC->settings()->getSetting("IconsDir");
- QStringList instFolders =
- {
- ":/icons/multimc/32x32/instances/",
- ":/icons/multimc/50x50/instances/",
- ":/icons/multimc/128x128/instances/"
- };
- m_icons.reset(new IconList(instFolders, setting->get().toString()));
- connect(setting.get(), &Setting::SettingChanged,[&](const Setting &, QVariant value)
- {
- m_icons->directoryChanged(value.toString());
- });
- ENV.registerIconList(m_icons);
-
- // set icon theme search path!
- auto searchPaths = QIcon::themeSearchPaths();
- searchPaths.append("iconthemes");
- QIcon::setThemeSearchPaths(searchPaths);
-}
-
-void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
-{
- const char *levels = "DWCFIS";
- const QString format("%1 %2 %3\n");
-
- qint64 msecstotal = MMC->timeSinceStart();
- qint64 seconds = msecstotal / 1000;
- qint64 msecs = msecstotal % 1000;
- QString foo;
- char buf[1025] = {0};
- ::snprintf(buf, 1024, "%5lld.%03lld", seconds, msecs);
-
- QString out = format.arg(buf).arg(levels[type]).arg(msg);
-
- MMC->logFile->write(out.toUtf8());
- MMC->logFile->flush();
- QTextStream(stderr) << out.toLocal8Bit();
- fflush(stderr);
-}
-
-static void moveFile(const QString &oldName, const QString &newName)
-{
- QFile::remove(newName);
- QFile::copy(oldName, newName);
- QFile::remove(oldName);
-}
-
-bool MultiMC::initLogger()
-{
- static const QString logBase = "MultiMC-%0.log";
-
- moveFile(logBase.arg(3), logBase.arg(4));
- moveFile(logBase.arg(2), logBase.arg(3));
- moveFile(logBase.arg(1), logBase.arg(2));
- moveFile(logBase.arg(0), logBase.arg(1));
-
- logFile = std::unique_ptr<QFile>(new QFile(logBase.arg(0)));
- auto succeeded = logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
- if(!succeeded)
- {
- return false;
- }
- qInstallMessageHandler(appDebugOutput);
- return true;
-}
-
-void MultiMC::shutdownLogger()
-{
- qInstallMessageHandler(nullptr);
-}
-
-void MultiMC::initAnalytics()
-{
- const int analyticsVersion = 2;
- if(BuildConfig.ANALYTICS_ID.isEmpty())
- {
- return;
- }
-
- auto analyticsSetting = m_settings->getSetting("Analytics");
- connect(analyticsSetting.get(), &Setting::SettingChanged, this, &MultiMC::analyticsSettingChanged);
- QString clientID = m_settings->get("AnalyticsClientID").toString();
- if(clientID.isEmpty())
- {
- clientID = QUuid::createUuid().toString();
- clientID.remove(QLatin1Char('{'));
- clientID.remove(QLatin1Char('}'));
- m_settings->set("AnalyticsClientID", clientID);
- }
- m_analytics = new GAnalytics(BuildConfig.ANALYTICS_ID, clientID, analyticsVersion, this);
- m_analytics->setLogLevel(GAnalytics::Debug);
- m_analytics->setAnonymizeIPs(true);
- m_analytics->setNetworkAccessManager(&ENV.qnam());
-
- if(m_settings->get("AnalyticsSeen").toInt() < m_analytics->version())
- {
- qDebug() << "Analytics info not seen by user yet (or old version).";
- return;
- }
- if(!m_settings->get("Analytics").toBool())
- {
- qDebug() << "Analytics disabled by user.";
- return;
- }
-
- m_analytics->enable();
- qDebug() << "Initialized analytics with tid" << BuildConfig.ANALYTICS_ID;
-}
-
-void MultiMC::shutdownAnalytics()
-{
- if(m_analytics)
- {
- // TODO: persist unsent messages? send them now?
- }
-}
-
void MultiMC::analyticsSettingChanged(const Setting&, QVariant value)
{
if(!m_analytics)
@@ -674,217 +868,16 @@ void MultiMC::analyticsSettingChanged(const Setting&, QVariant value)
m_analytics->enable(enabled);
}
-void MultiMC::initInstances()
-{
- auto InstDirSetting = m_settings->getSetting("InstanceDir");
- // instance path: check for problems with '!' in instance path and warn the user in the log
- // and rememer that we have to show him a dialog when the gui starts (if it does so)
- QString instDir = m_settings->get("InstanceDir").toString();
- qDebug() << "Instance path : " << instDir;
- if (FS::checkProblemticPathJava(QDir(instDir)))
- {
- qWarning() << "Your instance path contains \'!\' and this is known to cause java problems";
- }
- m_instances.reset(new InstanceList(m_settings, InstDirSetting->get().toString(), this));
- m_instanceFolder = new FolderInstanceProvider(m_settings, instDir);
- connect(InstDirSetting.get(), &Setting::SettingChanged, m_instanceFolder, &FolderInstanceProvider::on_InstFolderChanged);
- m_instances->addInstanceProvider(m_instanceFolder);
- m_instances->addInstanceProvider(new FTBInstanceProvider(m_settings));
- qDebug() << "Loading Instances...";
- m_instances->loadList(true);
-}
-
-void MultiMC::initAccounts()
-{
- // and accounts
- m_accounts.reset(new MojangAccountList(this));
- qDebug() << "Loading accounts...";
- m_accounts->setListFilePath("accounts.json", true);
- m_accounts->loadList();
-}
-
-void MultiMC::initGlobalSettings()
-{
- m_settings.reset(new INISettingsObject("multimc.cfg", this));
- // Updates
- m_settings->registerSetting("UpdateChannel", BuildConfig.VERSION_CHANNEL);
- m_settings->registerSetting("AutoUpdate", true);
-
- // Theming
- m_settings->registerSetting("IconTheme", QString("multimc"));
- m_settings->registerSetting("ApplicationTheme", QString("system"));
-
- // Notifications
- m_settings->registerSetting("ShownNotifications", QString());
-
- // Remembered state
- m_settings->registerSetting("LastUsedGroupForNewInstance", QString());
-
- QString defaultMonospace;
- int defaultSize = 11;
-#ifdef Q_OS_WIN32
- defaultMonospace = "Courier";
- defaultSize = 10;
-#elif defined(Q_OS_MAC)
- defaultMonospace = "Menlo";
-#else
- defaultMonospace = "Monospace";
-#endif
-
- // resolve the font so the default actually matches
- QFont consoleFont;
- consoleFont.setFamily(defaultMonospace);
- consoleFont.setStyleHint(QFont::Monospace);
- consoleFont.setFixedPitch(true);
- QFontInfo consoleFontInfo(consoleFont);
- QString resolvedDefaultMonospace = consoleFontInfo.family();
- QFont resolvedFont(resolvedDefaultMonospace);
- qDebug() << "Detected default console font:" << resolvedDefaultMonospace
- << ", substitutions:" << resolvedFont.substitutions().join(',');
-
- m_settings->registerSetting("ConsoleFont", resolvedDefaultMonospace);
- m_settings->registerSetting("ConsoleFontSize", defaultSize);
- m_settings->registerSetting("ConsoleMaxLines", 100000);
- m_settings->registerSetting("ConsoleOverflowStop", true);
-
- FTBPlugin::initialize(m_settings);
-
- // Folders
- m_settings->registerSetting("InstanceDir", "instances");
- m_settings->registerSetting({"CentralModsDir", "ModsDir"}, "mods");
- m_settings->registerSetting({"LWJGLDir", "LwjglDir"}, "lwjgl");
- m_settings->registerSetting("IconsDir", "icons");
-
- // Editors
- m_settings->registerSetting("JsonEditor", QString());
-
- // Language
- m_settings->registerSetting("Language", QString());
-
- // Console
- m_settings->registerSetting("ShowConsole", false);
- m_settings->registerSetting("AutoCloseConsole", false);
- m_settings->registerSetting("ShowConsoleOnError", true);
- m_settings->registerSetting("LogPrePostOutput", true);
-
- // Console Colors
- // m_settings->registerSetting("SysMessageColor", QColor(Qt::blue));
- // m_settings->registerSetting("StdOutColor", QColor(Qt::black));
- // m_settings->registerSetting("StdErrColor", QColor(Qt::red));
-
- // Window Size
- m_settings->registerSetting({"LaunchMaximized", "MCWindowMaximize"}, false);
- m_settings->registerSetting({"MinecraftWinWidth", "MCWindowWidth"}, 854);
- m_settings->registerSetting({"MinecraftWinHeight", "MCWindowHeight"}, 480);
-
- // Proxy Settings
- m_settings->registerSetting("ProxyType", "None");
- 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);
- m_settings->registerSetting("PermGen", 128);
-
- // Java Settings
- m_settings->registerSetting("JavaPath", "");
- m_settings->registerSetting("JavaTimestamp", 0);
- m_settings->registerSetting("JavaArchitecture", "");
- m_settings->registerSetting("JavaVersion", "");
- m_settings->registerSetting("LastHostname", "");
- m_settings->registerSetting("JvmArgs", "");
-
- // Minecraft launch method
- m_settings->registerSetting("MCLaunchMethod", "LauncherPart");
-
- // Wrapper command for launch
- m_settings->registerSetting("WrapperCommand", "");
-
- // Custom Commands
- m_settings->registerSetting({"PreLaunchCommand", "PreLaunchCmd"}, "");
- m_settings->registerSetting({"PostExitCommand", "PostExitCmd"}, "");
-
- // The cat
- m_settings->registerSetting("TheCat", false);
-
- m_settings->registerSetting("InstSortMode", "Name");
- m_settings->registerSetting("SelectedInstance", QString());
-
- // Window state and geometry
- m_settings->registerSetting("MainWindowState", "");
- m_settings->registerSetting("MainWindowGeometry", "");
-
- m_settings->registerSetting("ConsoleWindowState", "");
- m_settings->registerSetting("ConsoleWindowGeometry", "");
-
- m_settings->registerSetting("SettingsGeometry", "");
-
- m_settings->registerSetting("PagedGeometry", "");
-
- m_settings->registerSetting("UpdateDialogGeometry", "");
-
- // Jar mod nag dialog in version page
- m_settings->registerSetting("JarModNagSeen", false);
-
- // paste.ee API key
- m_settings->registerSetting("PasteEEAPIKey", "multimc");
-
- if(!BuildConfig.ANALYTICS_ID.isEmpty())
- {
- // Analytics
- m_settings->registerSetting("Analytics", true);
- m_settings->registerSetting("AnalyticsSeen", 0);
- m_settings->registerSetting("AnalyticsClientID", QString());
- }
-
- // Init page provider
- {
- m_globalSettingsProvider = std::make_shared<GenericPageProvider>(tr("Settings"));
- m_globalSettingsProvider->addPage<MultiMCPage>();
- m_globalSettingsProvider->addPage<MinecraftPage>();
- m_globalSettingsProvider->addPage<JavaPage>();
- m_globalSettingsProvider->addPage<ProxyPage>();
- m_globalSettingsProvider->addPage<PackagesPage>();
- m_globalSettingsProvider->addPage<ExternalToolsPage>();
- m_globalSettingsProvider->addPage<AccountListPage>();
- m_globalSettingsProvider->addPage<PasteEEPage>();
- }
-}
-
-void MultiMC::initMCEdit()
-{
- m_mcedit.reset(new MCEditTool(m_settings));
-}
-
-void MultiMC::initLegacyLwjgl()
-{
- auto list = lwjgllist();
-}
-
std::shared_ptr<TranslationsModel> MultiMC::translations()
{
return m_translations;
}
-std::shared_ptr<LWJGLVersionList> MultiMC::lwjgllist()
-{
- if (!m_lwjgllist)
- {
- m_lwjgllist.reset(new LWJGLVersionList());
- ENV.registerVersionList("org.lwjgl.legacy", m_lwjgllist);
- }
- return m_lwjgllist;
-}
-
std::shared_ptr<JavaInstallList> MultiMC::javalist()
{
if (!m_javalist)
{
m_javalist.reset(new JavaInstallList());
- ENV.registerVersionList("com.java", m_javalist);
}
return m_javalist;
}
@@ -901,19 +894,6 @@ std::vector<ITheme *> MultiMC::getValidApplicationThemes()
return ret;
}
-void MultiMC::initThemes()
-{
- auto insertTheme = [this](ITheme * theme)
- {
- m_themes.insert(std::make_pair(theme->id(), std::unique_ptr<ITheme>(theme)));
- };
- auto darkTheme = new DarkTheme();
- insertTheme(new SystemTheme());
- insertTheme(darkTheme);
- insertTheme(new BrightTheme());
- insertTheme(new CustomTheme(darkTheme, "custom"));
-}
-
void MultiMC::setApplicationTheme(const QString& name, bool initial)
{
auto systemPalette = qApp->palette();
@@ -939,19 +919,6 @@ QIcon MultiMC::getThemedIcon(const QString& name)
return XdgIcon::fromTheme(name);
}
-void MultiMC::onExit()
-{
- if(m_instances)
- {
- // m_instances->saveGroupList();
- }
- if(logFile)
- {
- logFile->flush();
- logFile->close();
- }
-}
-
bool MultiMC::openJsonEditor(const QString &filename)
{
const QString file = QDir::current().absoluteFilePath(filename);
@@ -1007,6 +974,11 @@ bool MultiMC::launch(InstancePtr instance, bool online, BaseProfilerFactory *pro
showInstanceWindow(instance, "console");
return true;
}
+ else if (instance->canEdit())
+ {
+ showInstanceWindow(instance);
+ return true;
+ }
return false;
}
@@ -1159,8 +1131,19 @@ MainWindow* MultiMC::showMainWindow(bool minimized)
* cd4 = CPU architecture
*/
QVariantMap customValues;
- customValues["cm1"] = m_settings->get("MinMemAlloc");
- customValues["cm2"] = m_settings->get("MaxMemAlloc");
+ int min = m_settings->get("MinMemAlloc").toInt();
+ int max = m_settings->get("MaxMemAlloc").toInt();
+ if(min < max)
+ {
+ customValues["cm1"] = min;
+ customValues["cm2"] = max;
+ }
+ else
+ {
+ customValues["cm1"] = max;
+ customValues["cm2"] = min;
+ }
+
constexpr uint64_t Mega = 1024ull * 1024ull;
int ramSize = int(Sys::getSystemRam() / Mega);
qDebug() << "RAM size is" << ramSize << "MB";
@@ -1232,5 +1215,3 @@ void MultiMC::on_windowClose()
exit(0);
}
}
-
-#include "MultiMC.moc"
diff --git a/application/MultiMC.h b/application/MultiMC.h
index c9bba2f8..e93d8a69 100644
--- a/application/MultiMC.h
+++ b/application/MultiMC.h
@@ -18,7 +18,6 @@ class SetupWizard;
class FolderInstanceProvider;
class GenericPageProvider;
class QFile;
-class LWJGLVersionList;
class HttpMetaCache;
class SettingsObject;
class InstanceList;
@@ -91,7 +90,7 @@ public:
}
std::shared_ptr<TranslationsModel> translations();
- std::shared_ptr<LWJGLVersionList> lwjgllist();
+
std::shared_ptr<JavaInstallList> javalist();
std::shared_ptr<InstanceList> instances() const
@@ -144,11 +143,6 @@ public:
InstanceWindow *showInstanceWindow(InstancePtr instance, QString page = QString());
MainWindow *showMainWindow(bool minimized = false);
- size_t numRunningInstances()
- {
- return m_runningInstances;
- }
-
void updateIsRunning(bool running);
bool updatesAreAllowed();
@@ -160,10 +154,6 @@ public slots:
bool kill(InstancePtr instance);
private slots:
- /**
- * Do all the things that should be done before we exit
- */
- void onExit();
void on_windowClose();
void messageReceived(const QString & message);
void controllerSucceeded();
@@ -172,19 +162,6 @@ private slots:
void setupWizardFinished(int status);
private:
- bool initLogger();
- void shutdownLogger();
- void initIcons();
- void initThemes();
- void initGlobalSettings();
- void initTranslations();
- void initNetwork();
- void initInstances();
- void initAccounts();
- void initMCEdit();
- void initAnalytics();
- void initLegacyLwjgl();
- void shutdownAnalytics();
bool createSetupWizard();
void performMainStartupAction();
@@ -205,7 +182,6 @@ private:
std::shared_ptr<IconList> m_icons;
std::shared_ptr<UpdateChecker> m_updateChecker;
std::shared_ptr<MojangAccountList> m_accounts;
- std::shared_ptr<LWJGLVersionList> m_lwjgllist;
std::shared_ptr<JavaInstallList> m_javalist;
std::shared_ptr<TranslationsModel> m_translations;
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
@@ -217,8 +193,10 @@ private:
QString m_rootPath;
Status m_status = MultiMC::StartingUp;
+#if defined Q_OS_WIN32
// used on Windows to attach the standard IO streams
bool consoleAttached = false;
+#endif
// FIXME: attach to instances instead.
struct InstanceXtras
diff --git a/application/VersionProxyModel.cpp b/application/VersionProxyModel.cpp
index 96bdc9ab..0dbc4ef6 100644
--- a/application/VersionProxyModel.cpp
+++ b/application/VersionProxyModel.cpp
@@ -369,6 +369,24 @@ QModelIndex VersionProxyModel::getRecommended() const
return index(recommended, 0);
}
+QModelIndex VersionProxyModel::getVersion(const QString& version) const
+{
+ int found = -1;
+ for (int i = 0; i < rowCount(); i++)
+ {
+ auto value = sourceModel()->data(mapToSource(index(i, 0)), BaseVersionList::VersionRole);
+ if (value.toString() == version)
+ {
+ found = i;
+ }
+ }
+ if(found == -1)
+ {
+ return QModelIndex();
+ }
+ return index(found, 0);
+}
+
void VersionProxyModel::clearFilters()
{
m_filters.clear();
diff --git a/application/VersionProxyModel.h b/application/VersionProxyModel.h
index 19e89271..4441ea6b 100644
--- a/application/VersionProxyModel.h
+++ b/application/VersionProxyModel.h
@@ -42,6 +42,7 @@ public:
void setFilter(const BaseVersionList::ModelRoles column, const QString &filter, const bool exact);
void clearFilters();
QModelIndex getRecommended() const;
+ QModelIndex getVersion(const QString & version) const;
private slots:
void sourceDataChanged(const QModelIndex &source_top_left,const QModelIndex &source_bottom_right);
diff --git a/application/dialogs/AboutDialog.cpp b/application/dialogs/AboutDialog.cpp
index 3d16f5c3..8f2e72c2 100644
--- a/application/dialogs/AboutDialog.cpp
+++ b/application/dialogs/AboutDialog.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -93,7 +93,7 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia
ui->urlLabel->setOpenExternalLinks(true);
- ui->icon->setPixmap(MMC->getThemedIcon("multimc").pixmap(64));
+ ui->icon->setPixmap(MMC->getThemedIcon("logo").pixmap(64));
ui->title->setText("MultiMC 5");
ui->versionLabel->setText(tr("Version") +": " + BuildConfig.printableVersionString());
diff --git a/application/dialogs/AboutDialog.h b/application/dialogs/AboutDialog.h
index 65c3628d..9768b866 100644
--- a/application/dialogs/AboutDialog.h
+++ b/application/dialogs/AboutDialog.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/AboutDialog.ui b/application/dialogs/AboutDialog.ui
index d1cafcb2..5e8e3e68 100644
--- a/application/dialogs/AboutDialog.ui
+++ b/application/dialogs/AboutDialog.ui
@@ -165,7 +165,7 @@
</font>
</property>
<property name="text">
- <string>© 2012-2017 MultiMC Contributors</string>
+ <string>© 2012-2018 MultiMC Contributors</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -180,7 +180,7 @@
</font>
</property>
<property name="text">
- <string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://github.com/MultiMC/MultiMC5&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://github.com/MultiMC/MultiMC5&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://github.com/MultiMC/MultiMC5&quot;&gt;http://github.com/MultiMC/MultiMC5&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
diff --git a/application/dialogs/ChooseFtbPackDialog.cpp b/application/dialogs/ChooseFtbPackDialog.cpp
new file mode 100644
index 00000000..ae7c72e1
--- /dev/null
+++ b/application/dialogs/ChooseFtbPackDialog.cpp
@@ -0,0 +1,64 @@
+#include "ChooseFtbPackDialog.h"
+#include "widgets/FtbModpackListItem.h"
+
+ChooseFtbPackDialog::ChooseFtbPackDialog(FtbModpackList modpacks) : ui(new Ui::ChooseFtbPackDialog) {
+ ui->setupUi(this);
+
+ for(int i = 0; i < modpacks.size(); i++) {
+ FtbModpackListItem *item = new FtbModpackListItem(ui->packList, modpacks.at(i));
+
+ item->setText(modpacks.at(i).name);
+ }
+
+ //TODO: Use a model/view instead of a widget
+ connect(ui->packList, &QListWidget::itemClicked, this, &ChooseFtbPackDialog::onListItemClicked);
+ connect(ui->packVersionSelection, &QComboBox::currentTextChanged, this, &ChooseFtbPackDialog::onVersionSelectionItemChanged);
+
+ ui->modpackInfo->setOpenExternalLinks(true);
+
+}
+
+ChooseFtbPackDialog::~ChooseFtbPackDialog(){
+ delete ui;
+}
+
+void ChooseFtbPackDialog::onListItemClicked(QListWidgetItem *item){
+ ui->packVersionSelection->clear();
+ FtbModpack selectedPack = static_cast<FtbModpackListItem*>(item)->getModpack();
+
+ ui->modpackInfo->setHtml("Pack by <b>" + selectedPack.author + "</b>" + "<br>Minecraft " + selectedPack.mcVersion + "<br>"
+ "<br>" + selectedPack.description + "<ul><li>" + selectedPack.mods.replace(";", "</li><li>") + "</li></ul>");
+
+ bool currentAdded = false;
+
+ for(int i = 0; i < selectedPack.oldVersions.size(); i++) {
+ if(selectedPack.currentVersion == selectedPack.oldVersions.at(i)) {
+ currentAdded = true;
+ }
+ ui->packVersionSelection->addItem(selectedPack.oldVersions.at(i));
+ }
+
+ if(!currentAdded) {
+ ui->packVersionSelection->addItem(selectedPack.currentVersion);
+ }
+
+ selected = selectedPack;
+
+}
+
+void ChooseFtbPackDialog::onVersionSelectionItemChanged(QString data) {
+ if(data.isNull() || data.isEmpty()) {
+ selectedVersion = "";
+ return;
+ }
+
+ selectedVersion = data;
+}
+
+FtbModpack ChooseFtbPackDialog::getSelectedModpack() {
+ return selected;
+}
+
+QString ChooseFtbPackDialog::getSelectedVersion() {
+ return selectedVersion;
+}
diff --git a/application/dialogs/ChooseFtbPackDialog.h b/application/dialogs/ChooseFtbPackDialog.h
new file mode 100644
index 00000000..212aa27b
--- /dev/null
+++ b/application/dialogs/ChooseFtbPackDialog.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <QDialog>
+#include <net/NetJob.h>
+#include <modplatform/PackHelpers.h>
+#include "ui_ChooseFtbPackDialog.h"
+#include <modplatform/PackHelpers.h>
+
+namespace Ui {
+ class ChooseFtbPackDialog;
+}
+
+class ChooseFtbPackDialog : public QDialog {
+
+ Q_OBJECT
+
+private:
+ Ui::ChooseFtbPackDialog *ui;
+ FtbModpack selected;
+ QString selectedVersion;
+
+private slots:
+ void onListItemClicked(QListWidgetItem *item);
+ void onVersionSelectionItemChanged(QString data);
+
+public:
+ ChooseFtbPackDialog(FtbModpackList packs);
+ ~ChooseFtbPackDialog();
+
+ FtbModpack getSelectedModpack();
+ QString getSelectedVersion();
+};
diff --git a/application/dialogs/ChooseFtbPackDialog.ui b/application/dialogs/ChooseFtbPackDialog.ui
new file mode 100644
index 00000000..fdf845a9
--- /dev/null
+++ b/application/dialogs/ChooseFtbPackDialog.ui
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ChooseFtbPackDialog</class>
+ <widget class="QDialog" name="ChooseFtbPackDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>730</width>
+ <height>437</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>false</bool>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="geometry">
+ <rect>
+ <x>540</x>
+ <y>400</y>
+ <width>176</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ <widget class="QScrollArea" name="scrollArea">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>261</width>
+ <height>381</height>
+ </rect>
+ </property>
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="scrollAreaWidgetContents">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>259</width>
+ <height>379</height>
+ </rect>
+ </property>
+ <widget class="QListWidget" name="packList">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>261</width>
+ <height>381</height>
+ </rect>
+ </property>
+ </widget>
+ </widget>
+ </widget>
+ <widget class="QScrollArea" name="scrollArea_2">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>10</y>
+ <width>441</width>
+ <height>381</height>
+ </rect>
+ </property>
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="scrollAreaWidgetContents_2">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>439</width>
+ <height>379</height>
+ </rect>
+ </property>
+ <widget class="QTextBrowser" name="modpackInfo">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>441</width>
+ <height>381</height>
+ </rect>
+ </property>
+ </widget>
+ </widget>
+ </widget>
+ <widget class="QComboBox" name="packVersionSelection">
+ <property name="geometry">
+ <rect>
+ <x>450</x>
+ <y>400</y>
+ <width>72</width>
+ <height>25</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QLabel" name="selectedVersionLabel">
+ <property name="geometry">
+ <rect>
+ <x>340</x>
+ <y>400</y>
+ <width>101</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Version selected:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ChooseFtbPackDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>666</x>
+ <y>422</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>889</x>
+ <y>501</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ChooseFtbPackDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>680</x>
+ <y>411</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>524</x>
+ <y>458</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/application/dialogs/CopyInstanceDialog.cpp b/application/dialogs/CopyInstanceDialog.cpp
index 1cf13144..72ef00fa 100644
--- a/application/dialogs/CopyInstanceDialog.cpp
+++ b/application/dialogs/CopyInstanceDialog.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/CopyInstanceDialog.h b/application/dialogs/CopyInstanceDialog.h
index 5a0f41f1..809552eb 100644
--- a/application/dialogs/CopyInstanceDialog.h
+++ b/application/dialogs/CopyInstanceDialog.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/CustomMessageBox.cpp b/application/dialogs/CustomMessageBox.cpp
index 007c941a..a7d75263 100644
--- a/application/dialogs/CustomMessageBox.cpp
+++ b/application/dialogs/CustomMessageBox.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/CustomMessageBox.h b/application/dialogs/CustomMessageBox.h
index 85059153..f9c0ad4e 100644
--- a/application/dialogs/CustomMessageBox.h
+++ b/application/dialogs/CustomMessageBox.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/EditAccountDialog.cpp b/application/dialogs/EditAccountDialog.cpp
index 4f12c70c..e43be1d8 100644
--- a/application/dialogs/EditAccountDialog.cpp
+++ b/application/dialogs/EditAccountDialog.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/EditAccountDialog.h b/application/dialogs/EditAccountDialog.h
index 3365dd1a..f121a111 100644
--- a/application/dialogs/EditAccountDialog.h
+++ b/application/dialogs/EditAccountDialog.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/ExportInstanceDialog.cpp b/application/dialogs/ExportInstanceDialog.cpp
index be859994..0e19b758 100644
--- a/application/dialogs/ExportInstanceDialog.cpp
+++ b/application/dialogs/ExportInstanceDialog.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -321,9 +321,11 @@ ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget *parent
auto root = instance->instanceRoot();
ui->treeView->setModel(proxyModel);
ui->treeView->setRootIndex(proxyModel->mapFromSource(model->index(root)));
+ ui->treeView->sortByColumn(0, Qt::AscendingOrder);
connect(proxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(rowsInserted(QModelIndex,int,int)));
+ model->setFilter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden);
model->setRootPath(root);
auto headerView = ui->treeView->header();
headerView->setSectionResizeMode(QHeaderView::ResizeToContents);
@@ -387,7 +389,7 @@ bool ExportInstanceDialog::doExport()
const QString output = QFileDialog::getSaveFileName(
this, tr("Export %1").arg(m_instance->name()),
FS::PathCombine(QDir::homePath(), name + ".zip"), "Zip (*.zip)", nullptr, QFileDialog::DontConfirmOverwrite);
- if (output.isNull())
+ if (output.isEmpty())
{
return false;
}
diff --git a/application/dialogs/ExportInstanceDialog.h b/application/dialogs/ExportInstanceDialog.h
index 0e136ad8..7b9c6726 100644
--- a/application/dialogs/ExportInstanceDialog.h
+++ b/application/dialogs/ExportInstanceDialog.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/IconPickerDialog.cpp b/application/dialogs/IconPickerDialog.cpp
index 70649b72..4ffd12bc 100644
--- a/application/dialogs/IconPickerDialog.cpp
+++ b/application/dialogs/IconPickerDialog.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
#include "groupview/InstanceDelegate.h"
#include "icons/IconList.h"
+#include <DesktopServices.h>
IconPickerDialog::IconPickerDialog(QWidget *parent)
: QDialog(parent), ui(new Ui::IconPickerDialog)
@@ -59,19 +60,21 @@ IconPickerDialog::IconPickerDialog(QWidget *parent)
contentsWidget->setModel(MMC->icons().get());
+ // NOTE: ResetRole forces the button to be on the left, while the OK/Cancel ones are on the right. We win.
auto buttonAdd = ui->buttonBox->addButton(tr("Add Icon"), QDialogButtonBox::ResetRole);
- auto buttonRemove =
- ui->buttonBox->addButton(tr("Remove Icon"), QDialogButtonBox::ResetRole);
+ auto buttonRemove = ui->buttonBox->addButton(tr("Remove Icon"), QDialogButtonBox::ResetRole);
connect(buttonAdd, SIGNAL(clicked(bool)), SLOT(addNewIcon()));
connect(buttonRemove, SIGNAL(clicked(bool)), SLOT(removeSelectedIcon()));
connect(contentsWidget, SIGNAL(doubleClicked(QModelIndex)), SLOT(activated(QModelIndex)));
- connect(contentsWidget->selectionModel(),
- SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
- SLOT(selectionChanged(QItemSelection, QItemSelection)));
+ connect(contentsWidget->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(selectionChanged(QItemSelection, QItemSelection)));
+
+ auto buttonFolder = ui->buttonBox->addButton(tr("Open Folder"), QDialogButtonBox::ResetRole);
+ connect(buttonFolder, &QPushButton::clicked, this, &IconPickerDialog::openFolder);
}
+
bool IconPickerDialog::eventFilter(QObject *obj, QEvent *evt)
{
if (obj != ui->iconView)
@@ -101,7 +104,7 @@ void IconPickerDialog::addNewIcon()
QString selectIcons = tr("Select Icons");
//: The type of icon files
QStringList fileNames = QFileDialog::getOpenFileNames(this, selectIcons, QString(),
- tr("Icons") + "(*.png *.jpg *.jpeg *.ico)");
+ tr("Icons") + "(*.png *.jpg *.jpeg *.ico *.svg)");
MMC->icons()->installIcons(fileNames);
}
@@ -152,3 +155,8 @@ IconPickerDialog::~IconPickerDialog()
{
delete ui;
}
+
+void IconPickerDialog::openFolder()
+{
+ DesktopServices::openDirectory(MMC->icons()->getDirectory(), true);
+}
diff --git a/application/dialogs/IconPickerDialog.h b/application/dialogs/IconPickerDialog.h
index a2a657ed..9053ec61 100644
--- a/application/dialogs/IconPickerDialog.h
+++ b/application/dialogs/IconPickerDialog.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,4 +45,5 @@ slots:
void delayed_scroll(QModelIndex);
void addNewIcon();
void removeSelectedIcon();
+ void openFolder();
};
diff --git a/application/dialogs/LoginDialog.cpp b/application/dialogs/LoginDialog.cpp
index 37e26045..b2020372 100644
--- a/application/dialogs/LoginDialog.cpp
+++ b/application/dialogs/LoginDialog.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/LoginDialog.h b/application/dialogs/LoginDialog.h
index 571da778..27b97cb0 100644
--- a/application/dialogs/LoginDialog.h
+++ b/application/dialogs/LoginDialog.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/NewComponentDialog.cpp b/application/dialogs/NewComponentDialog.cpp
new file mode 100644
index 00000000..514aa938
--- /dev/null
+++ b/application/dialogs/NewComponentDialog.cpp
@@ -0,0 +1,106 @@
+/* Copyright 2013-2018 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MultiMC.h"
+#include "NewComponentDialog.h"
+#include "ui_NewComponentDialog.h"
+
+#include <BaseVersion.h>
+#include <icons/IconList.h>
+#include <tasks/Task.h>
+#include <InstanceList.h>
+
+#include "VersionSelectDialog.h"
+#include "ProgressDialog.h"
+#include "IconPickerDialog.h"
+
+#include <QLayout>
+#include <QPushButton>
+#include <QFileDialog>
+#include <QValidator>
+
+#include <meta/Index.h>
+#include <meta/VersionList.h>
+
+NewComponentDialog::NewComponentDialog(const QString & initialName, const QString & initialUid, QWidget *parent)
+ : QDialog(parent), ui(new Ui::NewComponentDialog)
+{
+ ui->setupUi(this);
+ resize(minimumSizeHint());
+
+ ui->nameTextBox->setText(initialName);
+ ui->uidTextBox->setText(initialUid);
+
+ connect(ui->nameTextBox, &QLineEdit::textChanged, this, &NewComponentDialog::updateDialogState);
+ connect(ui->uidTextBox, &QLineEdit::textChanged, this, &NewComponentDialog::updateDialogState);
+
+ auto groups = MMC->instances()->getGroups().toSet();
+ ui->nameTextBox->setFocus();
+
+ originalPlaceholderText = ui->uidTextBox->placeholderText();
+ updateDialogState();
+}
+
+NewComponentDialog::~NewComponentDialog()
+{
+ delete ui;
+}
+
+void NewComponentDialog::updateDialogState()
+{
+ auto protoUid = ui->nameTextBox->text().toLower();
+ protoUid.remove(QRegularExpression("[^a-z]"));
+ if(protoUid.isEmpty())
+ {
+ ui->uidTextBox->setPlaceholderText(originalPlaceholderText);
+ }
+ else
+ {
+ QString suggestedUid = "org.multimc.custom." + protoUid;
+ ui->uidTextBox->setPlaceholderText(suggestedUid);
+ }
+ bool allowOK = !name().isEmpty() && !uid().isEmpty() && !uidBlacklist.contains(uid());
+ ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(allowOK);
+}
+
+QString NewComponentDialog::name() const
+{
+ auto result = ui->nameTextBox->text();
+ if(result.size())
+ {
+ return result.trimmed();
+ }
+ return QString();
+}
+
+QString NewComponentDialog::uid() const
+{
+ auto result = ui->uidTextBox->text();
+ if(result.size())
+ {
+ return result.trimmed();
+ }
+ result = ui->uidTextBox->placeholderText();
+ if(result.size() && result != originalPlaceholderText)
+ {
+ return result.trimmed();
+ }
+ return QString();
+}
+
+void NewComponentDialog::setBlacklist(QStringList badUids)
+{
+ uidBlacklist = badUids;
+}
diff --git a/application/dialogs/NewComponentDialog.h b/application/dialogs/NewComponentDialog.h
new file mode 100644
index 00000000..70caec0f
--- /dev/null
+++ b/application/dialogs/NewComponentDialog.h
@@ -0,0 +1,48 @@
+/* Copyright 2013-2018 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 <QDialog>
+
+#include <QString>
+#include <QStringList>
+
+namespace Ui
+{
+class NewComponentDialog;
+}
+
+class NewComponentDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit NewComponentDialog(const QString & initialName = QString(), const QString & initialUid = QString(), QWidget *parent = 0);
+ virtual ~NewComponentDialog();
+ void setBlacklist(QStringList badUids);
+
+ QString name() const;
+ QString uid() const;
+
+private slots:
+ void updateDialogState();
+
+private:
+ Ui::NewComponentDialog *ui;
+
+ QString originalPlaceholderText;
+ QStringList uidBlacklist;
+};
diff --git a/application/dialogs/NewComponentDialog.ui b/application/dialogs/NewComponentDialog.ui
new file mode 100644
index 00000000..b30c2431
--- /dev/null
+++ b/application/dialogs/NewComponentDialog.ui
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>NewComponentDialog</class>
+ <widget class="QDialog" name="NewComponentDialog">
+ <property name="windowModality">
+ <enum>Qt::ApplicationModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>345</width>
+ <height>146</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Copy Instance</string>
+ </property>
+ <property name="windowIcon">
+ <iconset>
+ <normaloff>:/icons/toolbar/copy</normaloff>:/icons/toolbar/copy</iconset>
+ </property>
+ <property name="modal">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLineEdit" name="nameTextBox">
+ <property name="placeholderText">
+ <string>Name</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="uidTextBox">
+ <property name="placeholderText">
+ <string>uid</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>nameTextBox</tabstop>
+ <tabstop>uidTextBox</tabstop>
+ </tabstops>
+ <resources>
+ <include location="../../graphics.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>NewComponentDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>NewComponentDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/application/dialogs/NewInstanceDialog.cpp b/application/dialogs/NewInstanceDialog.cpp
index d1a2bbfa..5faf57ac 100644
--- a/application/dialogs/NewInstanceDialog.cpp
+++ b/application/dialogs/NewInstanceDialog.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
#include "VersionSelectDialog.h"
#include "ProgressDialog.h"
#include "IconPickerDialog.h"
+#include "ChooseFtbPackDialog.h"
#include <QLayout>
#include <QPushButton>
@@ -71,7 +72,7 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString
}
else
{
- vlist->load();
+ vlist->load(Net::Mode::Online);
auto task = vlist->getLoadTask();
if(vlist->isLoaded())
{
@@ -92,9 +93,12 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString
connect(ui->modpackEdit, &QLineEdit::textChanged, this, &NewInstanceDialog::updateDialogState);
connect(ui->modpackBox, &QRadioButton::clicked, this, &NewInstanceDialog::updateDialogState);
+
connect(ui->versionBox, &QRadioButton::clicked, this, &NewInstanceDialog::updateDialogState);
connect(ui->versionTextBox, &QLineEdit::textChanged, this, &NewInstanceDialog::updateDialogState);
+ connect(ui->ftbBox, &QRadioButton::clicked, this, &NewInstanceDialog::updateDialogState);
+
auto groups = MMC->instances()->getGroups().toSet();
auto groupList = QStringList(groups.toList());
groupList.sort(Qt::CaseInsensitive);
@@ -117,6 +121,14 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString
ui->modpackBox->setChecked(true);
ui->modpackEdit->setText(url);
}
+
+ ftbPackDownloader = new FtbPackDownloader();
+
+ connect(ftbPackDownloader, &FtbPackDownloader::ready, this, &NewInstanceDialog::ftbPackDataDownloadSuccessfully);
+ connect(ftbPackDownloader, &FtbPackDownloader::packFetchFailed, this, &NewInstanceDialog::ftbPackDataDownloadFailed);
+
+ ftbPackDownloader->fetchModpacks(false);
+
updateDialogState();
}
@@ -147,6 +159,17 @@ void NewInstanceDialog::updateDialogState()
QFileInfo fi(url.fileName());
suggestedName = fi.completeBaseName();
}
+ else if (ui->ftbBox->isChecked())
+ {
+ if(ftbPackDownloader->isValidPackSelected()) {
+ suggestedName = ftbPackDownloader->getSuggestedInstanceName();
+ ui->labelFtbPack->setText(selectedPack.name);
+ }
+
+ }
+
+ ftbModpackRequested = ui->ftbBox->isChecked();
+
if(suggestedName.isEmpty())
{
ui->instNameTextBox->setPlaceholderText(originalPlaceholderText);
@@ -156,9 +179,10 @@ void NewInstanceDialog::updateDialogState()
ui->instNameTextBox->setPlaceholderText(suggestedName);
}
bool allowOK = !instName().isEmpty() && (
- (ui->versionBox->isChecked() && m_selectedVersion) ||
- (ui->modpackBox->isChecked() && ui->modpackEdit->hasAcceptableInput())
- );
+ (ui->versionBox->isChecked() && m_selectedVersion) ||
+ (ui->modpackBox->isChecked() && ui->modpackEdit->hasAcceptableInput()) ||
+ (ui->ftbBox->isChecked() && ftbPackDownloader && ftbPackDownloader->isValidPackSelected() )
+ );
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(allowOK);
}
@@ -271,3 +295,34 @@ void NewInstanceDialog::on_modpackBtn_clicked()
}
}
}
+
+bool NewInstanceDialog::isFtbModpackRequested() {
+ return ftbModpackRequested;
+}
+
+FtbPackDownloader *NewInstanceDialog::getFtbPackDownloader() {
+ return ftbPackDownloader;
+}
+
+void NewInstanceDialog::on_btnChooseFtbPack_clicked() {
+ ChooseFtbPackDialog dl(ftbPackDownloader->getModpacks());
+ dl.exec();
+ if(dl.result() == QDialog::Accepted) {
+ selectedPack = dl.getSelectedModpack();
+ ftbPackDownloader->selectPack(selectedPack, dl.getSelectedVersion());
+ }
+ updateDialogState();
+}
+
+void NewInstanceDialog::ftbPackDataDownloadSuccessfully() {
+ ui->packDataDownloadStatus->setText(tr("(Pack data download complete)"));
+ // ui->labelFtbPack->setText(tr("Disabled for now... not completed!"));
+
+ // Disable for PR
+ ui->ftbBox->setEnabled(true);
+}
+
+void NewInstanceDialog::ftbPackDataDownloadFailed() {
+ ui->packDataDownloadStatus->setText(tr("(Pack data download failed)"));
+}
+
diff --git a/application/dialogs/NewInstanceDialog.h b/application/dialogs/NewInstanceDialog.h
index 000b6a06..9b0f7f53 100644
--- a/application/dialogs/NewInstanceDialog.h
+++ b/application/dialogs/NewInstanceDialog.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,8 @@
#include <QDialog>
#include "BaseVersion.h"
+#include "modplatform/FtbPackDownloader.h"
+#include "modplatform/PackHelpers.h"
namespace Ui
{
@@ -42,19 +44,31 @@ public:
QUrl modpackUrl() const;
BaseVersionPtr selectedVersion() const;
+ bool isFtbModpackRequested();
+ FtbPackDownloader* getFtbPackDownloader();
+
private
slots:
void on_btnChangeVersion_clicked();
void on_iconButton_clicked();
void on_modpackBtn_clicked();
+ void on_btnChooseFtbPack_clicked();
void on_instNameTextBox_textChanged(const QString &arg1);
void versionListUpdated();
+ void ftbPackDataDownloadSuccessfully();
+ void ftbPackDataDownloadFailed();
+
private:
Ui::NewInstanceDialog *ui;
bool m_versionSetByUser = false;
+ bool ftbModpackRequested = false;
+
BaseVersionPtr m_selectedVersion;
QString InstIconKey;
QString originalPlaceholderText;
+
+ FtbPackDownloader* ftbPackDownloader;
+ FtbModpack selectedPack;
};
diff --git a/application/dialogs/NewInstanceDialog.ui b/application/dialogs/NewInstanceDialog.ui
index 6b875ff4..428b9c57 100644
--- a/application/dialogs/NewInstanceDialog.ui
+++ b/application/dialogs/NewInstanceDialog.ui
@@ -10,7 +10,7 @@
<x>0</x>
<y>0</y>
<width>281</width>
- <height>404</height>
+ <height>407</height>
</rect>
</property>
<property name="windowTitle">
@@ -107,37 +107,50 @@
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
- <item row="4" column="2">
- <widget class="QToolButton" name="modpackBtn">
+ <item row="5" column="0">
+ <widget class="QRadioButton" name="ftbBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
+ <string>Install FTB Pack</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QToolButton" name="btnChangeVersion">
+ <property name="text">
<string notr="true">...</string>
</property>
</widget>
</item>
- <item row="4" column="0" colspan="2">
- <widget class="FocusLineEdit" name="modpackEdit">
+ <item row="7" column="2">
+ <widget class="QToolButton" name="btnChooseFtbPack">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
- <string notr="true">http://</string>
+ <string>...</string>
</property>
</widget>
</item>
- <item row="2" column="0" colspan="2">
- <widget class="QLineEdit" name="versionTextBox">
- <property name="readOnly">
- <bool>true</bool>
+ <item row="4" column="2">
+ <widget class="QToolButton" name="modpackBtn">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string notr="true">...</string>
</property>
</widget>
</item>
- <item row="2" column="2">
- <widget class="QToolButton" name="btnChangeVersion">
+ <item row="7" column="0" colspan="2">
+ <widget class="QLabel" name="labelFtbPack">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="text">
- <string notr="true">...</string>
+ <string> No Pack choosen</string>
</property>
</widget>
</item>
@@ -158,6 +171,30 @@
</property>
</widget>
</item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QLineEdit" name="versionTextBox">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0" colspan="2">
+ <widget class="FocusLineEdit" name="modpackEdit">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string notr="true">http://</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1" colspan="2">
+ <widget class="QLabel" name="packDataDownloadStatus">
+ <property name="text">
+ <string>(Loading Pack data...)</string>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
<item>
@@ -219,8 +256,8 @@
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
- <x>257</x>
- <y>333</y>
+ <x>266</x>
+ <y>378</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
@@ -235,11 +272,11 @@
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
- <x>325</x>
- <y>333</y>
+ <x>271</x>
+ <y>378</y>
</hint>
<hint type="destinationlabel">
- <x>286</x>
+ <x>280</x>
<y>274</y>
</hint>
</hints>
@@ -251,12 +288,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>81</x>
- <y>229</y>
+ <x>91</x>
+ <y>251</y>
</hint>
<hint type="destinationlabel">
- <x>236</x>
- <y>221</y>
+ <x>240</x>
+ <y>278</y>
</hint>
</hints>
</connection>
@@ -267,12 +304,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>129</x>
- <y>225</y>
+ <x>139</x>
+ <y>251</y>
</hint>
<hint type="destinationlabel">
- <x>328</x>
- <y>229</y>
+ <x>270</x>
+ <y>278</y>
</hint>
</hints>
</connection>
@@ -287,8 +324,8 @@
<y>195</y>
</hint>
<hint type="destinationlabel">
- <x>213</x>
- <y>191</y>
+ <x>223</x>
+ <y>224</y>
</hint>
</hints>
</connection>
@@ -303,8 +340,40 @@
<y>198</y>
</hint>
<hint type="destinationlabel">
- <x>322</x>
- <y>192</y>
+ <x>270</x>
+ <y>224</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>ftbBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>btnChooseFtbPack</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>67</x>
+ <y>301</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>254</x>
+ <y>327</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>ftbBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>labelFtbPack</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>81</x>
+ <y>310</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>73</x>
+ <y>334</y>
</hint>
</hints>
</connection>
diff --git a/application/dialogs/NotificationDialog.cpp b/application/dialogs/NotificationDialog.cpp
index 8f920371..d61bf6bd 100644
--- a/application/dialogs/NotificationDialog.cpp
+++ b/application/dialogs/NotificationDialog.cpp
@@ -18,6 +18,7 @@ NotificationDialog::NotificationDialog(const NotificationChecker::NotificationEn
case NotificationChecker::NotificationEntry::Warning:
icon = QStyle::SP_MessageBoxWarning;
break;
+ default:
case NotificationChecker::NotificationEntry::Information:
icon = QStyle::SP_MessageBoxInformation;
break;
diff --git a/application/dialogs/ProfileSelectDialog.cpp b/application/dialogs/ProfileSelectDialog.cpp
index 16ffe51f..f1b335f9 100644
--- a/application/dialogs/ProfileSelectDialog.cpp
+++ b/application/dialogs/ProfileSelectDialog.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/ProfileSelectDialog.h b/application/dialogs/ProfileSelectDialog.h
index c8ef5959..b1268743 100644
--- a/application/dialogs/ProfileSelectDialog.h
+++ b/application/dialogs/ProfileSelectDialog.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/ProgressDialog.cpp b/application/dialogs/ProgressDialog.cpp
index db973c5a..9bf54a52 100644
--- a/application/dialogs/ProgressDialog.cpp
+++ b/application/dialogs/ProgressDialog.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -116,7 +116,7 @@ bool ProgressDialog::handleImmediateResult(QDialog::DialogCode &result)
{
if(task->isFinished())
{
- if(task->successful())
+ if(task->wasSuccessful())
{
result = QDialog::Accepted;
}
diff --git a/application/dialogs/ProgressDialog.h b/application/dialogs/ProgressDialog.h
index 28de8247..f27b71e1 100644
--- a/application/dialogs/ProgressDialog.h
+++ b/application/dialogs/ProgressDialog.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/SkinUploadDialog.cpp b/application/dialogs/SkinUploadDialog.cpp
index ebbab785..93414c6e 100644
--- a/application/dialogs/SkinUploadDialog.cpp
+++ b/application/dialogs/SkinUploadDialog.cpp
@@ -20,14 +20,59 @@ void SkinUploadDialog::on_buttonBox_accepted()
if (prog.execWithTask((Task*)login.get()) != QDialog::Accepted)
{
//FIXME: recover with password prompt
- CustomMessageBox::selectable(this, tr("Failed to login!"), tr("Unknown error"), QMessageBox::Warning)->exec();
+ CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Failed to login!"), QMessageBox::Warning)->exec();
close();
return;
}
- QString fileName = ui->skinPathTextBox->text();
- if (!QFile::exists(fileName))
+ QString fileName;
+ QString input = ui->skinPathTextBox->text();
+ QRegExp urlPrefixMatcher("^([a-z]+)://.+$");
+ bool isLocalFile = false;
+ // it has an URL prefix -> it is an URL
+ if(urlPrefixMatcher.exactMatch(input))
{
- CustomMessageBox::selectable(this, tr("Skin file does not exist!"), tr("Unknown error"), QMessageBox::Warning)->exec();
+ QUrl fileURL = input;
+ if(fileURL.isValid())
+ {
+ // local?
+ if(fileURL.isLocalFile())
+ {
+ isLocalFile = true;
+ fileName = fileURL.toLocalFile();
+ }
+ else
+ {
+ CustomMessageBox::selectable(
+ this,
+ tr("Skin Upload"),
+ tr("Using remote URLs for setting skins is not implemented yet."),
+ QMessageBox::Warning
+ )->exec();
+ close();
+ return;
+ }
+ }
+ else
+ {
+ CustomMessageBox::selectable(
+ this,
+ tr("Skin Upload"),
+ tr("You cannot use an invalid URL for uploading skins."),
+ QMessageBox::Warning
+ )->exec();
+ close();
+ return;
+ }
+ }
+ else
+ {
+ // just assume it's a path then
+ isLocalFile = true;
+ fileName = ui->skinPathTextBox->text();
+ }
+ if (isLocalFile && !QFile::exists(fileName))
+ {
+ CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Skin file does not exist!"), QMessageBox::Warning)->exec();
close();
return;
}
@@ -43,22 +88,22 @@ void SkinUploadDialog::on_buttonBox_accepted()
SkinUploadPtr upload = std::make_shared<SkinUpload>(this, session, FS::read(fileName), model);
if (prog.execWithTask((Task*)upload.get()) != QDialog::Accepted)
{
- CustomMessageBox::selectable(this, tr("Failed to upload skin!"), tr("Unknown error"), QMessageBox::Warning)->exec();
+ CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Failed to upload skin!"), QMessageBox::Warning)->exec();
close();
return;
}
- CustomMessageBox::selectable(this, tr("Skin uploaded!"), tr("Success"), QMessageBox::Information)->exec();
+ CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Success"), QMessageBox::Information)->exec();
close();
}
void SkinUploadDialog::on_skinBrowseBtn_clicked()
{
QString raw_path = QFileDialog::getOpenFileName(this, tr("Select Skin Texture"), QString(), "*.png");
- QString cooked_path = FS::NormalizePath(raw_path);
- if (cooked_path.isEmpty() || !QFileInfo::exists(cooked_path))
+ if (raw_path.isEmpty() || !QFileInfo::exists(raw_path))
{
return;
}
+ QString cooked_path = FS::NormalizePath(raw_path);
ui->skinPathTextBox->setText(cooked_path);
}
diff --git a/application/dialogs/UpdateDialog.cpp b/application/dialogs/UpdateDialog.cpp
index c935ec3b..30c7173d 100644
--- a/application/dialogs/UpdateDialog.cpp
+++ b/application/dialogs/UpdateDialog.cpp
@@ -81,6 +81,12 @@ QString reprocessCommits(QByteArray json)
{
const auto & commitval = commitarray[i];
auto commitobj = Json::requireObject(commitval);
+ auto parents_info = Json::ensureArray(commitobj, "parents");
+ // NOTE: this ignores merge commits, because they have more than one parent
+ if(parents_info.size() > 1)
+ {
+ continue;
+ }
auto commit_url = Json::requireString(commitobj, "html_url");
auto commit_info = Json::requireObject(commitobj, "commit");
auto commit_message = Json::requireString(commit_info, "message");
diff --git a/application/dialogs/UpdateDialog.h b/application/dialogs/UpdateDialog.h
index 8099464b..78960c99 100644
--- a/application/dialogs/UpdateDialog.h
+++ b/application/dialogs/UpdateDialog.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/dialogs/VersionSelectDialog.cpp b/application/dialogs/VersionSelectDialog.cpp
index de525d89..a44572cc 100644
--- a/application/dialogs/VersionSelectDialog.cpp
+++ b/application/dialogs/VersionSelectDialog.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -83,6 +83,12 @@ void VersionSelectDialog::retranslate()
m_refreshButton->setText(tr("&Refresh"));
}
+void VersionSelectDialog::setCurrentVersion(const QString& version)
+{
+ m_currentVersion = version;
+ m_versionWidget->setCurrentVersion(version);
+}
+
void VersionSelectDialog::setEmptyString(QString emptyString)
{
m_versionWidget->setEmptyString(emptyString);
diff --git a/application/dialogs/VersionSelectDialog.h b/application/dialogs/VersionSelectDialog.h
index 4b13a57b..c8b00c65 100644
--- a/application/dialogs/VersionSelectDialog.h
+++ b/application/dialogs/VersionSelectDialog.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,12 +46,12 @@ public:
BaseVersionPtr selectedVersion() const;
+ void setCurrentVersion(const QString & version);
void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter);
void setExactFilter(BaseVersionList::ModelRoles role, QString filter);
void setEmptyString(QString emptyString);
void setEmptyErrorString(QString emptyErrorString);
void setResizeOn(int column);
- void setUseLatest(const bool useLatest);
private slots:
void on_refreshButton_clicked();
@@ -61,6 +61,7 @@ private:
void selectRecommended();
private:
+ QString m_currentVersion;
VersionSelectWidget *m_versionWidget = nullptr;
QVBoxLayout *m_verticalLayout = nullptr;
QHBoxLayout *m_horizontalLayout = nullptr;
diff --git a/application/groupview/GroupView.cpp b/application/groupview/GroupView.cpp
index 6178db0b..0d6aa49e 100644
--- a/application/groupview/GroupView.cpp
+++ b/application/groupview/GroupView.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -104,37 +104,9 @@ inline bool operator<(const LocaleString &lhs, const LocaleString &rhs)
return (QString::localeAwareCompare(lhs, rhs) < 0);
}
-void GroupView::updateGeometries()
+void GroupView::updateScrollbar()
{
- geometryCache.clear();
int previousScroll = verticalScrollBar()->value();
-
- QMap<LocaleString, VisualGroup *> cats;
-
- for (int i = 0; i < model()->rowCount(); ++i)
- {
- const QString groupName = model()->index(i, 0).data(GroupViewRoles::GroupRole).toString();
- if (!cats.contains(groupName))
- {
- VisualGroup *old = this->category(groupName);
- if (old)
- {
- auto cat = new VisualGroup(old);
- cats.insert(groupName, cat);
- cat->update();
- }
- else
- {
- auto cat = new VisualGroup(groupName, this);
- cats.insert(groupName, cat);
- cat->update();
- }
- }
- }
-
- qDeleteAll(m_groups);
- m_groups = cats.values();
-
if (m_groups.isEmpty())
{
verticalScrollBar()->setRange(0, 0);
@@ -167,7 +139,38 @@ void GroupView::updateGeometries()
}
verticalScrollBar()->setValue(qMin(previousScroll, verticalScrollBar()->maximum()));
+}
+
+void GroupView::updateGeometries()
+{
+ geometryCache.clear();
+
+ QMap<LocaleString, VisualGroup *> cats;
+ for (int i = 0; i < model()->rowCount(); ++i)
+ {
+ const QString groupName = model()->index(i, 0).data(GroupViewRoles::GroupRole).toString();
+ if (!cats.contains(groupName))
+ {
+ VisualGroup *old = this->category(groupName);
+ if (old)
+ {
+ auto cat = new VisualGroup(old);
+ cats.insert(groupName, cat);
+ cat->update();
+ }
+ else
+ {
+ auto cat = new VisualGroup(groupName, this);
+ cats.insert(groupName, cat);
+ cat->update();
+ }
+ }
+ }
+
+ qDeleteAll(m_groups);
+ m_groups = cats.values();
+ updateScrollbar();
viewport()->update();
}
@@ -511,6 +514,10 @@ void GroupView::resizeEvent(QResizeEvent *event)
m_currentItemsPerRow = newItemsPerRow;
updateGeometries();
}
+ else
+ {
+ updateScrollbar();
+ }
}
void GroupView::dragEnterEvent(QDragEnterEvent *event)
diff --git a/application/groupview/GroupView.h b/application/groupview/GroupView.h
index a3f8a400..07c65bb5 100644
--- a/application/groupview/GroupView.h
+++ b/application/groupview/GroupView.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -96,6 +96,8 @@ protected:
void startDrag(Qt::DropActions supportedActions) override;
+ void updateScrollbar();
+
private:
friend struct VisualGroup;
QList<VisualGroup *> m_groups;
diff --git a/application/groupview/GroupedProxyModel.cpp b/application/groupview/GroupedProxyModel.cpp
index e7d4670e..c13f2411 100644
--- a/application/groupview/GroupedProxyModel.cpp
+++ b/application/groupview/GroupedProxyModel.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/groupview/GroupedProxyModel.h b/application/groupview/GroupedProxyModel.h
index dc39346f..babeb308 100644
--- a/application/groupview/GroupedProxyModel.h
+++ b/application/groupview/GroupedProxyModel.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/groupview/InstanceDelegate.cpp b/application/groupview/InstanceDelegate.cpp
index 10e31178..0855c04a 100644
--- a/application/groupview/InstanceDelegate.cpp
+++ b/application/groupview/InstanceDelegate.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/groupview/InstanceDelegate.h b/application/groupview/InstanceDelegate.h
index 49496b5b..c0148570 100644
--- a/application/groupview/InstanceDelegate.h
+++ b/application/groupview/InstanceDelegate.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/groupview/VisualGroup.cpp b/application/groupview/VisualGroup.cpp
index e6f23af0..940c7a8b 100644
--- a/application/groupview/VisualGroup.cpp
+++ b/application/groupview/VisualGroup.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/groupview/VisualGroup.h b/application/groupview/VisualGroup.h
index 940acd7a..2caac49f 100644
--- a/application/groupview/VisualGroup.h
+++ b/application/groupview/VisualGroup.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/install_prereqs.cmake.in b/application/install_prereqs.cmake.in
index 7f283c89..2906a4ec 100644
--- a/application/install_prereqs.cmake.in
+++ b/application/install_prereqs.cmake.in
@@ -10,6 +10,8 @@ function(gp_resolved_file_type_override resolved_file type_var)
set(${type_var} other PARENT_SCOPE)
elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libpng")
set(${type_var} other PARENT_SCOPE)
+ elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libproxy")
+ set(${type_var} other PARENT_SCOPE)
elseif((resolved_file MATCHES "^/(usr/)?lib(.+)?/libstdc\\+\\+") AND (UNIX AND NOT APPLE))
set(${type_var} other PARENT_SCOPE)
endif()
diff --git a/application/main.cpp b/application/main.cpp
index 48983dd6..ade05faf 100644
--- a/application/main.cpp
+++ b/application/main.cpp
@@ -49,6 +49,7 @@ int main(int argc, char *argv[])
Q_INIT_RESOURCE(pe_colored);
Q_INIT_RESOURCE(OSX);
Q_INIT_RESOURCE(iOS);
+ Q_INIT_RESOURCE(flat);
return app.exec();
}
case MultiMC::Failed:
diff --git a/application/package/linux/multimc.desktop b/application/package/linux/multimc.desktop
index 7fce5c7a..514b330f 100755
--- a/application/package/linux/multimc.desktop
+++ b/application/package/linux/multimc.desktop
@@ -1,6 +1,5 @@
[Desktop Entry]
Version=1.0
-Encoding=UTF-8
Name=MultiMC
GenericName=MultiMC
Comment=Free, open source launcher and instance manager for Minecraft.
@@ -8,4 +7,4 @@ Type=Application
Terminal=false
Exec=multimc
Icon=multimc
-Categories=Application;Game
+Categories=Game
diff --git a/application/pagedialog/PageDialog.cpp b/application/pagedialog/PageDialog.cpp
index b175b55f..b201de85 100644
--- a/application/pagedialog/PageDialog.cpp
+++ b/application/pagedialog/PageDialog.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pagedialog/PageDialog.h b/application/pagedialog/PageDialog.h
index 2717df93..67cd290e 100644
--- a/application/pagedialog/PageDialog.h
+++ b/application/pagedialog/PageDialog.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/BasePage.h b/application/pages/BasePage.h
index 1d6e4bd0..63a26239 100644
--- a/application/pages/BasePage.h
+++ b/application/pages/BasePage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,11 +33,15 @@ public:
virtual QString helpPage() const { return QString(); }
virtual void opened() {}
virtual void closed() {}
- virtual void setParentContainer(BasePageContainer *) {};
-
+ virtual void setParentContainer(BasePageContainer * container)
+ {
+ m_container = container;
+ };
public:
int stackIndex = -1;
int listIndex = -1;
+protected:
+ BasePageContainer * m_container = nullptr;
};
typedef std::shared_ptr<BasePage> BasePagePtr;
diff --git a/application/pages/BasePageContainer.h b/application/pages/BasePageContainer.h
index 660685d3..ff7315c2 100644
--- a/application/pages/BasePageContainer.h
+++ b/application/pages/BasePageContainer.h
@@ -6,4 +6,5 @@ public:
virtual ~BasePageContainer(){};
virtual bool selectPage(QString pageId) = 0;
virtual void refreshContainer() = 0;
+ virtual bool requestClose() = 0;
};
diff --git a/application/pages/BasePageProvider.h b/application/pages/BasePageProvider.h
index b976bc16..0ebcff7a 100644
--- a/application/pages/BasePageProvider.h
+++ b/application/pages/BasePageProvider.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/InstanceSettingsPage.cpp b/application/pages/InstanceSettingsPage.cpp
index 82438583..71e90a32 100644
--- a/application/pages/InstanceSettingsPage.cpp
+++ b/application/pages/InstanceSettingsPage.cpp
@@ -11,12 +11,16 @@
#include <java/JavaInstallList.h>
#include <FileSystem.h>
+#include <sys.h>
+#include <widgets/CustomCommands.h>
InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent)
: QWidget(parent), ui(new Ui::InstanceSettingsPage), m_instance(inst)
{
m_settings = inst->settings();
ui->setupUi(this);
+ auto sysMB = Sys::getSystemRam() / Sys::megabyte;
+ ui->maxMemSpinBox->setMaximum(sysMB);
loadSettings();
}
@@ -77,8 +81,18 @@ void InstanceSettingsPage::applySettings()
m_settings->set("OverrideMemory", memory);
if (memory)
{
- m_settings->set("MinMemAlloc", ui->minMemSpinBox->value());
- m_settings->set("MaxMemAlloc", ui->maxMemSpinBox->value());
+ int min = ui->minMemSpinBox->value();
+ int max = ui->maxMemSpinBox->value();
+ if(min < max)
+ {
+ m_settings->set("MinMemAlloc", min);
+ m_settings->set("MaxMemAlloc", max);
+ }
+ else
+ {
+ m_settings->set("MinMemAlloc", max);
+ m_settings->set("MaxMemAlloc", min);
+ }
m_settings->set("PermGen", ui->permGenSpinBox->value());
}
else
@@ -117,13 +131,13 @@ void InstanceSettingsPage::applySettings()
m_settings->reset("OverrideJava");
// Custom Commands
- bool custcmd = ui->customCommandsGroupBox->isChecked();
+ bool custcmd = ui->customCommands->checked();
m_settings->set("OverrideCommands", custcmd);
if (custcmd)
{
- m_settings->set("PreLaunchCommand", ui->preLaunchCmdTextBox->text());
- m_settings->set("WrapperCommand", ui->wrapperCmdTextBox->text());
- m_settings->set("PostExitCommand", ui->postExitCmdTextBox->text());
+ m_settings->set("PreLaunchCommand", ui->customCommands->prelaunchCommand());
+ m_settings->set("WrapperCommand", ui->customCommands->wrapperCommand());
+ m_settings->set("PostExitCommand", ui->customCommands->postexitCommand());
}
else
{
@@ -149,8 +163,18 @@ void InstanceSettingsPage::loadSettings()
// Memory
ui->memoryGroupBox->setChecked(m_settings->get("OverrideMemory").toBool());
- ui->minMemSpinBox->setValue(m_settings->get("MinMemAlloc").toInt());
- ui->maxMemSpinBox->setValue(m_settings->get("MaxMemAlloc").toInt());
+ int min = m_settings->get("MinMemAlloc").toInt();
+ int max = m_settings->get("MaxMemAlloc").toInt();
+ if(min < max)
+ {
+ ui->minMemSpinBox->setValue(min);
+ ui->maxMemSpinBox->setValue(max);
+ }
+ else
+ {
+ ui->minMemSpinBox->setValue(max);
+ ui->maxMemSpinBox->setValue(min);
+ }
ui->permGenSpinBox->setValue(m_settings->get("PermGen").toInt());
// Java Settings
@@ -164,11 +188,14 @@ void InstanceSettingsPage::loadSettings()
ui->javaArgumentsGroupBox->setChecked(overrideArgs);
ui->jvmArgsTextBox->setPlainText(m_settings->get("JvmArgs").toString());
- // Custom Commands
- ui->customCommandsGroupBox->setChecked(m_settings->get("OverrideCommands").toBool());
- ui->preLaunchCmdTextBox->setText(m_settings->get("PreLaunchCommand").toString());
- ui->wrapperCmdTextBox->setText(m_settings->get("WrapperCommand").toString());
- ui->postExitCmdTextBox->setText(m_settings->get("PostExitCommand").toString());
+ // Custom commands
+ ui->customCommands->initialize(
+ true,
+ m_settings->get("OverrideCommands").toBool(),
+ m_settings->get("PreLaunchCommand").toString(),
+ m_settings->get("WrapperCommand").toString(),
+ m_settings->get("PostExitCommand").toString()
+ );
}
void InstanceSettingsPage::on_javaDetectBtn_clicked()
@@ -189,13 +216,13 @@ void InstanceSettingsPage::on_javaDetectBtn_clicked()
void InstanceSettingsPage::on_javaBrowseBtn_clicked()
{
QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"));
- QString cooked_path = FS::NormalizePath(raw_path);
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
- if(cooked_path.isEmpty())
+ if(raw_path.isEmpty())
{
return;
}
+ QString cooked_path = FS::NormalizePath(raw_path);
QFileInfo javaInfo(cooked_path);;
if(!javaInfo.exists() || !javaInfo.isExecutable())
diff --git a/application/pages/InstanceSettingsPage.h b/application/pages/InstanceSettingsPage.h
index 5930a2fd..4959bdbe 100644
--- a/application/pages/InstanceSettingsPage.h
+++ b/application/pages/InstanceSettingsPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/InstanceSettingsPage.ui b/application/pages/InstanceSettingsPage.ui
index 6163297f..0c180df3 100644
--- a/application/pages/InstanceSettingsPage.ui
+++ b/application/pages/InstanceSettingsPage.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>458</width>
- <height>508</height>
+ <width>553</width>
+ <height>522</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@@ -42,7 +42,7 @@
<bool>true</bool>
</property>
<property name="title">
- <string>Java ins&amp;tallation</string>
+ <string>Java insta&amp;llation</string>
</property>
<property name="checkable">
<bool>true</bool>
@@ -196,7 +196,7 @@
<bool>true</bool>
</property>
<property name="title">
- <string>Java arguments</string>
+ <string>Java argumen&amp;ts</string>
</property>
<property name="checkable">
<bool>true</bool>
@@ -211,19 +211,6 @@
</layout>
</widget>
</item>
- <item>
- <spacer name="verticalSpacerMinecraft">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- </spacer>
- </item>
</layout>
</widget>
<widget class="QWidget" name="javaTab">
@@ -363,81 +350,7 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
- <widget class="QGroupBox" name="customCommandsGroupBox">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="title">
- <string>Cus&amp;tom Commands</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="2" column="0">
- <widget class="QLabel" name="labelPostExitCmd">
- <property name="text">
- <string>Post-exit command:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="preLaunchCmdTextBox"/>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="labelPreLaunchCmd">
- <property name="text">
- <string>Pre-launch command:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="postExitCmdTextBox"/>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="labelWrapperCmd">
- <property name="text">
- <string>Wrapper command:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="wrapperCmdTextBox"/>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="labelCustomCmdsDescription">
- <property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Pre-launch command runs before the instance launches and post-exit command runs after it exits.&lt;/p&gt;&lt;p&gt;Both will be run in MultiMC's working folder with extra environment variables:&lt;/p&gt;&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;INST_NAME - Name of the instance&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;INST_ID - ID of the instance&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;INST_DIR - absolute path of the instance&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;INST_MC_DIR - absolute path of minecraft&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;INST_JAVA - java binary used for launch&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;INST_JAVA_ARGS - command-line parameters used for launch&lt;/li&gt;&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacerMinecraft_3">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>88</width>
- <height>186</height>
- </size>
- </property>
- </spacer>
+ <widget class="CustomCommands" name="customCommands" native="true"/>
</item>
</layout>
</widget>
@@ -445,6 +358,14 @@
</item>
</layout>
</widget>
+ <customwidgets>
+ <customwidget>
+ <class>CustomCommands</class>
+ <extends>QWidget</extends>
+ <header>widgets/CustomCommands.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
<tabstops>
<tabstop>settingsTabs</tabstop>
<tabstop>javaSettingsGroupBox</tabstop>
@@ -466,10 +387,6 @@
<tabstop>showConsoleCheck</tabstop>
<tabstop>autoCloseConsoleCheck</tabstop>
<tabstop>showConsoleErrorCheck</tabstop>
- <tabstop>customCommandsGroupBox</tabstop>
- <tabstop>preLaunchCmdTextBox</tabstop>
- <tabstop>wrapperCmdTextBox</tabstop>
- <tabstop>postExitCmdTextBox</tabstop>
</tabstops>
<resources/>
<connections/>
diff --git a/application/pages/LegacyJarModPage.cpp b/application/pages/LegacyJarModPage.cpp
deleted file mode 100644
index c13bce8c..00000000
--- a/application/pages/LegacyJarModPage.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/* Copyright 2013-2017 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 "LegacyJarModPage.h"
-#include "ui_LegacyJarModPage.h"
-
-#include <QKeyEvent>
-#include <QKeyEvent>
-
-#include "dialogs/VersionSelectDialog.h"
-#include "dialogs/ProgressDialog.h"
-#include "dialogs/ModEditDialogCommon.h"
-#include "minecraft/legacy/LegacyModList.h"
-#include "minecraft/legacy/LegacyInstance.h"
-#include "Env.h"
-#include <DesktopServices.h>
-#include "MultiMC.h"
-#include <GuiUtil.h>
-
-LegacyJarModPage::LegacyJarModPage(LegacyInstance *inst, QWidget *parent)
- : QWidget(parent), ui(new Ui::LegacyJarModPage), m_inst(inst)
-{
- ui->setupUi(this);
- ui->tabWidget->tabBar()->hide();
-
- m_jarmods = m_inst->jarModList();
- ui->jarModsTreeView->setModel(m_jarmods.get());
- ui->jarModsTreeView->setDragDropMode(QAbstractItemView::DragDrop);
- ui->jarModsTreeView->setSelectionMode(QAbstractItemView::SingleSelection);
- ui->jarModsTreeView->installEventFilter(this);
- m_jarmods->startWatching();
- auto smodel = ui->jarModsTreeView->selectionModel();
- connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
- SLOT(jarCurrent(QModelIndex, QModelIndex)));
-}
-
-LegacyJarModPage::~LegacyJarModPage()
-{
- m_jarmods->stopWatching();
- delete ui;
-}
-
-bool LegacyJarModPage::shouldDisplay() const
-{
- return !m_inst->isRunning();
-}
-
-bool LegacyJarModPage::eventFilter(QObject *obj, QEvent *ev)
-{
- if (ev->type() != QEvent::KeyPress || obj != ui->jarModsTreeView)
- {
- return QWidget::eventFilter(obj, ev);
- }
-
- QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
- switch (keyEvent->key())
- {
- case Qt::Key_Up:
- {
- if (keyEvent->modifiers() & Qt::ControlModifier)
- {
- on_moveJarUpBtn_clicked();
- return true;
- }
- break;
- }
- case Qt::Key_Down:
- {
- if (keyEvent->modifiers() & Qt::ControlModifier)
- {
- on_moveJarDownBtn_clicked();
- return true;
- }
- break;
- }
- case Qt::Key_Delete:
- on_rmJarBtn_clicked();
- return true;
- case Qt::Key_Plus:
- on_addJarBtn_clicked();
- return true;
- default:
- break;
- }
- return QWidget::eventFilter(obj, ev);
-}
-
-void LegacyJarModPage::on_addJarBtn_clicked()
-{
- auto list = GuiUtil::BrowseForFiles("jarmod", tr("Select jar mods"), tr("Minecraft.jar mods (*.zip *.jar)"), MMC->settings()->get("CentralModsDir").toString(), this->parentWidget());
- if(!list.empty())
- {
- m_jarmods->stopWatching();
- for (auto filename : list)
- {
- m_jarmods->installMod(filename);
- }
- m_jarmods->startWatching();
- }
-}
-
-void LegacyJarModPage::on_moveJarDownBtn_clicked()
-{
- int first, last;
- auto list = ui->jarModsTreeView->selectionModel()->selectedRows();
-
- if (!lastfirst(list, first, last))
- return;
-
- m_jarmods->moveModsDown(first, last);
-}
-
-void LegacyJarModPage::on_moveJarUpBtn_clicked()
-{
- int first, last;
- auto list = ui->jarModsTreeView->selectionModel()->selectedRows();
-
- if (!lastfirst(list, first, last))
- return;
- m_jarmods->moveModsUp(first, last);
-}
-
-void LegacyJarModPage::on_rmJarBtn_clicked()
-{
- int first, last;
- auto list = ui->jarModsTreeView->selectionModel()->selectedRows();
-
- if (!lastfirst(list, first, last))
- return;
- m_jarmods->stopWatching();
- m_jarmods->deleteMods(first, last);
- m_jarmods->startWatching();
-}
-
-void LegacyJarModPage::on_viewJarBtn_clicked()
-{
- DesktopServices::openDirectory(m_inst->jarModsDir(), true);
-}
-
-void LegacyJarModPage::jarCurrent(QModelIndex current, QModelIndex previous)
-{
- if (!current.isValid())
- {
- ui->jarMIFrame->clear();
- return;
- }
- int row = current.row();
- Mod &m = m_jarmods->operator[](row);
- ui->jarMIFrame->updateWithMod(m);
-}
diff --git a/application/pages/LegacyJarModPage.h b/application/pages/LegacyJarModPage.h
deleted file mode 100644
index 2a5ac75f..00000000
--- a/application/pages/LegacyJarModPage.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* Copyright 2013-2017 MultiMC Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <QWidget>
-
-#include "net/NetJob.h"
-#include "BasePage.h"
-#include <MultiMC.h>
-
-class LegacyModList;
-class LegacyInstance;
-namespace Ui
-{
-class LegacyJarModPage;
-}
-
-class LegacyJarModPage : public QWidget, public BasePage
-{
- Q_OBJECT
-
-public:
- explicit LegacyJarModPage(LegacyInstance *inst, QWidget *parent = 0);
- virtual ~LegacyJarModPage();
-
- virtual QString displayName() const override
- {
- return tr("Jar Mods");
- }
- virtual QIcon icon() const override
- {
- return MMC->getThemedIcon("jarmods");
- }
- virtual QString id() const override
- {
- return "jarmods";
- }
- virtual QString helpPage() const override
- {
- return "Legacy-jar-mods";
- }
- virtual bool shouldDisplay() const override;
-
-private
-slots:
-
- void on_addJarBtn_clicked();
- void on_rmJarBtn_clicked();
- void on_moveJarUpBtn_clicked();
- void on_moveJarDownBtn_clicked();
- void on_viewJarBtn_clicked();
-
- void jarCurrent(QModelIndex current, QModelIndex previous);
-
-protected:
- virtual bool eventFilter(QObject *obj, QEvent *ev) override;
-
-private:
- Ui::LegacyJarModPage *ui;
- std::shared_ptr<LegacyModList> m_jarmods;
- LegacyInstance *m_inst;
- NetJobPtr forgeJob;
-};
diff --git a/application/pages/LegacyJarModPage.ui b/application/pages/LegacyJarModPage.ui
deleted file mode 100644
index 137a4ae5..00000000
--- a/application/pages/LegacyJarModPage.ui
+++ /dev/null
@@ -1,162 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>LegacyJarModPage</class>
- <widget class="QWidget" name="LegacyJarModPage">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>659</width>
- <height>593</height>
- </rect>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QTabWidget" name="tabWidget">
- <property name="currentIndex">
- <number>0</number>
- </property>
- <widget class="QWidget" name="tab">
- <attribute name="title">
- <string notr="true">Tab 1</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="ModListView" name="jarModsTreeView">
- <property name="verticalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOn</enum>
- </property>
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOff</enum>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QVBoxLayout" name="jarModsButtonBox">
- <item>
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Selection</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="rmJarBtn">
- <property name="text">
- <string>&amp;Remove</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="moveJarUpBtn">
- <property name="text">
- <string>Move &amp;Up</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="moveJarDownBtn">
- <property name="text">
- <string>Move &amp;Down</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="LineSeparator" name="separator" native="true"/>
- </item>
- <item>
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Install</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="addJarBtn">
- <property name="text">
- <string>&amp;Add jar mod</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="viewJarBtn">
- <property name="text">
- <string>&amp;View Folder</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- <item>
- <widget class="MCModInfoFrame" name="jarMIFrame">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <customwidgets>
- <customwidget>
- <class>ModListView</class>
- <extends>QTreeView</extends>
- <header>widgets/ModListView.h</header>
- </customwidget>
- <customwidget>
- <class>MCModInfoFrame</class>
- <extends>QFrame</extends>
- <header>widgets/MCModInfoFrame.h</header>
- <container>1</container>
- </customwidget>
- <customwidget>
- <class>LineSeparator</class>
- <extends>QWidget</extends>
- <header>widgets/LineSeparator.h</header>
- <container>1</container>
- </customwidget>
- </customwidgets>
- <resources/>
- <connections/>
-</ui>
diff --git a/application/pages/LegacyUpgradePage.cpp b/application/pages/LegacyUpgradePage.cpp
index 14cb916d..a8f4a08c 100644
--- a/application/pages/LegacyUpgradePage.cpp
+++ b/application/pages/LegacyUpgradePage.cpp
@@ -2,8 +2,13 @@
#include "ui_LegacyUpgradePage.h"
#include "minecraft/legacy/LegacyInstance.h"
+#include "minecraft/legacy/LegacyUpgradeTask.h"
+#include "MultiMC.h"
+#include "FolderInstanceProvider.h"
+#include "dialogs/CustomMessageBox.h"
+#include "dialogs/ProgressDialog.h"
-LegacyUpgradePage::LegacyUpgradePage(LegacyInstance *inst, QWidget *parent)
+LegacyUpgradePage::LegacyUpgradePage(InstancePtr inst, QWidget *parent)
: QWidget(parent), ui(new Ui::LegacyUpgradePage), m_inst(inst)
{
ui->setupUi(this);
@@ -14,9 +19,24 @@ LegacyUpgradePage::~LegacyUpgradePage()
delete ui;
}
+void LegacyUpgradePage::runModalTask(Task *task)
+{
+ connect(task, &Task::failed, [this](QString reason)
+ {
+ CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Warning)->show();
+ });
+ ProgressDialog loadDialog(this);
+ loadDialog.setSkipButton(true, tr("Abort"));
+ if(loadDialog.execWithTask(task) == QDialog::Accepted)
+ {
+ m_container->requestClose();
+ }
+}
+
void LegacyUpgradePage::on_upgradeButton_clicked()
{
- // now what?
+ std::unique_ptr<Task> task(MMC->folderProvider()->legacyUpgradeTask(m_inst));
+ runModalTask(task.get());
}
bool LegacyUpgradePage::shouldDisplay() const
diff --git a/application/pages/LegacyUpgradePage.h b/application/pages/LegacyUpgradePage.h
index 4731bb82..3e1abe93 100644
--- a/application/pages/LegacyUpgradePage.h
+++ b/application/pages/LegacyUpgradePage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
#include "minecraft/legacy/LegacyInstance.h"
#include "pages/BasePage.h"
#include <MultiMC.h>
+#include "tasks/Task.h"
namespace Ui
{
@@ -31,7 +32,7 @@ class LegacyUpgradePage : public QWidget, public BasePage
Q_OBJECT
public:
- explicit LegacyUpgradePage(LegacyInstance *inst, QWidget *parent = 0);
+ explicit LegacyUpgradePage(InstancePtr inst, QWidget *parent = 0);
virtual ~LegacyUpgradePage();
virtual QString displayName() const override
{
@@ -50,11 +51,14 @@ public:
return "Legacy-upgrade";
}
virtual bool shouldDisplay() const override;
-private
-slots:
+
+private slots:
void on_upgradeButton_clicked();
private:
+ void runModalTask(Task *task);
+
+private:
Ui::LegacyUpgradePage *ui;
- LegacyInstance *m_inst;
+ InstancePtr m_inst;
};
diff --git a/application/pages/LegacyUpgradePage.ui b/application/pages/LegacyUpgradePage.ui
index 5e8c74eb..a94ee039 100644
--- a/application/pages/LegacyUpgradePage.ui
+++ b/application/pages/LegacyUpgradePage.ui
@@ -26,15 +26,7 @@
<item>
<widget class="QTextBrowser" name="textBrowser">
<property name="html">
- <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:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt; &lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; 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;New format is available&lt;/span&gt; &lt;/p&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;MultiMC now supports old Minecraft versions in the new (OneSix) instance format. The old format won't be getting any new features and only the most critical bugfixes. As a consequence, you should upgrade this instance. &lt;/p&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The upgrade will create a new instance with the same contents as the current one, in the new format. The original instance will remain untouched, in case anything goes wrong in the process. &lt;/p&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Please report any issues on our &lt;a href=&quot;https://github.com/MultiMC/MultiMC5/issues&quot;&gt;&lt;img src=&quot;:/icons/multimc/22x22/bug.png&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;https://github.com/MultiMC/MultiMC5/issues&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#68a0df;&quot;&gt;github issues page&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;body&gt;&lt;h1&gt;Upgrade is required&lt;/h1&gt;&lt;p&gt;MultiMC now supports old Minecraft versions and all the required features in the new (OneSix) instance format. As a consequence, the old (Legacy) format has been entirely disabled and old instances need to be upgraded.&lt;/p&gt;&lt;p&gt;The upgrade will create a new instance with the same contents as the current one, in the new format. The original instance will remain untouched, in case anything goes wrong in the process.&lt;/p&gt;&lt;p&gt;Please report any issues on our &lt;a href=&quot;https://github.com/MultiMC/MultiMC5/issues&quot;&gt;github issues page&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;There is also a &lt;a href=&quot;https://discord.gg/GtPmv93&quot;&gt;discord channel for testing here&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
@@ -44,7 +36,7 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QCommandLinkButton" name="upgradeButton">
<property name="text">
- <string>Start the upgrade! (Not Yet Implemented, Coming Soonâ„¢)</string>
+ <string>Upgrade the instance</string>
</property>
</widget>
</item>
diff --git a/application/pages/LogPage.cpp b/application/pages/LogPage.cpp
index 75e1df7d..0fa1ee67 100644
--- a/application/pages/LogPage.cpp
+++ b/application/pages/LogPage.cpp
@@ -141,13 +141,11 @@ LogPage::LogPage(InstancePtr instance, QWidget *parent)
auto launchTask = m_instance->getLaunchTask();
if(launchTask)
{
- on_InstanceLaunchTask_changed(launchTask);
+ setInstanceLaunchTaskChanged(launchTask, true);
}
- connect(m_instance.get(), &BaseInstance::launchTaskChanged, this, &LogPage::on_InstanceLaunchTask_changed);
+ connect(m_instance.get(), &BaseInstance::launchTaskChanged, this, &LogPage::onInstanceLaunchTaskChanged);
}
- ui->text->setWordWrap(true);
-
auto findShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this);
connect(findShortcut, SIGNAL(activated()), SLOT(findActivated()));
auto findNextShortcut = new QShortcut(QKeySequence(QKeySequence::FindNext), this);
@@ -162,13 +160,53 @@ LogPage::~LogPage()
delete ui;
}
-void LogPage::on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc)
+void LogPage::modelStateToUI()
+{
+ if(m_model->wrapLines())
+ {
+ ui->text->setWordWrap(true);
+ ui->wrapCheckbox->setCheckState(Qt::Checked);
+ }
+ else
+ {
+ ui->text->setWordWrap(false);
+ ui->wrapCheckbox->setCheckState(Qt::Unchecked);
+ }
+ if(m_model->suspended())
+ {
+ ui->trackLogCheckbox->setCheckState(Qt::Unchecked);
+ }
+ else
+ {
+ ui->trackLogCheckbox->setCheckState(Qt::Checked);
+ }
+}
+
+void LogPage::UIToModelState()
+{
+ if(!m_model)
+ {
+ return;
+ }
+ m_model->setLineWrap(ui->wrapCheckbox->checkState() == Qt::Checked);
+ m_model->suspend(ui->trackLogCheckbox->checkState() != Qt::Checked);
+}
+
+void LogPage::setInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc, bool initial)
{
m_process = proc;
if(m_process)
{
m_model = proc->getLogModel();
m_proxy->setSourceModel(m_model.get());
+ if(initial)
+ {
+ modelStateToUI();
+ }
+ else
+ {
+ UIToModelState();
+ }
}
else
{
@@ -177,6 +215,11 @@ void LogPage::on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc)
}
}
+void LogPage::onInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc)
+{
+ setInstanceLaunchTaskChanged(proc, false);
+}
+
bool LogPage::apply()
{
return true;
@@ -218,7 +261,7 @@ void LogPage::on_btnClear_clicked()
if(!m_model)
return;
m_model->clear();
- m_parentContainer->refreshContainer();
+ m_container->refreshContainer();
}
void LogPage::on_btnBottom_clicked()
@@ -228,12 +271,17 @@ void LogPage::on_btnBottom_clicked()
void LogPage::on_trackLogCheckbox_clicked(bool checked)
{
+ if(!m_model)
+ return;
m_model->suspend(!checked);
}
void LogPage::on_wrapCheckbox_clicked(bool checked)
{
ui->text->setWordWrap(checked);
+ if(!m_model)
+ return;
+ m_model->setLineWrap(checked);
}
void LogPage::on_findButton_clicked()
@@ -262,8 +310,3 @@ void LogPage::findActivated()
ui->searchBar->selectAll();
}
}
-
-void LogPage::setParentContainer(BasePageContainer * container)
-{
- m_parentContainer = container;
-}
diff --git a/application/pages/LogPage.h b/application/pages/LogPage.h
index 8dceb94f..b830118e 100644
--- a/application/pages/LogPage.h
+++ b/application/pages/LogPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,7 +54,6 @@ public:
return "Minecraft-Logs";
}
virtual bool shouldDisplay() const override;
- virtual void setParentContainer(BasePageContainer *) override;
private slots:
void on_btnPaste_clicked();
@@ -70,14 +69,18 @@ private slots:
void findNextActivated();
void findPreviousActivated();
- void on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc);
+ void onInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc);
+
+private:
+ void modelStateToUI();
+ void UIToModelState();
+ void setInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc, bool initial);
private:
Ui::LogPage *ui;
InstancePtr m_instance;
std::shared_ptr<LaunchTask> m_process;
- BasePageContainer * m_parentContainer;
LogFormatProxyModel * m_proxy;
shared_qobject_ptr <LogModel> m_model;
};
diff --git a/application/pages/ModFolderPage.cpp b/application/pages/ModFolderPage.cpp
index 5c60cc7f..2b3f4416 100644
--- a/application/pages/ModFolderPage.cpp
+++ b/application/pages/ModFolderPage.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
#include "minecraft/ModList.h"
#include "minecraft/Mod.h"
#include "minecraft/VersionFilterData.h"
+#include "minecraft/ComponentList.h"
#include <DesktopServices.h>
ModFolderPage::ModFolderPage(BaseInstance *inst, std::shared_ptr<ModList> mods, QString id,
@@ -99,21 +100,21 @@ bool CoreModFolderPage::shouldDisplay() const
{
if (ModFolderPage::shouldDisplay())
{
- auto inst = dynamic_cast<OneSixInstance *>(m_inst);
+ auto inst = dynamic_cast<MinecraftInstance *>(m_inst);
if (!inst)
return true;
- auto version = inst->getMinecraftProfile();
+ auto version = inst->getComponentList();
if (!version)
return true;
- if(!version->versionPatch("net.minecraftforge"))
+ if(!version->getComponent("net.minecraftforge"))
{
return false;
}
- if(!version->versionPatch("net.minecraft"))
+ if(!version->getComponent("net.minecraft"))
{
return false;
}
- if(version->versionPatch("net.minecraft")->getReleaseDateTime() < g_VersionFilterData.legacyCutoffDate)
+ if(version->getComponent("net.minecraft")->getReleaseDateTime() < g_VersionFilterData.legacyCutoffDate)
{
return true;
}
diff --git a/application/pages/ModFolderPage.h b/application/pages/ModFolderPage.h
index 191fa9dc..02282c41 100644
--- a/application/pages/ModFolderPage.h
+++ b/application/pages/ModFolderPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
#include <QWidget>
-#include "minecraft/onesix/OneSixInstance.h"
+#include "minecraft/MinecraftInstance.h"
#include "BasePage.h"
#include <MultiMC.h>
diff --git a/application/pages/NotesPage.h b/application/pages/NotesPage.h
index a119142f..eab446ad 100644
--- a/application/pages/NotesPage.h
+++ b/application/pages/NotesPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/OtherLogsPage.cpp b/application/pages/OtherLogsPage.cpp
index 3988e939..2141e0cc 100644
--- a/application/pages/OtherLogsPage.cpp
+++ b/application/pages/OtherLogsPage.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
#include "RecursiveFileSystemWatcher.h"
#include <GZip.h>
#include <FileSystem.h>
+#include <QShortcut>
OtherLogsPage::OtherLogsPage(QString path, IPathMatcher::Ptr fileFilter, QWidget *parent)
: QWidget(parent), ui(new Ui::OtherLogsPage), m_path(path), m_fileFilter(fileFilter),
@@ -35,6 +36,17 @@ OtherLogsPage::OtherLogsPage(QString path, IPathMatcher::Ptr fileFilter, QWidget
connect(m_watcher, &RecursiveFileSystemWatcher::filesChanged, this, &OtherLogsPage::populateSelectLogBox);
populateSelectLogBox();
+
+ auto findShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this);
+ connect(findShortcut, &QShortcut::activated, this, &OtherLogsPage::findActivated);
+
+ auto findNextShortcut = new QShortcut(QKeySequence(QKeySequence::FindNext), this);
+ connect(findNextShortcut, &QShortcut::activated, this, &OtherLogsPage::findNextActivated);
+
+ auto findPreviousShortcut = new QShortcut(QKeySequence(QKeySequence::FindPrevious), this);
+ connect(findPreviousShortcut, &QShortcut::activated, this, &OtherLogsPage::findPreviousActivated);
+
+ connect(ui->searchBar, &QLineEdit::returnPressed, this, &OtherLogsPage::on_findButton_clicked);
}
OtherLogsPage::~OtherLogsPage()
@@ -115,9 +127,22 @@ void OtherLogsPage::on_btnReload_clicked()
}
else
{
+ auto setPlainText = [&](const QString & text)
+ {
+ QString fontFamily = MMC->settings()->get("ConsoleFont").toString();
+ bool conversionOk = false;
+ int fontSize = MMC->settings()->get("ConsoleFontSize").toInt(&conversionOk);
+ if(!conversionOk)
+ {
+ fontSize = 11;
+ }
+ QTextDocument *doc = ui->text->document();
+ doc->setDefaultFont(QFont(fontFamily, fontSize));
+ ui->text->setPlainText(text);
+ };
auto showTooBig = [&]()
{
- ui->text->setPlainText(
+ setPlainText(
tr("The file (%1) is too big. You may want to open it in a viewer optimized "
"for large files.").arg(file.fileName()));
};
@@ -132,7 +157,7 @@ void OtherLogsPage::on_btnReload_clicked()
QByteArray temp;
if(!GZip::unzip(file.readAll(), temp))
{
- ui->text->setPlainText(
+ setPlainText(
tr("The file (%1) is not readable.").arg(file.fileName()));
return;
}
@@ -147,7 +172,7 @@ void OtherLogsPage::on_btnReload_clicked()
showTooBig();
return;
}
- ui->text->setPlainText(content);
+ setPlainText(content);
}
}
@@ -200,7 +225,7 @@ void OtherLogsPage::on_btnClean_clicked()
}
else
{
- messageBox->setText(tr("Do you really want to these files?\n%1").arg(toDelete.join('\n')));
+ messageBox->setText(tr("Do you really want to delete these files?\n%1").arg(toDelete.join('\n')));
}
messageBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
messageBox->setDefaultButton(QMessageBox::Ok);
@@ -253,3 +278,36 @@ void OtherLogsPage::setControlsEnabled(const bool enabled)
ui->text->setEnabled(enabled);
ui->btnClean->setEnabled(enabled);
}
+
+// FIXME: HACK, use LogView instead?
+static void findNext(QPlainTextEdit * _this, const QString& what, bool reverse)
+{
+ _this->find(what, reverse ? QTextDocument::FindFlag::FindBackward : QTextDocument::FindFlag(0));
+}
+
+void OtherLogsPage::on_findButton_clicked()
+{
+ auto modifiers = QApplication::keyboardModifiers();
+ bool reverse = modifiers & Qt::ShiftModifier;
+ findNext(ui->text, ui->searchBar->text(), reverse);
+}
+
+void OtherLogsPage::findNextActivated()
+{
+ findNext(ui->text, ui->searchBar->text(), false);
+}
+
+void OtherLogsPage::findPreviousActivated()
+{
+ findNext(ui->text, ui->searchBar->text(), true);
+}
+
+void OtherLogsPage::findActivated()
+{
+ // focus the search bar if it doesn't have focus
+ if (!ui->searchBar->hasFocus())
+ {
+ ui->searchBar->setFocus();
+ ui->searchBar->selectAll();
+ }
+}
diff --git a/application/pages/OtherLogsPage.h b/application/pages/OtherLogsPage.h
index 9ccf964f..157f5e9d 100644
--- a/application/pages/OtherLogsPage.h
+++ b/application/pages/OtherLogsPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -64,6 +64,11 @@ private slots:
void on_btnDelete_clicked();
void on_btnClean_clicked();
+ void on_findButton_clicked();
+ void findActivated();
+ void findNextActivated();
+ void findPreviousActivated();
+
private:
void setControlsEnabled(const bool enabled);
diff --git a/application/pages/OtherLogsPage.ui b/application/pages/OtherLogsPage.ui
index 43d6a35b..56ff3b62 100644
--- a/application/pages/OtherLogsPage.ui
+++ b/application/pages/OtherLogsPage.ui
@@ -32,8 +32,34 @@
<attribute name="title">
<string notr="true">Tab 1</string>
</attribute>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="searchBar"/>
+ </item>
+ <item row="2" column="2">
+ <widget class="QPushButton" name="findButton">
+ <property name="text">
+ <string>Find</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="4">
+ <widget class="QPlainTextEdit" name="text">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="verticalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOn</enum>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="4">
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="1">
<widget class="QPushButton" name="btnCopy">
@@ -65,6 +91,16 @@
</property>
</widget>
</item>
+ <item row="3" column="4">
+ <widget class="QPushButton" name="btnClean">
+ <property name="toolTip">
+ <string>Clear the log</string>
+ </property>
+ <property name="text">
+ <string>Clean</string>
+ </property>
+ </widget>
+ </item>
<item row="3" column="0">
<widget class="QPushButton" name="btnReload">
<property name="text">
@@ -82,31 +118,12 @@
</property>
</widget>
</item>
- <item row="3" column="4">
- <widget class="QPushButton" name="btnClean">
- <property name="toolTip">
- <string>Clear the log</string>
- </property>
- <property name="text">
- <string>Clean</string>
- </property>
- </widget>
- </item>
</layout>
</item>
- <item>
- <widget class="QPlainTextEdit" name="text">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="verticalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOn</enum>
- </property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Search:</string>
</property>
</widget>
</item>
@@ -117,7 +134,16 @@
</layout>
</widget>
<tabstops>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>selectLogBox</tabstop>
+ <tabstop>btnReload</tabstop>
+ <tabstop>btnCopy</tabstop>
+ <tabstop>btnPaste</tabstop>
+ <tabstop>btnDelete</tabstop>
+ <tabstop>btnClean</tabstop>
<tabstop>text</tabstop>
+ <tabstop>searchBar</tabstop>
+ <tabstop>findButton</tabstop>
</tabstops>
<resources/>
<connections/>
diff --git a/application/pages/ScreenshotsPage.cpp b/application/pages/ScreenshotsPage.cpp
index a4ee6f9d..7d32576a 100644
--- a/application/pages/ScreenshotsPage.cpp
+++ b/application/pages/ScreenshotsPage.cpp
@@ -280,7 +280,7 @@ void ScreenshotsPage::on_viewFolderBtn_clicked()
void ScreenshotsPage::on_uploadBtn_clicked()
{
- auto selection = ui->listView->selectionModel()->selectedIndexes();
+ auto selection = ui->listView->selectionModel()->selectedRows();
if (selection.isEmpty())
return;
diff --git a/application/pages/ScreenshotsPage.h b/application/pages/ScreenshotsPage.h
index 4aa16d18..c3ccbdee 100644
--- a/application/pages/ScreenshotsPage.h
+++ b/application/pages/ScreenshotsPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/ScreenshotsPage.ui b/application/pages/ScreenshotsPage.ui
index 7b70c07e..d05c4384 100644
--- a/application/pages/ScreenshotsPage.ui
+++ b/application/pages/ScreenshotsPage.ui
@@ -39,7 +39,7 @@
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior">
- <enum>QAbstractItemView::SelectItems</enum>
+ <enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
diff --git a/application/pages/VersionPage.cpp b/application/pages/VersionPage.cpp
index 8c14818f..00ae0a7e 100644
--- a/application/pages/VersionPage.cpp
+++ b/application/pages/VersionPage.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
#include "dialogs/CustomMessageBox.h"
#include "dialogs/VersionSelectDialog.h"
+#include "dialogs/NewComponentDialog.h"
#include "dialogs/ModEditDialogCommon.h"
#include "dialogs/ProgressDialog.h"
@@ -35,7 +36,7 @@
#include <QString>
#include <QUrl>
-#include "minecraft/MinecraftProfile.h"
+#include "minecraft/ComponentList.h"
#include "minecraft/auth/MojangAccountList.h"
#include "minecraft/Mod.h"
#include "icons/IconList.h"
@@ -50,13 +51,13 @@ class IconProxy : public QIdentityProxyModel
{
Q_OBJECT
public:
-
+
IconProxy(QWidget *parentWidget) : QIdentityProxyModel(parentWidget)
{
connect(parentWidget, &QObject::destroyed, this, &IconProxy::widgetGone);
m_parentWidget = parentWidget;
}
-
+
virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const override
{
QVariant var = QIdentityProxyModel::data(mapToSource(proxyIndex), role);
@@ -98,20 +99,15 @@ bool VersionPage::shouldDisplay() const
return !m_inst->isRunning();
}
-void VersionPage::setParentContainer(BasePageContainer * container)
-{
- m_container = container;
-}
-
-VersionPage::VersionPage(OneSixInstance *inst, QWidget *parent)
+VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent)
: QWidget(parent), ui(new Ui::VersionPage), m_inst(inst)
{
ui->setupUi(this);
ui->tabWidget->tabBar()->hide();
+ m_profile = m_inst->getComponentList();
- reloadMinecraftProfile();
+ reloadComponentList();
- m_profile = m_inst->getMinecraftProfile();
if (m_profile)
{
auto proxy = new IconProxy(ui->packageView);
@@ -119,10 +115,9 @@ VersionPage::VersionPage(OneSixInstance *inst, QWidget *parent)
ui->packageView->setModel(proxy);
ui->packageView->installEventFilter(this);
ui->packageView->setSelectionMode(QAbstractItemView::SingleSelection);
- connect(ui->packageView->selectionModel(), &QItemSelectionModel::currentChanged,
- this, &VersionPage::versionCurrent);
+ connect(ui->packageView->selectionModel(), &QItemSelectionModel::currentChanged, this, &VersionPage::versionCurrent);
auto smodel = ui->packageView->selectionModel();
- connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), SLOT(packageCurrent(QModelIndex, QModelIndex)));
+ connect(smodel, &QItemSelectionModel::currentChanged, this, &VersionPage::packageCurrent);
updateVersionControls();
// select first item.
preselect(0);
@@ -131,7 +126,7 @@ VersionPage::VersionPage(OneSixInstance *inst, QWidget *parent)
{
disableVersionControls();
}
- connect(m_inst, &OneSixInstance::versionReloaded, this,
+ connect(m_inst, &MinecraftInstance::versionReloaded, this,
&VersionPage::updateVersionControls);
}
@@ -148,7 +143,7 @@ void VersionPage::packageCurrent(const QModelIndex &current, const QModelIndex &
return;
}
int row = current.row();
- auto patch = m_profile->versionPatch(row);
+ auto patch = m_profile->getComponent(row);
auto severity = patch->getProblemSeverity();
switch(severity)
{
@@ -168,15 +163,15 @@ void VersionPage::packageCurrent(const QModelIndex &current, const QModelIndex &
QString problemOut;
for (auto &problem: problems)
{
- if(problem.getSeverity() == ProblemSeverity::Error)
+ if(problem.m_severity == ProblemSeverity::Error)
{
problemOut += tr("Error: ");
}
- else if(problem.getSeverity() == ProblemSeverity::Warning)
+ else if(problem.m_severity == ProblemSeverity::Warning)
{
problemOut += tr("Warning: ");
}
- problemOut += problem.getDescription();
+ problemOut += problem.m_description;
problemOut += "\n";
}
ui->frame->setModDescription(problemOut);
@@ -198,11 +193,11 @@ void VersionPage::disableVersionControls()
updateButtons();
}
-bool VersionPage::reloadMinecraftProfile()
+bool VersionPage::reloadComponentList()
{
try
{
- m_inst->reloadProfile();
+ m_profile->reload(Net::Mode::Online);
return true;
}
catch (Exception &e)
@@ -221,7 +216,7 @@ bool VersionPage::reloadMinecraftProfile()
void VersionPage::on_reloadBtn_clicked()
{
- reloadMinecraftProfile();
+ reloadComponentList();
m_container->refreshContainer();
}
@@ -236,7 +231,7 @@ void VersionPage::on_removeBtn_clicked()
}
}
updateButtons();
- reloadMinecraftProfile();
+ reloadComponentList();
m_container->refreshContainer();
}
@@ -250,47 +245,20 @@ void VersionPage::on_modBtn_clicked()
void VersionPage::on_jarmodBtn_clicked()
{
- bool nagShown = false;
- if (!m_profile->hasTrait("legacyLaunch") && !m_profile->hasTrait("alphaLaunch"))
- {
- // not legacy launch... nag
- auto seenNag = MMC->settings()->get("JarModNagSeen").toBool();
- if(!seenNag)
- {
- auto result = QMessageBox::question(this,
- tr("Are you sure?"),
- tr("This will add mods directly to the Minecraft jar.\n"
- "Unless you KNOW that this is what NEEDS to be done, you should just use the mods folder (Loader mods).\n"
- "\n"
- "Do you want to continue?"),
- tr("I understand, continue."), tr("Cancel"), QString(), 1, 1
- );
- if(result != 0)
- return;
- nagShown = true;
- }
- }
auto list = GuiUtil::BrowseForFiles("jarmod", tr("Select jar mods"), tr("Minecraft.jar mods (*.zip *.jar)"), MMC->settings()->get("CentralModsDir").toString(), this->parentWidget());
if(!list.empty())
{
m_profile->installJarMods(list);
- if(nagShown)
- {
- MMC->settings()->set("JarModNagSeen", QVariant(true));
- }
}
updateButtons();
}
-void VersionPage::on_resetOrderBtn_clicked()
+void VersionPage::on_jarBtn_clicked()
{
- try
- {
- m_profile->resetOrder();
- }
- catch (Exception &e)
+ auto jarPath = GuiUtil::BrowseForFile("jar", tr("Select jar"), tr("Minecraft.jar replacement (*.jar)"), MMC->settings()->get("CentralModsDir").toString(), this->parentWidget());
+ if(!jarPath.isEmpty())
{
- QMessageBox::critical(this, tr("Error"), e.cause());
+ m_profile->installCustomJar(jarPath);
}
updateButtons();
}
@@ -299,7 +267,7 @@ void VersionPage::on_moveUpBtn_clicked()
{
try
{
- m_profile->move(currentRow(), MinecraftProfile::MoveUp);
+ m_profile->move(currentRow(), ComponentList::MoveUp);
}
catch (Exception &e)
{
@@ -312,7 +280,7 @@ void VersionPage::on_moveDownBtn_clicked()
{
try
{
- m_profile->move(currentRow(), MinecraftProfile::MoveDown);
+ m_profile->move(currentRow(), ComponentList::MoveDown);
}
catch (Exception &e)
{
@@ -328,7 +296,7 @@ void VersionPage::on_changeVersionBtn_clicked()
{
return;
}
- auto patch = m_profile->versionPatch(versionRow);
+ auto patch = m_profile->getComponent(versionRow);
auto name = patch->getName();
auto list = patch->getVersionList();
if(!list)
@@ -336,10 +304,39 @@ void VersionPage::on_changeVersionBtn_clicked()
return;
}
auto uid = list->uid();
+ // FIXME: this is a horrible HACK. Get version filtering information from the actual metadata...
+ if(uid == "net.minecraftforge")
+ {
+ on_forgeBtn_clicked();
+ return;
+ }
+ else if (uid == "com.mumfrey.liteloader")
+ {
+ on_liteloaderBtn_clicked();
+ return;
+ }
VersionSelectDialog vselect(list.get(), tr("Change %1 version").arg(name), this);
+ auto currentVersion = patch->getVersion();
+ if(!currentVersion.isEmpty())
+ {
+ vselect.setCurrentVersion(currentVersion);
+ }
if (!vselect.exec() || !vselect.selectedVersion())
return;
+ qDebug() << "Change" << uid << "to" << vselect.selectedVersion()->descriptor();
+ bool important = false;
+ if(uid == "net.minecraft")
+ {
+ important = true;
+ }
+ m_profile->setComponentVersion(uid, vselect.selectedVersion()->descriptor(), important);
+ m_profile->resolve(Net::Mode::Online);
+ m_container->refreshContainer();
+}
+
+void VersionPage::on_downloadBtn_clicked()
+{
if (!MMC->accounts()->anyAccountIsValid())
{
CustomMessageBox::selectable(
@@ -350,42 +347,17 @@ void VersionPage::on_changeVersionBtn_clicked()
return;
}
- qDebug() << "Change" << uid << "to" << vselect.selectedVersion()->descriptor();
- if(uid == "net.minecraft")
- {
- if (!m_profile->isVanilla())
- {
- auto result = CustomMessageBox::selectable(
- this, tr("Are you sure?"),
- tr("This will remove any library/version customization you did previously. "
- "This includes things like Forge install and similar."),
- QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Abort,
- QMessageBox::Abort)->exec();
-
- if (result != QMessageBox::Ok)
- return;
- m_profile->revertToVanilla();
- reloadMinecraftProfile();
- }
- }
- m_inst->setComponentVersion(uid, vselect.selectedVersion()->descriptor());
- doUpdate();
- m_container->refreshContainer();
-}
-
-int VersionPage::doUpdate()
-{
- auto updateTask = m_inst->createUpdateTask();
+ auto updateTask = m_inst->createUpdateTask(Net::Mode::Online);
if (!updateTask)
{
- return 1;
+ return;
}
ProgressDialog tDialog(this);
connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString)));
- int ret = tDialog.execWithTask(updateTask.get());
+ // FIXME: unused return value
+ tDialog.execWithTask(updateTask.get());
updateButtons();
m_container->refreshContainer();
- return ret;
}
void VersionPage::on_forgeBtn_clicked()
@@ -396,20 +368,45 @@ void VersionPage::on_forgeBtn_clicked()
return;
}
VersionSelectDialog vselect(vlist.get(), tr("Select Forge version"), this);
- vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_inst->currentVersionId());
- vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") + m_inst->currentVersionId());
+ vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft"));
+ vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") + m_profile->getComponentVersion("net.minecraft"));
vselect.setEmptyErrorString(tr("Couldn't load or download the Forge version lists!"));
+
+ auto currentVersion = m_profile->getComponentVersion("net.minecraftforge");
+ if(!currentVersion.isEmpty())
+ {
+ vselect.setCurrentVersion(currentVersion);
+ }
+
if (vselect.exec() && vselect.selectedVersion())
{
auto vsn = vselect.selectedVersion();
- m_inst->setComponentVersion("net.minecraftforge", vsn->descriptor());
- m_profile->reload();
+ m_profile->setComponentVersion("net.minecraftforge", vsn->descriptor());
+ m_profile->resolve(Net::Mode::Online);
// m_profile->installVersion();
preselect(m_profile->rowCount(QModelIndex())-1);
m_container->refreshContainer();
}
}
+void VersionPage::on_addEmptyBtn_clicked()
+{
+ NewComponentDialog compdialog(QString(), QString(), this);
+ QStringList blacklist;
+ for(int i = 0; i < m_profile->rowCount(); i++)
+ {
+ auto comp = m_profile->getComponent(i);
+ blacklist.push_back(comp->getID());
+ }
+ compdialog.setBlacklist(blacklist);
+ if (compdialog.exec())
+ {
+ qDebug() << "name:" << compdialog.name();
+ qDebug() << "uid:" << compdialog.uid();
+ m_profile->installEmpty(compdialog.uid(), compdialog.name());
+ }
+}
+
void VersionPage::on_liteloaderBtn_clicked()
{
auto vlist = ENV.metadataIndex()->get("com.mumfrey.liteloader");
@@ -418,14 +415,21 @@ void VersionPage::on_liteloaderBtn_clicked()
return;
}
VersionSelectDialog vselect(vlist.get(), tr("Select LiteLoader version"), this);
- vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_inst->currentVersionId());
- vselect.setEmptyString(tr("No LiteLoader versions are currently available for Minecraft ") + m_inst->currentVersionId());
+ vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft"));
+ vselect.setEmptyString(tr("No LiteLoader versions are currently available for Minecraft ") + m_profile->getComponentVersion("net.minecraft"));
vselect.setEmptyErrorString(tr("Couldn't load or download the LiteLoader version lists!"));
+
+ auto currentVersion = m_profile->getComponentVersion("com.mumfrey.liteloader");
+ if(!currentVersion.isEmpty())
+ {
+ vselect.setCurrentVersion(currentVersion);
+ }
+
if (vselect.exec() && vselect.selectedVersion())
{
auto vsn = vselect.selectedVersion();
- m_inst->setComponentVersion("com.mumfrey.liteloader", vsn->descriptor());
- m_profile->reload();
+ m_profile->setComponentVersion("com.mumfrey.liteloader", vsn->descriptor());
+ m_profile->resolve(Net::Mode::Online);
// m_profile->installVersion(vselect.selectedVersion());
preselect(m_profile->rowCount(QModelIndex())-1);
m_container->refreshContainer();
@@ -461,7 +465,7 @@ void VersionPage::updateButtons(int row)
{
if(row == -1)
row = currentRow();
- auto patch = m_profile->versionPatch(row);
+ auto patch = m_profile->getComponent(row);
if (!patch)
{
ui->removeBtn->setDisabled(true);
@@ -490,14 +494,14 @@ void VersionPage::onGameUpdateError(QString error)
QMessageBox::Warning)->show();
}
-ProfilePatchPtr VersionPage::current()
+Component * VersionPage::current()
{
auto row = currentRow();
if(row < 0)
{
return nullptr;
}
- return m_profile->versionPatch(row);
+ return m_profile->getComponent(row);
}
int VersionPage::currentRow()
@@ -516,7 +520,7 @@ void VersionPage::on_customizeBtn_clicked()
{
return;
}
- auto patch = m_profile->versionPatch(version);
+ auto patch = m_profile->getComponent(version);
if(!patch->getVersionFile())
{
// TODO: wait for the update task to finish here...
@@ -563,3 +567,4 @@ void VersionPage::on_revertBtn_clicked()
}
#include "VersionPage.moc"
+
diff --git a/application/pages/VersionPage.h b/application/pages/VersionPage.h
index cc6c0b7b..49620c56 100644
--- a/application/pages/VersionPage.h
+++ b/application/pages/VersionPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,8 @@
#include <QWidget>
-#include "minecraft/onesix/OneSixInstance.h"
+#include "minecraft/MinecraftInstance.h"
+#include "minecraft/ComponentList.h"
#include "BasePage.h"
namespace Ui
@@ -30,7 +31,7 @@ class VersionPage : public QWidget, public BasePage
Q_OBJECT
public:
- explicit VersionPage(OneSixInstance *inst, QWidget *parent = 0);
+ explicit VersionPage(MinecraftInstance *inst, QWidget *parent = 0);
virtual ~VersionPage();
virtual QString displayName() const override
{
@@ -43,32 +44,32 @@ public:
}
virtual QString helpPage() const override
{
- return "Instance-Versions";
+ return "Instance-Version";
}
virtual bool shouldDisplay() const override;
- virtual void setParentContainer(BasePageContainer *) override;
-
private slots:
void on_forgeBtn_clicked();
+ void on_addEmptyBtn_clicked();
void on_liteloaderBtn_clicked();
void on_reloadBtn_clicked();
void on_removeBtn_clicked();
- void on_resetOrderBtn_clicked();
void on_moveUpBtn_clicked();
void on_moveDownBtn_clicked();
void on_jarmodBtn_clicked();
+ void on_jarBtn_clicked();
void on_revertBtn_clicked();
void on_editBtn_clicked();
void on_modBtn_clicked();
void on_customizeBtn_clicked();
+ void on_downloadBtn_clicked();
void updateVersionControls();
void disableVersionControls();
void on_changeVersionBtn_clicked();
private:
- ProfilePatchPtr current();
+ Component * current();
int currentRow();
void updateButtons(int row = -1);
void preselect(int row = 0);
@@ -76,14 +77,13 @@ private:
protected:
/// FIXME: this shouldn't be necessary!
- bool reloadMinecraftProfile();
+ bool reloadComponentList();
private:
Ui::VersionPage *ui;
- std::shared_ptr<MinecraftProfile> m_profile;
- OneSixInstance *m_inst;
+ std::shared_ptr<ComponentList> m_profile;
+ MinecraftInstance *m_inst;
int currentIdx = 0;
- BasePageContainer * m_container = nullptr;
public slots:
void versionCurrent(const QModelIndex &current, const QModelIndex &previous);
diff --git a/application/pages/VersionPage.ui b/application/pages/VersionPage.ui
index c16208db..d54dd840 100644
--- a/application/pages/VersionPage.ui
+++ b/application/pages/VersionPage.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>693</width>
- <height>750</height>
+ <width>870</width>
+ <height>1008</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@@ -206,17 +206,21 @@
<string>Add a mod into the Minecraft jar file.</string>
</property>
<property name="text">
- <string>Add jar mod</string>
+ <string>Add to Minecraft.jar</string>
</property>
</widget>
</item>
<item>
- <widget class="QPushButton" name="resetOrderBtn">
- <property name="toolTip">
- <string>Reset apply order of packages.</string>
+ <widget class="QPushButton" name="jarBtn">
+ <property name="text">
+ <string>Replace Minecraft.jar</string>
</property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="addEmptyBtn">
<property name="text">
- <string>Reset order</string>
+ <string>Add Empty</string>
</property>
</widget>
</item>
@@ -231,6 +235,16 @@
</widget>
</item>
<item>
+ <widget class="QPushButton" name="downloadBtn">
+ <property name="toolTip">
+ <string>Download the files needed to launch the instance now.</string>
+ </property>
+ <property name="text">
+ <string>Download All</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -281,7 +295,6 @@
</customwidget>
</customwidgets>
<tabstops>
- <tabstop>tabWidget</tabstop>
<tabstop>packageView</tabstop>
<tabstop>changeVersionBtn</tabstop>
<tabstop>moveUpBtn</tabstop>
@@ -294,8 +307,11 @@
<tabstop>liteloaderBtn</tabstop>
<tabstop>modBtn</tabstop>
<tabstop>jarmodBtn</tabstop>
- <tabstop>resetOrderBtn</tabstop>
+ <tabstop>jarBtn</tabstop>
+ <tabstop>addEmptyBtn</tabstop>
<tabstop>reloadBtn</tabstop>
+ <tabstop>downloadBtn</tabstop>
+ <tabstop>tabWidget</tabstop>
</tabstops>
<resources/>
<connections/>
diff --git a/application/pages/WorldListPage.cpp b/application/pages/WorldListPage.cpp
index b6195bb3..56a7e791 100644
--- a/application/pages/WorldListPage.cpp
+++ b/application/pages/WorldListPage.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2015-2017 MultiMC Contributors
+/* Copyright 2015-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/WorldListPage.h b/application/pages/WorldListPage.h
index 89d86158..d0aa6150 100644
--- a/application/pages/WorldListPage.h
+++ b/application/pages/WorldListPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2015-2017 MultiMC Contributors
+/* Copyright 2015-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
#include <QWidget>
-#include "minecraft/onesix/OneSixInstance.h"
+#include "minecraft/MinecraftInstance.h"
#include "BasePage.h"
#include <MultiMC.h>
#include <LoggedProcess.h>
diff --git a/application/pages/global/AccountListPage.cpp b/application/pages/global/AccountListPage.cpp
index 8edcad98..63943174 100644
--- a/application/pages/global/AccountListPage.cpp
+++ b/application/pages/global/AccountListPage.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/global/AccountListPage.h b/application/pages/global/AccountListPage.h
index 52022b6c..fa5561fe 100644
--- a/application/pages/global/AccountListPage.h
+++ b/application/pages/global/AccountListPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/global/CustomCommandsPage.cpp b/application/pages/global/CustomCommandsPage.cpp
new file mode 100644
index 00000000..1352b6be
--- /dev/null
+++ b/application/pages/global/CustomCommandsPage.cpp
@@ -0,0 +1,50 @@
+#include "CustomCommandsPage.h"
+#include <QVBoxLayout>
+#include <QTabWidget>
+#include <QTabBar>
+
+CustomCommandsPage::CustomCommandsPage(QWidget* parent): QWidget(parent)
+{
+
+ auto verticalLayout = new QVBoxLayout(this);
+ verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setContentsMargins(0, 0, 0, 0);
+
+ auto tabWidget = new QTabWidget(this);
+ tabWidget->setObjectName(QStringLiteral("tabWidget"));
+ commands = new CustomCommands(this);
+ tabWidget->addTab(commands, "Foo");
+ tabWidget->tabBar()->hide();
+ verticalLayout->addWidget(tabWidget);
+ loadSettings();
+}
+
+CustomCommandsPage::~CustomCommandsPage()
+{
+}
+
+bool CustomCommandsPage::apply()
+{
+ applySettings();
+ return true;
+}
+
+void CustomCommandsPage::applySettings()
+{
+ auto s = MMC->settings();
+ s->set("PreLaunchCommand", commands->prelaunchCommand());
+ s->set("WrapperCommand", commands->wrapperCommand());
+ s->set("PostExitCommand", commands->postexitCommand());
+}
+
+void CustomCommandsPage::loadSettings()
+{
+ auto s = MMC->settings();
+ commands->initialize(
+ false,
+ true,
+ s->get("PreLaunchCommand").toString(),
+ s->get("WrapperCommand").toString(),
+ s->get("PostExitCommand").toString()
+ );
+}
diff --git a/application/pages/global/CustomCommandsPage.h b/application/pages/global/CustomCommandsPage.h
new file mode 100644
index 00000000..52256ed3
--- /dev/null
+++ b/application/pages/global/CustomCommandsPage.h
@@ -0,0 +1,55 @@
+/* Copyright 2018-2018 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+#include <QDialog>
+
+#include "pages/BasePage.h"
+#include <MultiMC.h>
+#include "widgets/CustomCommands.h"
+
+class CustomCommandsPage : public QWidget, public BasePage
+{
+ Q_OBJECT
+
+public:
+ explicit CustomCommandsPage(QWidget *parent = 0);
+ ~CustomCommandsPage();
+
+ QString displayName() const override
+ {
+ return tr("Custom Commands");
+ }
+ QIcon icon() const override
+ {
+ return MMC->getThemedIcon("custom-commands");
+ }
+ QString id() const override
+ {
+ return "custom-commands";
+ }
+ QString helpPage() const override
+ {
+ return "Custom-commands";
+ }
+ bool apply() override;
+
+private:
+ void applySettings();
+ void loadSettings();
+ CustomCommands * commands;
+};
diff --git a/application/pages/global/ExternalToolsPage.cpp b/application/pages/global/ExternalToolsPage.cpp
index b446fc06..ff63ecbb 100644
--- a/application/pages/global/ExternalToolsPage.cpp
+++ b/application/pages/global/ExternalToolsPage.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -206,12 +206,12 @@ void ExternalToolsPage::on_jsonEditorBrowseBtn_clicked()
? QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).first()
#endif
: ui->jsonEditorTextBox->text());
- QString cooked_file = FS::NormalizePath(raw_file);
- if (cooked_file.isEmpty())
+ if (raw_file.isEmpty())
{
return;
}
+ QString cooked_file = FS::NormalizePath(raw_file);
// it has to exist and be an executable
if (QFileInfo(cooked_file).exists() && QFileInfo(cooked_file).isExecutable())
diff --git a/application/pages/global/ExternalToolsPage.h b/application/pages/global/ExternalToolsPage.h
index b222db5e..de46d8a6 100644
--- a/application/pages/global/ExternalToolsPage.h
+++ b/application/pages/global/ExternalToolsPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/global/ExternalToolsPage.ui b/application/pages/global/ExternalToolsPage.ui
index cdb33b35..5f19898b 100644
--- a/application/pages/global/ExternalToolsPage.ui
+++ b/application/pages/global/ExternalToolsPage.ui
@@ -63,7 +63,7 @@
<item>
<widget class="QLabel" name="jprofilerLink">
<property name="text">
- <string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://www.ej-technologies.com/products/jprofiler/overview.html&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.ej-technologies.com/products/jprofiler/overview.html&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://www.ej-technologies.com/products/jprofiler/overview.html&quot;&gt;http://www.ej-technologies.com/products/jprofiler/overview.html&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
@@ -100,7 +100,7 @@
<item>
<widget class="QLabel" name="jvisualvmLink">
<property name="text">
- <string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://visualvm.java.net/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://visualvm.java.net/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://visualvm.github.io/&quot;&gt;https://visualvm.github.io/&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
@@ -137,7 +137,7 @@
<item>
<widget class="QLabel" name="mceditLink">
<property name="text">
- <string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://www.mcedit.net/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.mcedit.net/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://www.mcedit.net/&quot;&gt;http://www.mcedit.net/&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
diff --git a/application/pages/global/JavaPage.cpp b/application/pages/global/JavaPage.cpp
index 543cc11f..57250c79 100644
--- a/application/pages/global/JavaPage.cpp
+++ b/application/pages/global/JavaPage.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,6 @@
#include <QDir>
#include "dialogs/VersionSelectDialog.h"
-#include <ColumnResizer.h>
#include "java/JavaUtils.h"
#include "java/JavaInstallList.h"
@@ -30,16 +29,15 @@
#include "settings/SettingsObject.h"
#include <FileSystem.h>
#include "MultiMC.h"
+#include <sys.h>
JavaPage::JavaPage(QWidget *parent) : QWidget(parent), ui(new Ui::JavaPage)
{
ui->setupUi(this);
ui->tabWidget->tabBar()->hide();
- auto resizer = new ColumnResizer(this);
- resizer->addWidgetsFromLayout(ui->javaSettingsGroupBox->layout(), 0);
- resizer->addWidgetsFromLayout(ui->customCommandsGroupBox->layout(), 0);
-
+ auto sysMB = Sys::getSystemRam() / Sys::megabyte;
+ ui->maxMemSpinBox->setMaximum(sysMB);
loadSettings();
}
@@ -59,36 +57,46 @@ void JavaPage::applySettings()
auto s = MMC->settings();
// Memory
- s->set("MinMemAlloc", ui->minMemSpinBox->value());
- s->set("MaxMemAlloc", ui->maxMemSpinBox->value());
+ int min = ui->minMemSpinBox->value();
+ int max = ui->maxMemSpinBox->value();
+ if(min < max)
+ {
+ s->set("MinMemAlloc", min);
+ s->set("MaxMemAlloc", max);
+ }
+ else
+ {
+ s->set("MinMemAlloc", max);
+ s->set("MaxMemAlloc", min);
+ }
s->set("PermGen", ui->permGenSpinBox->value());
// Java Settings
s->set("JavaPath", ui->javaPathTextBox->text());
s->set("JvmArgs", ui->jvmArgsTextBox->text());
JavaCommon::checkJVMArgs(s->get("JvmArgs").toString(), this->parentWidget());
-
- // Custom Commands
- s->set("PreLaunchCommand", ui->preLaunchCmdTextBox->text());
- s->set("WrapperCommand", ui->wrapperCmdTextBox->text());
- s->set("PostExitCommand", ui->postExitCmdTextBox->text());
}
void JavaPage::loadSettings()
{
auto s = MMC->settings();
// Memory
- ui->minMemSpinBox->setValue(s->get("MinMemAlloc").toInt());
- ui->maxMemSpinBox->setValue(s->get("MaxMemAlloc").toInt());
+ int min = s->get("MinMemAlloc").toInt();
+ int max = s->get("MaxMemAlloc").toInt();
+ if(min < max)
+ {
+ ui->minMemSpinBox->setValue(min);
+ ui->maxMemSpinBox->setValue(max);
+ }
+ else
+ {
+ ui->minMemSpinBox->setValue(max);
+ ui->maxMemSpinBox->setValue(min);
+ }
ui->permGenSpinBox->setValue(s->get("PermGen").toInt());
// Java Settings
ui->javaPathTextBox->setText(s->get("JavaPath").toString());
ui->jvmArgsTextBox->setText(s->get("JvmArgs").toString());
-
- // Custom Commands
- ui->preLaunchCmdTextBox->setText(s->get("PreLaunchCommand").toString());
- ui->wrapperCmdTextBox->setText(s->get("WrapperCommand").toString());
- ui->postExitCmdTextBox->setText(s->get("PostExitCommand").toString());
}
void JavaPage::on_javaDetectBtn_clicked()
@@ -108,14 +116,14 @@ void JavaPage::on_javaDetectBtn_clicked()
void JavaPage::on_javaBrowseBtn_clicked()
{
QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"));
- QString cooked_path = FS::NormalizePath(raw_path);
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
- if(cooked_path.isEmpty())
+ if(raw_path.isEmpty())
{
return;
}
+ QString cooked_path = FS::NormalizePath(raw_path);
QFileInfo javaInfo(cooked_path);;
if(!javaInfo.exists() || !javaInfo.isExecutable())
{
diff --git a/application/pages/global/JavaPage.h b/application/pages/global/JavaPage.h
index 4feec427..e3a9f37f 100644
--- a/application/pages/global/JavaPage.h
+++ b/application/pages/global/JavaPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/global/JavaPage.ui b/application/pages/global/JavaPage.ui
index 9023b932..201b310c 100644
--- a/application/pages/global/JavaPage.ui
+++ b/application/pages/global/JavaPage.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>545</width>
- <height>760</height>
+ <height>580</height>
</rect>
</property>
<property name="sizePolicy">
@@ -17,7 +17,16 @@
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -217,62 +226,17 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="customCommandsGroupBox">
- <property name="title">
- <string>Custom Commands</string>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
</property>
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="3" column="0">
- <widget class="QLabel" name="labelPostExitCmd">
- <property name="text">
- <string>Post-exit command:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="labelPreLaunchCmd">
- <property name="text">
- <string>Pre-launch command:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="preLaunchCmdTextBox"/>
- </item>
- <item row="3" column="1">
- <widget class="QLineEdit" name="postExitCmdTextBox"/>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="labelWrapperCmd">
- <property name="text">
- <string>Wrapper command:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="wrapperCmdTextBox"/>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="labelCustomCmdsDescription">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
</property>
- <property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Pre-launch command runs before the instance launches and post-exit command runs after it exits. Both will be run in MultiMC's working folder with INST_ID, INST_DIR, and INST_NAME as environment variables.&lt;/p&gt;&lt;p&gt;Wrapper command allows running java using an extra wrapper program (like 'optirun' on Linux)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
+ </spacer>
</item>
</layout>
</widget>
@@ -289,9 +253,6 @@
<tabstop>jvmArgsTextBox</tabstop>
<tabstop>javaDetectBtn</tabstop>
<tabstop>javaTestBtn</tabstop>
- <tabstop>preLaunchCmdTextBox</tabstop>
- <tabstop>wrapperCmdTextBox</tabstop>
- <tabstop>postExitCmdTextBox</tabstop>
<tabstop>tabWidget</tabstop>
</tabstops>
<resources/>
diff --git a/application/pages/global/MinecraftPage.cpp b/application/pages/global/MinecraftPage.cpp
index b3a56327..aecd8d57 100644
--- a/application/pages/global/MinecraftPage.cpp
+++ b/application/pages/global/MinecraftPage.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/global/MinecraftPage.h b/application/pages/global/MinecraftPage.h
index 311b0967..d1abd6fe 100644
--- a/application/pages/global/MinecraftPage.h
+++ b/application/pages/global/MinecraftPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/global/MultiMCPage.cpp b/application/pages/global/MultiMCPage.cpp
index 4073f6b7..620fc3a3 100644
--- a/application/pages/global/MultiMCPage.cpp
+++ b/application/pages/global/MultiMCPage.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,6 @@
#include <QDir>
#include <QTextCharFormat>
-#include <ColumnResizer.h>
#include "updater/UpdateChecker.h"
#include "settings/SettingsObject.h"
@@ -49,10 +48,6 @@ MultiMCPage::MultiMCPage(QWidget *parent) : QWidget(parent), ui(new Ui::MultiMCP
ui->sortingModeGroup->setId(ui->sortByNameBtn, Sort_Name);
ui->sortingModeGroup->setId(ui->sortLastLaunchedBtn, Sort_LastLaunch);
- auto resizer = new ColumnResizer(this);
- resizer->addWidgetsFromLayout(ui->groupBox->layout(), 1);
- resizer->addWidgetsFromLayout(ui->foldersBox->layout(), 1);
-
defaultFormat = new QTextCharFormat(ui->fontPreview->currentCharFormat());
m_languageModel = MMC->translations();
@@ -97,40 +92,14 @@ bool MultiMCPage::apply()
return true;
}
-void MultiMCPage::on_ftbLauncherBrowseBtn_clicked()
-{
- QString raw_dir = QFileDialog::getExistingDirectory(this, tr("FTB Launcher Folder"),
- ui->ftbLauncherBox->text());
- QString cooked_dir = FS::NormalizePath(raw_dir);
-
- // do not allow current dir - it's dirty. Do not allow dirs that don't exist
- if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
- {
- ui->ftbLauncherBox->setText(cooked_dir);
- }
-}
-void MultiMCPage::on_ftbBrowseBtn_clicked()
-{
- QString raw_dir =
- QFileDialog::getExistingDirectory(this, tr("FTB Folder"), ui->ftbBox->text());
- QString cooked_dir = FS::NormalizePath(raw_dir);
-
- // do not allow current dir - it's dirty. Do not allow dirs that don't exist
- if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
- {
- ui->ftbBox->setText(cooked_dir);
- }
-}
-
void MultiMCPage::on_instDirBrowseBtn_clicked()
{
- QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Instance Folder"),
- ui->instDirTextBox->text());
- QString cooked_dir = FS::NormalizePath(raw_dir);
+ QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Instance Folder"), ui->instDirTextBox->text());
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
- if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
+ if (!raw_dir.isEmpty() && QDir(raw_dir).exists())
{
+ QString cooked_dir = FS::NormalizePath(raw_dir);
if (FS::checkProblemticPathJava(QDir(cooked_dir)))
{
QMessageBox warning;
@@ -157,40 +126,26 @@ void MultiMCPage::on_instDirBrowseBtn_clicked()
void MultiMCPage::on_iconsDirBrowseBtn_clicked()
{
- QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Icons Folder"),
- ui->iconsDirTextBox->text());
- QString cooked_dir = FS::NormalizePath(raw_dir);
+ QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Icons Folder"), ui->iconsDirTextBox->text());
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
- if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
+ if (!raw_dir.isEmpty() && QDir(raw_dir).exists())
{
+ QString cooked_dir = FS::NormalizePath(raw_dir);
ui->iconsDirTextBox->setText(cooked_dir);
}
}
void MultiMCPage::on_modsDirBrowseBtn_clicked()
{
- QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Mods Folder"),
- ui->modsDirTextBox->text());
- QString cooked_dir = FS::NormalizePath(raw_dir);
+ QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Mods Folder"), ui->modsDirTextBox->text());
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
- if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
+ if (!raw_dir.isEmpty() && QDir(raw_dir).exists())
{
+ QString cooked_dir = FS::NormalizePath(raw_dir);
ui->modsDirTextBox->setText(cooked_dir);
}
}
-void MultiMCPage::on_lwjglDirBrowseBtn_clicked()
-{
- QString raw_dir = QFileDialog::getExistingDirectory(this, tr("LWJGL Folder"),
- ui->lwjglDirTextBox->text());
- QString cooked_dir = FS::NormalizePath(raw_dir);
-
- // do not allow current dir - it's dirty. Do not allow dirs that don't exist
- if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
- {
- ui->lwjglDirTextBox->setText(cooked_dir);
- }
-}
void MultiMCPage::languageIndexChanged(int index)
{
@@ -315,6 +270,9 @@ void MultiMCPage::applySettings()
s->set("IconTheme", "iOS");
break;
case 7:
+ s->set("IconTheme", "flat");
+ break;
+ case 8:
s->set("IconTheme", "custom");
break;
case 0:
@@ -346,16 +304,10 @@ void MultiMCPage::applySettings()
s->set("ConsoleMaxLines", ui->lineLimitSpinBox->value());
s->set("ConsoleOverflowStop", ui->checkStopLogging->checkState() != Qt::Unchecked);
- // FTB
- s->set("TrackFTBInstances", ui->trackFtbBox->isChecked());
- s->set("FTBLauncherLocal", FS::NormalizePath(ui->ftbLauncherBox->text()));
- s->set("FTBRoot", FS::NormalizePath(ui->ftbBox->text()));
-
// Folders
// TODO: Offer to move instances to new instance folder.
s->set("InstanceDir", ui->instDirTextBox->text());
s->set("CentralModsDir", ui->modsDirTextBox->text());
- s->set("LWJGLDir", ui->lwjglDirTextBox->text());
s->set("IconsDir", ui->iconsDirTextBox->text());
auto sortMode = (InstSortMode)ui->sortingModeGroup->checkedId();
@@ -414,10 +366,14 @@ void MultiMCPage::loadSettings()
{
ui->themeComboBox->setCurrentIndex(6);
}
- else if (theme == "custom")
+ else if (theme == "flat")
{
ui->themeComboBox->setCurrentIndex(7);
}
+ else if (theme == "custom")
+ {
+ ui->themeComboBox->setCurrentIndex(8);
+ }
else
{
ui->themeComboBox->setCurrentIndex(0);
@@ -457,15 +413,9 @@ void MultiMCPage::loadSettings()
ui->lineLimitSpinBox->setValue(s->get("ConsoleMaxLines").toInt());
ui->checkStopLogging->setChecked(s->get("ConsoleOverflowStop").toBool());
- // FTB
- ui->trackFtbBox->setChecked(s->get("TrackFTBInstances").toBool());
- ui->ftbLauncherBox->setText(s->get("FTBLauncherLocal").toString());
- ui->ftbBox->setText(s->get("FTBRoot").toString());
-
// Folders
ui->instDirTextBox->setText(s->get("InstanceDir").toString());
ui->modsDirTextBox->setText(s->get("CentralModsDir").toString());
- ui->lwjglDirTextBox->setText(s->get("LWJGLDir").toString());
ui->iconsDirTextBox->setText(s->get("IconsDir").toString());
QString sortMode = s->get("InstSortMode").toString();
diff --git a/application/pages/global/MultiMCPage.h b/application/pages/global/MultiMCPage.h
index 98eb353d..d5194c0e 100644
--- a/application/pages/global/MultiMCPage.h
+++ b/application/pages/global/MultiMCPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -64,12 +64,8 @@ private:
private
slots:
- void on_ftbLauncherBrowseBtn_clicked();
- void on_ftbBrowseBtn_clicked();
-
void on_instDirBrowseBtn_clicked();
void on_modsDirBrowseBtn_clicked();
- void on_lwjglDirBrowseBtn_clicked();
void on_iconsDirBrowseBtn_clicked();
void languageIndexChanged(int index);
diff --git a/application/pages/global/MultiMCPage.ui b/application/pages/global/MultiMCPage.ui
index 0b966876..124401c3 100644
--- a/application/pages/global/MultiMCPage.ui
+++ b/application/pages/global/MultiMCPage.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>467</width>
- <height>614</height>
+ <height>629</height>
</rect>
</property>
<property name="sizePolicy">
@@ -89,75 +89,6 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="groupBox">
- <property name="title">
- <string notr="true">FTB</string>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="2" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>&amp;Launcher:</string>
- </property>
- <property name="buddy">
- <cstring>ftbLauncherBox</cstring>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="ftbLauncherBox">
- <property name="enabled">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLineEdit" name="ftbBox"/>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Files:</string>
- </property>
- <property name="buddy">
- <cstring>ftbBox</cstring>
- </property>
- </widget>
- </item>
- <item row="3" column="2">
- <widget class="QToolButton" name="ftbBrowseBtn">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="text">
- <string notr="true">...</string>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QToolButton" name="ftbLauncherBrowseBtn">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="focusPolicy">
- <enum>Qt::TabFocus</enum>
- </property>
- <property name="text">
- <string notr="true">...</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0" colspan="3">
- <widget class="QCheckBox" name="trackFtbBox">
- <property name="text">
- <string>Track FTB instances</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
<widget class="QGroupBox" name="foldersBox">
<property name="title">
<string>Folders</string>
@@ -196,9 +127,6 @@
<item row="1" column="1">
<widget class="QLineEdit" name="modsDirTextBox"/>
</item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="lwjglDirTextBox"/>
- </item>
<item row="1" column="2">
<widget class="QToolButton" name="modsDirBrowseBtn">
<property name="text">
@@ -206,27 +134,10 @@
</property>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QLabel" name="labelLWJGLDir">
- <property name="text">
- <string notr="true">LW&amp;JGL:</string>
- </property>
- <property name="buddy">
- <cstring>lwjglDirTextBox</cstring>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QToolButton" name="lwjglDirBrowseBtn">
- <property name="text">
- <string notr="true">...</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
+ <item row="2" column="1">
<widget class="QLineEdit" name="iconsDirTextBox"/>
</item>
- <item row="3" column="0">
+ <item row="2" column="0">
<widget class="QLabel" name="labelIconsDir">
<property name="text">
<string>&amp;Icons:</string>
@@ -236,7 +147,7 @@
</property>
</widget>
</item>
- <item row="3" column="2">
+ <item row="2" column="2">
<widget class="QToolButton" name="iconsDirBrowseBtn">
<property name="text">
<string notr="true">...</string>
@@ -393,6 +304,11 @@
</item>
<item>
<property name="text">
+ <string notr="true">Flat</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
<string>Custom</string>
</property>
</item>
@@ -645,17 +561,10 @@
<tabstop>tabWidget</tabstop>
<tabstop>autoUpdateCheckBox</tabstop>
<tabstop>updateChannelComboBox</tabstop>
- <tabstop>trackFtbBox</tabstop>
- <tabstop>ftbLauncherBox</tabstop>
- <tabstop>ftbLauncherBrowseBtn</tabstop>
- <tabstop>ftbBox</tabstop>
- <tabstop>ftbBrowseBtn</tabstop>
<tabstop>instDirTextBox</tabstop>
<tabstop>instDirBrowseBtn</tabstop>
<tabstop>modsDirTextBox</tabstop>
<tabstop>modsDirBrowseBtn</tabstop>
- <tabstop>lwjglDirTextBox</tabstop>
- <tabstop>lwjglDirBrowseBtn</tabstop>
<tabstop>iconsDirTextBox</tabstop>
<tabstop>iconsDirBrowseBtn</tabstop>
<tabstop>resetNotificationsBtn</tabstop>
diff --git a/application/pages/global/PackagesPage.cpp b/application/pages/global/PackagesPage.cpp
index e15ddbab..5fd4934c 100644
--- a/application/pages/global/PackagesPage.cpp
+++ b/application/pages/global/PackagesPage.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2015-2017 MultiMC Contributors
+/* Copyright 2015-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,10 +38,17 @@ static QString formatRequires(const VersionPtr &version)
auto iter = reqs.begin();
while (iter != reqs.end())
{
- auto &uid = iter.key();
- auto &version = iter.value();
+ auto &uid = iter->uid;
+ auto &version = iter->equalsVersion;
const QString readable = ENV.metadataIndex()->hasUid(uid) ? ENV.metadataIndex()->get(uid)->humanReadable() : uid;
- lines.append(QString("%1 (%2)").arg(readable, version));
+ if(!version.isEmpty())
+ {
+ lines.append(QString("%1 (%2)").arg(readable, version));
+ }
+ else
+ {
+ lines.append(QString("%1").arg(readable));
+ }
iter++;
}
return lines.join('\n');
@@ -95,7 +102,7 @@ QIcon PackagesPage::icon() const
void PackagesPage::on_refreshIndexBtn_clicked()
{
- ENV.metadataIndex()->load();
+ ENV.metadataIndex()->load(Net::Mode::Online);
}
void PackagesPage::on_refreshFileBtn_clicked()
{
@@ -104,7 +111,7 @@ void PackagesPage::on_refreshFileBtn_clicked()
{
return;
}
- list->load();
+ list->load(Net::Mode::Online);
}
void PackagesPage::on_refreshVersionBtn_clicked()
{
@@ -113,7 +120,7 @@ void PackagesPage::on_refreshVersionBtn_clicked()
{
return;
}
- version->load();
+ version->load(Net::Mode::Online);
}
void PackagesPage::on_fileSearchEdit_textChanged(const QString &search)
@@ -156,7 +163,7 @@ void PackagesPage::updateCurrentVersionList(const QModelIndex &index)
ui->fileName->setText(list->name());
m_versionProxy->setSourceModel(list.get());
ui->refreshFileBtn->setText(tr("Refresh %1").arg(list->humanReadable()));
- list->load();
+ list->load(Net::Mode::Offline);
}
else
{
@@ -213,5 +220,5 @@ void PackagesPage::updateVersion()
void PackagesPage::opened()
{
- ENV.metadataIndex()->load();
+ ENV.metadataIndex()->load(Net::Mode::Offline);
}
diff --git a/application/pages/global/PackagesPage.h b/application/pages/global/PackagesPage.h
index 80c2886d..2afbcf8e 100644
--- a/application/pages/global/PackagesPage.h
+++ b/application/pages/global/PackagesPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2015-2017 MultiMC Contributors
+/* Copyright 2015-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/global/PasteEEPage.cpp b/application/pages/global/PasteEEPage.cpp
index 2ceb725f..3d4e3a88 100644
--- a/application/pages/global/PasteEEPage.cpp
+++ b/application/pages/global/PasteEEPage.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,11 +43,7 @@ void PasteEEPage::loadSettings()
{
auto s = MMC->settings();
QString keyToUse = s->get("PasteEEAPIKey").toString();
- if(keyToUse == "public")
- {
- ui->publicButton->setChecked(true);
- }
- else if(keyToUse == "multimc")
+ if(keyToUse == "multimc")
{
ui->multimcButton->setChecked(true);
}
@@ -65,8 +61,6 @@ void PasteEEPage::applySettings()
QString pasteKeyToUse;
if (ui->customButton->isChecked())
pasteKeyToUse = ui->customAPIkeyEdit->text();
- else if (ui->publicButton->isChecked())
- pasteKeyToUse = "public";
else
{
pasteKeyToUse = "multimc";
diff --git a/application/pages/global/PasteEEPage.h b/application/pages/global/PasteEEPage.h
index 2bd5f2f2..1b152577 100644
--- a/application/pages/global/PasteEEPage.h
+++ b/application/pages/global/PasteEEPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/global/PasteEEPage.ui b/application/pages/global/PasteEEPage.ui
index 689c421f..10883781 100644
--- a/application/pages/global/PasteEEPage.ui
+++ b/application/pages/global/PasteEEPage.ui
@@ -40,16 +40,6 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
- <widget class="QRadioButton" name="publicButton">
- <property name="text">
- <string>No key - &amp;2MB upload limit</string>
- </property>
- <attribute name="buttonGroup">
- <string notr="true">pasteButtonGroup</string>
- </attribute>
- </widget>
- </item>
- <item>
<widget class="QRadioButton" name="multimcButton">
<property name="text">
<string>MultiMC key - 12MB &amp;upload limit</string>
@@ -89,7 +79,7 @@
<item>
<widget class="QLabel" name="label">
<property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://paste.ee&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#2980b9;&quot;&gt;paste.ee&lt;/span&gt;&lt;/a&gt; is used by MultiMC for log uploads. If you have a &lt;a href=&quot;https://paste.ee&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#2980b9;&quot;&gt;paste.ee&lt;/span&gt;&lt;/a&gt; account, you can add your API key here and have your uploaded logs paired with your account.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://paste.ee&quot;&gt;paste.ee&lt;/a&gt; is used by MultiMC for log uploads. If you have a &lt;a href=&quot;https://paste.ee&quot;&gt;paste.ee&lt;/a&gt; account, you can add your API key here and have your uploaded logs paired with your account.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
@@ -97,6 +87,9 @@
<property name="wordWrap">
<bool>true</bool>
</property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
</widget>
</item>
</layout>
@@ -123,7 +116,6 @@
</widget>
<tabstops>
<tabstop>tabWidget</tabstop>
- <tabstop>publicButton</tabstop>
<tabstop>multimcButton</tabstop>
<tabstop>customButton</tabstop>
<tabstop>customAPIkeyEdit</tabstop>
diff --git a/application/pages/global/ProxyPage.cpp b/application/pages/global/ProxyPage.cpp
index a68963ca..1e75bab1 100644
--- a/application/pages/global/ProxyPage.cpp
+++ b/application/pages/global/ProxyPage.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/pages/global/ProxyPage.h b/application/pages/global/ProxyPage.h
index 1ed53808..565c2857 100644
--- a/application/pages/global/ProxyPage.h
+++ b/application/pages/global/ProxyPage.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/resources/MultiMC.icns b/application/resources/MultiMC.icns
index 05ce9207..c4eb59d5 100644
--- a/application/resources/MultiMC.icns
+++ b/application/resources/MultiMC.icns
Binary files differ
diff --git a/application/resources/MultiMC.ico b/application/resources/MultiMC.ico
index 734af0fb..1846964e 100644
--- a/application/resources/MultiMC.ico
+++ b/application/resources/MultiMC.ico
Binary files differ
diff --git a/application/resources/OSX/OSX.qrc b/application/resources/OSX/OSX.qrc
index 20c71eb8..a7d7be17 100644
--- a/application/resources/OSX/OSX.qrc
+++ b/application/resources/OSX/OSX.qrc
@@ -10,6 +10,7 @@
<file>scalable/copy.svg</file>
<file>scalable/coremods.svg</file>
<file>scalable/externaltools.svg</file>
+ <file>scalable/help.svg</file>
<file>scalable/instance-settings.svg</file>
<file>scalable/jarmods.svg</file>
<file>scalable/java.svg</file>
@@ -31,5 +32,6 @@
<file>scalable/status-good.svg</file>
<file>scalable/status-yellow.svg</file>
<file>scalable/viewfolder.svg</file>
+ <file>scalable/worlds.svg</file>
</qresource>
</RCC>
diff --git a/application/resources/OSX/scalable/help.svg b/application/resources/OSX/scalable/help.svg
new file mode 100644
index 00000000..9d1b367c
--- /dev/null
+++ b/application/resources/OSX/scalable/help.svg
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xml:space="preserve"
+ enable-background="new 0 0 32 32"
+ viewBox="0 0 32 32"
+ y="0px"
+ x="0px"
+ id="Calque_1"
+ version="1.1"><metadata
+ id="metadata24"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs22" /><rect
+ id="rect2"
+ height="32"
+ width="32"
+ fill="none"
+ clip-rule="evenodd"
+ fill-rule="evenodd" /><path
+ id="path4"
+ d="M30,28H2c-1.1,0-2-0.9-2-2V8c0-1.1,0.9-2,2-2h28c1.1,0,2,0.9,2,2v18C32,27.1,31.1,28,30,28z"
+ fill="#B6B5B6" /><path
+ id="path6"
+ d="M30,27H2c-1.1,0-2-0.9-2-2V8c0-1.1,0.9-2,2-2h28c1.1,0,2,0.9,2,2v17C32,26.1,31.1,27,30,27z"
+ fill="#FBFBFB" /><g
+ id="g854"><g
+ id="g861"
+ transform="matrix(0.51850737,0,0,0.51850737,29.410453,7.662064)"
+ style="fill:#585858;fill-opacity:1"><g
+ id="text832"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.34714317px;line-height:85.45981598px;font-family:'Nimbus Sans L';-inkscape-font-specification:'Nimbus Sans L';letter-spacing:0px;word-spacing:0px;fill:#585858;fill-opacity:1;stroke:none;stroke-width:3.4183929px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ aria-label="?"><path
+ id="path855"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Monofonto;-inkscape-font-specification:Monofonto;fill:#585858;fill-opacity:1;stroke-width:3.4183929px"
+ d="m -20.968435,13.920532 c 0,0.6381 -0.07293,1.239737 -0.218777,1.804911 -0.145852,0.565174 -0.401092,1.066538 -0.76572,1.504093 -0.401092,0.492249 -0.774836,0.902456 -1.121233,1.230621 -0.346397,0.328166 -0.656332,0.6381 -0.929803,0.929803 -0.25524,0.273471 -0.464902,0.556059 -0.628985,0.847762 -0.145851,0.291703 -0.218777,0.656331 -0.218777,1.093885 v 0.38286 h -3.144921 V 20.72997 c 0,-0.601637 0.136736,-1.221505 0.410207,-1.859605 0.273471,-0.656332 0.756604,-1.285316 1.449399,-1.886953 0.346397,-0.309935 0.638099,-0.583406 0.875108,-0.820415 0.237009,-0.25524 0.428439,-0.492248 0.57429,-0.711025 0.145851,-0.237009 0.246124,-0.483133 0.300819,-0.738373 0.05469,-0.273471 0.08204,-0.57429 0.08204,-0.902456 0,-0.528711 -0.12762,-0.984497 -0.38286,-1.367357 -0.237009,-0.401091 -0.656331,-0.601637 -1.257968,-0.601637 -1.057423,0 -1.640829,0.692794 -1.750218,2.078383 h -3.06288 c 0.01823,-0.747489 0.145853,-1.431167 0.38286,-2.051036 0.237009,-0.6381 0.565175,-1.185043 0.984498,-1.640829 0.419323,-0.474017 0.920687,-0.8386455 1.504092,-1.0938855 0.601637,-0.25524 1.2762,-0.38286 2.023689,-0.38286 0.838646,0 1.567903,0.1367357 2.187771,0.4102072 0.619869,0.25524 1.130349,0.6198684 1.53144,1.0938853 0.401092,0.455786 0.692795,1.002729 0.875109,1.640829 0.200546,0.619869 0.300819,1.294432 0.30082,2.023689 z" /></g><circle
+ id="circle6-6"
+ r="1.8"
+ cy="25.466606"
+ cx="-26.38899"
+ style="fill:#585858;fill-opacity:1" /></g><g
+ id="g17"><g
+ id="_x38__12_"><g
+ id="g12"><path
+ d="M16,9c-4.4,0-8,3.6-8,8c0,4.4,3.6,8,8,8s8-3.6,8-8C24,12.6,20.4,9,16,9z M16,24c-3.9,0-7-3.1-7-7 c0-3.9,3.1-7,7-7s7,3.1,7,7C23,20.9,19.9,24,16,24z"
+ id="path10"
+ fill="#585858" /></g></g></g></g></svg> \ No newline at end of file
diff --git a/application/resources/OSX/scalable/worlds.svg b/application/resources/OSX/scalable/worlds.svg
new file mode 100644
index 00000000..b1491272
--- /dev/null
+++ b/application/resources/OSX/scalable/worlds.svg
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xml:space="preserve"
+ enable-background="new 0 0 24 24"
+ viewBox="0 0 24 24"
+ y="0px"
+ x="0px"
+ id="Calque_1"
+ version="1.1"><metadata
+ id="metadata22"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs20" /><path
+ id="path2"
+ d="M21,20H9c-1.1,0-2-0.9-2-2V6c0-1.1,0.9-2,2-2h12c1.1,0,2,0.9,2,2 v12C23,19.1,22.1,20,21,20z"
+ fill="#E6E6E6"
+ clip-rule="evenodd"
+ fill-rule="evenodd" /><rect
+ id="rect4"
+ height="24"
+ width="24"
+ fill="none" /><g
+ id="_x36__8_"><g
+ id="g8"><path
+ style="fill:#585858"
+ id="path6"
+ d="M 21,4 H 9 C 7.9,4 7,4.9 7,6 v 12 c 0,1.1 0.9,2 2,2 h 12 c 1.1,0 2,-0.9 2,-2 V 6 C 23,4.9 22.1,4 21,4 Z m 1,14 -1,1 H 9 L 8,18 V 6 C 8,5.4 8.4,5 9,5 h 12 c 0.6,0 1,0.4 1,1 z" /></g></g><circle
+ style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd"
+ id="circle11"
+ r="1"
+ cy="11.559504"
+ cx="-3.8492424" /><g
+ style="stroke:#585858;stroke-width:1.55746377;stroke-opacity:1"
+ transform="matrix(0.55621145,0.32075232,-0.32075232,0.55621145,11.232654,-2.0314203)"
+ id="g881"><ellipse
+ ry="8.9473686"
+ rx="8.9473696"
+ cy="16"
+ cx="16"
+ id="path845"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#585858;stroke-width:1.55746377;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /><ellipse
+ ry="8.9473686"
+ rx="3.4915254"
+ cy="15.947369"
+ cx="16"
+ id="path845-3"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#585858;stroke-width:1.55746377;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /><path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#585858;stroke-width:1.55746377;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 8.1848294,12.430327 C 12.570183,14.790801 20.662272,13.548526 23.355,11.76263"
+ id="path870" /><path
+ id="path872"
+ d="M 8.2166335,20.492522 C 12.601987,18.132048 21.148735,17.776739 23.841463,19.562635"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#585858;stroke-width:1.55746377;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /></g></svg> \ No newline at end of file
diff --git a/application/resources/flat/flat.qrc b/application/resources/flat/flat.qrc
new file mode 100644
index 00000000..aee2e30c
--- /dev/null
+++ b/application/resources/flat/flat.qrc
@@ -0,0 +1,44 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource prefix="/icons/flat">
+ <file>index.theme</file>
+ <file>scalable/about.svg</file>
+ <file>scalable/accounts.svg</file>
+ <file>scalable/bug.svg</file>
+ <file>scalable/cat.svg</file>
+ <file>scalable/centralmods.svg</file>
+ <file>scalable/checkupdate.svg</file>
+ <file>scalable/copy.svg</file>
+ <file>scalable/coremods.svg</file>
+ <file>scalable/discord.svg</file>
+ <file>scalable/externaltools.svg</file>
+ <file>scalable/help.svg</file>
+ <file>scalable/instance-settings.svg</file>
+ <file>scalable/jarmods.svg</file>
+ <file>scalable/java.svg</file>
+ <file>scalable/loadermods.svg</file>
+ <file>scalable/log.svg</file>
+ <file>scalable/minecraft.svg</file>
+ <file>scalable/multimc.svg</file>
+ <file>scalable/new.svg</file>
+ <file>scalable/news.svg</file>
+ <file>scalable/notes.svg</file>
+ <file>scalable/packages.svg</file>
+ <file>scalable/patreon.svg</file>
+ <file>scalable/proxy.svg</file>
+ <file>scalable/quickmods.svg</file>
+ <file>scalable/reddit-alien.svg</file>
+ <file>scalable/refresh.svg</file>
+ <file>scalable/resourcepacks.svg</file>
+ <file>scalable/screenshot-placeholder.svg</file>
+ <file>scalable/screenshots.svg</file>
+ <file>scalable/settings.svg</file>
+ <file>scalable/star.svg</file>
+ <file>scalable/status-bad.svg</file>
+ <file>scalable/status-good.svg</file>
+ <file>scalable/status-running.svg</file>
+ <file>scalable/status-yellow.svg</file>
+ <file>scalable/viewfolder.svg</file>
+ <file>scalable/worlds.svg</file>
+ </qresource>
+</RCC>
diff --git a/application/resources/flat/index.theme b/application/resources/flat/index.theme
new file mode 100644
index 00000000..34e27aa0
--- /dev/null
+++ b/application/resources/flat/index.theme
@@ -0,0 +1,11 @@
+[Icon Theme]
+Name=Flat
+Comment=Flat icons
+Inherits=multimc
+Directories=scalable
+
+[scalable]
+Size=48
+Type=Scalable
+MinSize=16
+MaxSize=256
diff --git a/application/resources/flat/scalable/about.svg b/application/resources/flat/scalable/about.svg
new file mode 100644
index 00000000..4f85045d
--- /dev/null
+++ b/application/resources/flat/scalable/about.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/accounts.svg b/application/resources/flat/scalable/accounts.svg
new file mode 100644
index 00000000..e6a1328d
--- /dev/null
+++ b/application/resources/flat/scalable/accounts.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M16,13C15.71,13 15.38,13 15.03,13.05C16.19,13.89 17,15 17,16.5V19H23V16.5C23,14.17 18.33,13 16,13M8,13C5.67,13 1,14.17 1,16.5V19H15V16.5C15,14.17 10.33,13 8,13M8,11A3,3 0 0,0 11,8A3,3 0 0,0 8,5A3,3 0 0,0 5,8A3,3 0 0,0 8,11M16,11A3,3 0 0,0 19,8A3,3 0 0,0 16,5A3,3 0 0,0 13,8A3,3 0 0,0 16,11Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/bug.svg b/application/resources/flat/scalable/bug.svg
new file mode 100644
index 00000000..ea370faa
--- /dev/null
+++ b/application/resources/flat/scalable/bug.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/cat.svg b/application/resources/flat/scalable/cat.svg
new file mode 100644
index 00000000..e90763b5
--- /dev/null
+++ b/application/resources/flat/scalable/cat.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M12,8L10.67,8.09C9.81,7.07 7.4,4.5 5,4.5C5,4.5 3.03,7.46 4.96,11.41C4.41,12.24 4.07,12.67 4,13.66L2.07,13.95L2.28,14.93L4.04,14.67L4.18,15.38L2.61,16.32L3.08,17.21L4.53,16.32C5.68,18.76 8.59,20 12,20C15.41,20 18.32,18.76 19.47,16.32L20.92,17.21L21.39,16.32L19.82,15.38L19.96,14.67L21.72,14.93L21.93,13.95L20,13.66C19.93,12.67 19.59,12.24 19.04,11.41C20.97,7.46 19,4.5 19,4.5C16.6,4.5 14.19,7.07 13.33,8.09L12,8M9,11A1,1 0 0,1 10,12A1,1 0 0,1 9,13A1,1 0 0,1 8,12A1,1 0 0,1 9,11M15,11A1,1 0 0,1 16,12A1,1 0 0,1 15,13A1,1 0 0,1 14,12A1,1 0 0,1 15,11M11,14H13L12.3,15.39C12.5,16.03 13.06,16.5 13.75,16.5A1.5,1.5 0 0,0 15.25,15H15.75A2,2 0 0,1 13.75,17C13,17 12.35,16.59 12,16V16H12C11.65,16.59 11,17 10.25,17A2,2 0 0,1 8.25,15H8.75A1.5,1.5 0 0,0 10.25,16.5C10.94,16.5 11.5,16.03 11.7,15.39L11,14Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/centralmods.svg b/application/resources/flat/scalable/centralmods.svg
new file mode 100644
index 00000000..c694662a
--- /dev/null
+++ b/application/resources/flat/scalable/centralmods.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M20 6h-8l-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-2.06 11L15 15.28 12.06 17l.78-3.33-2.59-2.24 3.41-.29L15 8l1.34 3.14 3.41.29-2.59 2.24.78 3.33z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/checkupdate.svg b/application/resources/flat/scalable/checkupdate.svg
new file mode 100644
index 00000000..e6525a08
--- /dev/null
+++ b/application/resources/flat/scalable/checkupdate.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1-2.73 2.71-2.73 7.08 0 9.79 2.73 2.71 7.15 2.71 9.88 0C18.32 15.65 19 14.08 19 12.1h2c0 1.98-.88 4.55-2.64 6.29-3.51 3.48-9.21 3.48-12.72 0-3.5-3.47-3.53-9.11-.02-12.58 3.51-3.47 9.14-3.47 12.65 0L21 3v7.12zM12.5 8v4.25l3.5 2.08-.72 1.21L11 13V8h1.5z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/copy.svg b/application/resources/flat/scalable/copy.svg
new file mode 100644
index 00000000..36986e0d
--- /dev/null
+++ b/application/resources/flat/scalable/copy.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9h-4v4h-2v-4H9V9h4V5h2v4h4v2z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/coremods.svg b/application/resources/flat/scalable/coremods.svg
new file mode 100644
index 00000000..21a3450e
--- /dev/null
+++ b/application/resources/flat/scalable/coremods.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M22,12A10,10,0,1,1,12,2,10,10,0,0,1,22,12ZM12,4a8,8,0,1,0,8,8A8,8,0,0,0,12,4Zm4.23,14-1.12-4.82,3.73-3.23-4.92-.42L12,5,10.08,9.54,5.16,10l3.73,3.23L7.77,18,12,15.45,16.23,18"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/discord.svg b/application/resources/flat/scalable/discord.svg
new file mode 100644
index 00000000..ad63180f
--- /dev/null
+++ b/application/resources/flat/scalable/discord.svg
@@ -0,0 +1,4 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M10.14,11.63a1.15,1.15,0,1,0,1,1.14A1.1,1.1,0,0,0,10.14,11.63Zm3.75,0a1.15,1.15,0,1,0,1,1.14A1.1,1.1,0,0,0,13.89,11.63Z"/>
+ <path d="M18.89,3H5.11A2.11,2.11,0,0,0,3,5.12V19a2.11,2.11,0,0,0,2.11,2.12H16.77l-.55-1.9,1.32,1.22,1.24,1.15,2.21,2V5.12A2.11,2.11,0,0,0,18.89,3Zm-4,13.43s-.37-.44-.68-.83a3.25,3.25,0,0,0,1.86-1.22,5.89,5.89,0,0,1-1.18.61,6.77,6.77,0,0,1-1.49.44,7.21,7.21,0,0,1-2.66,0A8.63,8.63,0,0,1,9.25,15a6,6,0,0,1-.75-.35l-.09-.05,0,0-.29-.17a3.2,3.2,0,0,0,1.8,1.21l-.69.85a3.73,3.73,0,0,1-3.14-1.56,13.77,13.77,0,0,1,1.48-6,5.09,5.09,0,0,1,2.89-1.08l.1.12A6.94,6.94,0,0,0,7.82,9.26s.23-.12.61-.3a7.72,7.72,0,0,1,2.33-.65l.17,0a8.7,8.7,0,0,1,2.08,0,8.38,8.38,0,0,1,3.1,1A6.85,6.85,0,0,0,13.55,8l.14-.16a5.09,5.09,0,0,1,2.89,1.08,13.77,13.77,0,0,1,1.48,6A3.76,3.76,0,0,1,14.92,16.43Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/externaltools.svg b/application/resources/flat/scalable/externaltools.svg
new file mode 100644
index 00000000..55820dfc
--- /dev/null
+++ b/application/resources/flat/scalable/externaltools.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M22.7,19L13.6,9.9C14.5,7.6 14,4.9 12.1,3C10.1,1 7.1,0.6 4.7,1.7L9,6L6,9L1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1C4.8,14 7.5,14.5 9.8,13.6L18.9,22.7C19.3,23.1 19.9,23.1 20.3,22.7L22.6,20.4C23.1,20 23.1,19.3 22.7,19Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/help.svg b/application/resources/flat/scalable/help.svg
new file mode 100644
index 00000000..26d5d7f4
--- /dev/null
+++ b/application/resources/flat/scalable/help.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ id="svg4"
+ version="1.1"
+ width="24"
+ viewBox="0 0 24 24"
+ height="24"
+ fill="#757575">
+ <path
+ d="m 15.07,11.25 -0.9,0.92 C 13.45,12.89 13,13.5 13,15 h -2 v -0.5 c 0,-1.11 0.45,-2.11 1.17,-2.83 l 1.24,-1.26 C 13.78,10.049999 14,9.549999 14,9 14,7.89 13.100001,7 12,7 A 2,2 0 0 0 10,9 H 7.9999995 A 4,4 0 0 1 12,5 4,4 0 0 1 16,9 c 0,0.879999 -0.36,1.67 -0.93,2.25 M 13,19 h -2 v -2 h 2 M 12,2 A 10,10 0 0 0 1.9999995,12 10,10 0 0 0 12,22 10,10 0 0 0 22,12 C 22,6.47 17.5,2 12,2 Z"
+ id="path817" />
+</svg>
diff --git a/application/resources/flat/scalable/instance-settings.svg b/application/resources/flat/scalable/instance-settings.svg
new file mode 100644
index 00000000..dd9d86ed
--- /dev/null
+++ b/application/resources/flat/scalable/instance-settings.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/jarmods.svg b/application/resources/flat/scalable/jarmods.svg
new file mode 100644
index 00000000..db90fa34
--- /dev/null
+++ b/application/resources/flat/scalable/jarmods.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M2,21H20V19H2M20,8H18V5h2m0-2H4V13a4,4,0,0,0,4,4h6a4,4,0,0,0,4-4V10h2a2,2,0,0,0,2-2V5A2,2,0,0,0,20,3ZM11,4.43l1.62,3.29,3.63.53-2.63,2.56.62,3.62L11,12.72,7.75,14.43l.62-3.62L5.74,8.25l3.63-.53Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/java.svg b/application/resources/flat/scalable/java.svg
new file mode 100644
index 00000000..dc19ee23
--- /dev/null
+++ b/application/resources/flat/scalable/java.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M2,21H20V19H2M20,8H18V5H20M20,3H4V13A4,4 0 0,0 8,17H14A4,4 0 0,0 18,13V10H20A2,2 0 0,0 22,8V5C22,3.89 21.1,3 20,3Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/loadermods.svg b/application/resources/flat/scalable/loadermods.svg
new file mode 100644
index 00000000..8a2fd12c
--- /dev/null
+++ b/application/resources/flat/scalable/loadermods.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M16.23,18l-1.12-4.82,3.73-3.23-4.92-.42L12,5,10.08,9.54,5.16,10l3.73,3.23L7.77,18,12,15.45,16.23,18M20,4H4V20H20Zm0,18H4a2,2,0,0,1-2-2V4A2,2,0,0,1,4,2H20a2,2,0,0,1,2,2V20A2,2,0,0,1,20,22Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/log.svg b/application/resources/flat/scalable/log.svg
new file mode 100644
index 00000000..e8caa08a
--- /dev/null
+++ b/application/resources/flat/scalable/log.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/minecraft.svg b/application/resources/flat/scalable/minecraft.svg
new file mode 100644
index 00000000..c17c44cd
--- /dev/null
+++ b/application/resources/flat/scalable/minecraft.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L6.04,7.5L12,10.85L17.96,7.5L12,4.15M5,15.91L11,19.29V12.58L5,9.21V15.91M19,15.91V9.21L13,12.58V19.29L19,15.91Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/multimc.svg b/application/resources/flat/scalable/multimc.svg
new file mode 100644
index 00000000..1c1f2359
--- /dev/null
+++ b/application/resources/flat/scalable/multimc.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M0,2A2,2,0,0,1,2,0H22a2,2,0,0,1,2,2V8L22,8V6H20V8H18v2H16V8H14V6H12V8H10V6H8v4H6V8H4V6H2V8H0ZM0,22a2,2,0,0,0,2,2H22a2,2,0,0,0,2-2V10H22V22H2V10H0Zm18.71-3.29a3.83,3.83,0,0,0-5.41-5.41L12,14.59l-1.29-1.29a3.83,3.83,0,1,0,0,5.41L12,17.41l1.29,1.29a3.83,3.83,0,0,0,5.41,0Zm-4-4a1.83,1.83,0,1,1,0,2.59L13.41,16Zm-5.41,0L10.59,16,9.29,17.29a1.83,1.83,0,1,1,0-2.59Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/new.svg b/application/resources/flat/scalable/new.svg
new file mode 100644
index 00000000..01f19d7c
--- /dev/null
+++ b/application/resources/flat/scalable/new.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/news.svg b/application/resources/flat/scalable/news.svg
new file mode 100644
index 00000000..8868414e
--- /dev/null
+++ b/application/resources/flat/scalable/news.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M20,11H4V8H20M20,15H13V13H20M20,19H13V17H20M11,19H4V13H11M20.33,4.67L18.67,3L17,4.67L15.33,3L13.67,4.67L12,3L10.33,4.67L8.67,3L7,4.67L5.33,3L3.67,4.67L2,3V19A2,2 0 0,0 4,21H20A2,2 0 0,0 22,19V3L20.33,4.67Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/notes.svg b/application/resources/flat/scalable/notes.svg
new file mode 100644
index 00000000..ebe0cb5a
--- /dev/null
+++ b/application/resources/flat/scalable/notes.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M14,17H7V15H14M17,13H7V11H17M17,9H7V7H17M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/packages.svg b/application/resources/flat/scalable/packages.svg
new file mode 100644
index 00000000..fe576a43
--- /dev/null
+++ b/application/resources/flat/scalable/packages.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M5.12,5l.81-1h12l.94,1m1.67.23L19.15,3.55A1.45,1.45,0,0,0,18,3H6a1.49,1.49,0,0,0-1.16.55L3.46,5.23A1.92,1.92,0,0,0,3,6.5V19a2,2,0,0,0,2,2H19a2,2,0,0,0,2-2V6.5A1.92,1.92,0,0,0,20.54,5.23Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/patreon.svg b/application/resources/flat/scalable/patreon.svg
new file mode 100644
index 00000000..ad561f57
--- /dev/null
+++ b/application/resources/flat/scalable/patreon.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M12,3h0a9,9,0,0,0-9,9v9H5.09V12a6.91,6.91,0,1,1,7.23,6.9,5.9,5.9,0,0,1-2.59-.47v-3A4.13,4.13,0,1,0,7.85,12v9H12A9,9,0,1,0,12,3Zm0,15.91h0Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/proxy.svg b/application/resources/flat/scalable/proxy.svg
new file mode 100644
index 00000000..4956fec8
--- /dev/null
+++ b/application/resources/flat/scalable/proxy.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M22 4v-.5C22 2.12 20.88 1 19.5 1S17 2.12 17 3.5V4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h5c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zm-.8 0h-3.4v-.5c0-.94.76-1.7 1.7-1.7s1.7.76 1.7 1.7V4zm-2.28 8c.04.33.08.66.08 1 0 2.08-.8 3.97-2.1 5.39-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H7v-2h2c.55 0 1-.45 1-1V8h2c1.1 0 2-.9 2-2V3.46c-.95-.3-1.95-.46-3-.46C5.48 3 1 7.48 1 13s4.48 10 10 10 10-4.48 10-10c0-.34-.02-.67-.05-1h-2.03zM10 20.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L8 16v1c0 1.1.9 2 2 2v1.93z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/quickmods.svg b/application/resources/flat/scalable/quickmods.svg
new file mode 100644
index 00000000..952d1e0e
--- /dev/null
+++ b/application/resources/flat/scalable/quickmods.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M8.75,5.5v7.15H10.7V18.5l4.55-7.8h-2.6l2.6-5.2ZM20,4H4V20H20Zm0,18H4a2,2,0,0,1-2-2V4A2,2,0,0,1,4,2H20a2,2,0,0,1,2,2V20A2,2,0,0,1,20,22Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/reddit-alien.svg b/application/resources/flat/scalable/reddit-alien.svg
new file mode 100644
index 00000000..9bcfbedc
--- /dev/null
+++ b/application/resources/flat/scalable/reddit-alien.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M20,11.86a1.76,1.76,0,0,0-1.75-1.75,1.73,1.73,0,0,0-1.22.51,9,9,0,0,0-4.67-1.38l1-3.16L16,6.71s0,0,0,0a1.46,1.46,0,1,0,.1-.53l-2.89-.68a.25.25,0,0,0-.29.17L11.83,9.23a9.16,9.16,0,0,0-4.88,1.36,1.75,1.75,0,1,0-2.07,2.79,3,3,0,0,0-.06.58C4.82,16.58,8,18.7,12,18.7s7.14-2.13,7.14-4.74a2.94,2.94,0,0,0-.05-.55A1.74,1.74,0,0,0,20,11.86ZM8.51,13.08a1.06,1.06,0,1,1,1.06,1.06A1.06,1.06,0,0,1,8.51,13.08Zm6.06,3.14A3.48,3.48,0,0,1,12,17h0a3.48,3.48,0,0,1-2.56-.79.25.25,0,0,1,.35-.35,3,3,0,0,0,2.2.65h0a3,3,0,0,0,2.2-.65.25.25,0,1,1,.35.35Zm-.13-2.08a1.06,1.06,0,1,1,1.06-1.06A1.06,1.06,0,0,1,14.44,14.14Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/refresh.svg b/application/resources/flat/scalable/refresh.svg
new file mode 100644
index 00000000..94be1e27
--- /dev/null
+++ b/application/resources/flat/scalable/refresh.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/resourcepacks.svg b/application/resources/flat/scalable/resourcepacks.svg
new file mode 100644
index 00000000..b6054baf
--- /dev/null
+++ b/application/resources/flat/scalable/resourcepacks.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M19.51 3.08L3.08 19.51c.09.34.27.65.51.9.25.24.56.42.9.51L20.93 4.49c-.19-.69-.73-1.23-1.42-1.41zM11.88 3L3 11.88v2.83L14.71 3h-2.83zM5 3c-1.1 0-2 .9-2 2v2l4-4H5zm14 18c.55 0 1.05-.22 1.41-.59.37-.36.59-.86.59-1.41v-2l-4 4h2zm-9.71 0h2.83L21 12.12V9.29L9.29 21z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/screenshot-placeholder.svg b/application/resources/flat/scalable/screenshot-placeholder.svg
new file mode 100644
index 00000000..99e0c17a
--- /dev/null
+++ b/application/resources/flat/scalable/screenshot-placeholder.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M21 15h2v2h-2v-2zm0-4h2v2h-2v-2zm2 8h-2v2c1 0 2-1 2-2zM13 3h2v2h-2V3zm8 4h2v2h-2V7zm0-4v2h2c0-1-1-2-2-2zM1 7h2v2H1V7zm16-4h2v2h-2V3zm0 16h2v2h-2v-2zM3 3C2 3 1 4 1 5h2V3zm6 0h2v2H9V3zM5 3h2v2H5V3zm-4 8v8c0 1.1.9 2 2 2h12V11H1zm2 8l2.5-3.21 1.79 2.15 2.5-3.22L13 19H3z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/screenshots.svg b/application/resources/flat/scalable/screenshots.svg
new file mode 100644
index 00000000..208bb104
--- /dev/null
+++ b/application/resources/flat/scalable/screenshots.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M21 3H3C2 3 1 4 1 5v14c0 1.1.9 2 2 2h18c1 0 2-1 2-2V5c0-1-1-2-2-2zM5 17l3.5-4.5 2.5 3.01L14.5 11l4.5 6H5z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/settings.svg b/application/resources/flat/scalable/settings.svg
new file mode 100644
index 00000000..dd9d86ed
--- /dev/null
+++ b/application/resources/flat/scalable/settings.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/star.svg b/application/resources/flat/scalable/star.svg
new file mode 100644
index 00000000..878bdca8
--- /dev/null
+++ b/application/resources/flat/scalable/star.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M12,17.27L18.18,21L16.54,13.97L22,9.24L14.81,8.62L12,2L9.19,8.62L2,9.24L7.45,13.97L5.82,21L12,17.27Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/status-bad.svg b/application/resources/flat/scalable/status-bad.svg
new file mode 100644
index 00000000..3f8e0116
--- /dev/null
+++ b/application/resources/flat/scalable/status-bad.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M12,2A10,10,0,1,0,22,12,10,10,0,0,0,12,2Zm4.24,7.17L13.41,12l2.83,2.83-1.41,1.41L12,13.41,9.17,16.24,7.76,14.83,10.59,12,7.76,9.17,9.17,7.76,12,10.59l2.83-2.83Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/status-good.svg b/application/resources/flat/scalable/status-good.svg
new file mode 100644
index 00000000..3503d6ba
--- /dev/null
+++ b/application/resources/flat/scalable/status-good.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/status-running.svg b/application/resources/flat/scalable/status-running.svg
new file mode 100644
index 00000000..7c750319
--- /dev/null
+++ b/application/resources/flat/scalable/status-running.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5v-9l6 4.5-6 4.5z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/status-yellow.svg b/application/resources/flat/scalable/status-yellow.svg
new file mode 100644
index 00000000..ac2d2349
--- /dev/null
+++ b/application/resources/flat/scalable/status-yellow.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/viewfolder.svg b/application/resources/flat/scalable/viewfolder.svg
new file mode 100644
index 00000000..2f5e29c9
--- /dev/null
+++ b/application/resources/flat/scalable/viewfolder.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/flat/scalable/worlds.svg b/application/resources/flat/scalable/worlds.svg
new file mode 100644
index 00000000..95a59bd4
--- /dev/null
+++ b/application/resources/flat/scalable/worlds.svg
@@ -0,0 +1,3 @@
+<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M18.2,13a3.18,3.18,0,0,1-.84,2.16.8.8,0,0,0-.76-.56h-.4V13.4a.4.4,0,0,0-.4-.4H13.4v-.8h.8a.4.4,0,0,0,.4-.4V11h.8a.8.8,0,0,0,.8-.8V10A3.19,3.19,0,0,1,18.2,13Zm-4.4,1.6v-.4l-1.92-1.92a3.18,3.18,0,0,0,2.72,3.89V15.4A.8.8,0,0,1,13.8,14.6ZM22,8V18a2,2,0,0,1-2,2H4a2,2,0,0,1-2-2V6A2,2,0,0,1,4,4h6l2,2h8A2,2,0,0,1,22,8Zm-3,5a4,4,0,1,0-4,4A4,4,0,0,0,19,13Z"/>
+</svg> \ No newline at end of file
diff --git a/application/resources/iOS/iOS.qrc b/application/resources/iOS/iOS.qrc
index eb625d0b..0cb642f4 100644
--- a/application/resources/iOS/iOS.qrc
+++ b/application/resources/iOS/iOS.qrc
@@ -10,6 +10,7 @@
<file>scalable/copy.svg</file>
<file>scalable/coremods.svg</file>
<file>scalable/externaltools.svg</file>
+ <file>scalable/help.svg</file>
<file>scalable/instance-settings.svg</file>
<file>scalable/jarmods.svg</file>
<file>scalable/java.svg</file>
@@ -31,5 +32,6 @@
<file>scalable/status-good.svg</file>
<file>scalable/status-yellow.svg</file>
<file>scalable/viewfolder.svg</file>
+ <file>scalable/worlds.svg</file>
</qresource>
</RCC>
diff --git a/application/resources/iOS/scalable/help.svg b/application/resources/iOS/scalable/help.svg
new file mode 100644
index 00000000..9c2d2e93
--- /dev/null
+++ b/application/resources/iOS/scalable/help.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xml:space="preserve"
+ enable-background="new 0 0 32 32"
+ viewBox="0 0 32 32"
+ y="0px"
+ x="0px"
+ id="Calque_1"
+ version="1.1"><metadata
+ id="metadata18"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs16" /><g
+ id="g11"><g
+ id="_x38__8_"><g
+ id="g6"><path
+ id="path4"
+ d="M16,0C7.2,0,0,7.2,0,16c0,8.8,7.2,16,16,16c8.8,0,16-7.2,16-16C32,7.2,24.8,0,16,0z M16,30 C8.3,30,2,23.7,2,16C2,8.3,8.3,2,16,2c7.7,0,14,6.3,14,14C30,23.7,23.7,30,16,30z"
+ fill="#3366CC" /></g></g></g><g
+ style="fill:#3366cc;fill-opacity:1"
+ transform="matrix(1.0878826,0,0,1.0878826,44.136533,-3.5919647)"
+ id="g861"><g
+ aria-label="?"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.34714317px;line-height:85.45981598px;font-family:'Nimbus Sans L';-inkscape-font-specification:'Nimbus Sans L';letter-spacing:0px;word-spacing:0px;fill:#3366cc;fill-opacity:1;stroke:none;stroke-width:3.4183929px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="text832"><path
+ d="m -20.968435,13.920532 c 0,0.6381 -0.07293,1.239737 -0.218777,1.804911 -0.145852,0.565174 -0.401092,1.066538 -0.76572,1.504093 -0.401092,0.492249 -0.774836,0.902456 -1.121233,1.230621 -0.346397,0.328166 -0.656332,0.6381 -0.929803,0.929803 -0.25524,0.273471 -0.464902,0.556059 -0.628985,0.847762 -0.145851,0.291703 -0.218777,0.656331 -0.218777,1.093885 v 0.38286 h -3.144921 V 20.72997 c 0,-0.601637 0.136736,-1.221505 0.410207,-1.859605 0.273471,-0.656332 0.756604,-1.285316 1.449399,-1.886953 0.346397,-0.309935 0.638099,-0.583406 0.875108,-0.820415 0.237009,-0.25524 0.428439,-0.492248 0.57429,-0.711025 0.145851,-0.237009 0.246124,-0.483133 0.300819,-0.738373 0.05469,-0.273471 0.08204,-0.57429 0.08204,-0.902456 0,-0.528711 -0.12762,-0.984497 -0.38286,-1.367357 -0.237009,-0.401091 -0.656331,-0.601637 -1.257968,-0.601637 -1.057423,0 -1.640829,0.692794 -1.750218,2.078383 h -3.06288 c 0.01823,-0.747489 0.145853,-1.431167 0.38286,-2.051036 0.237009,-0.6381 0.565175,-1.185043 0.984498,-1.640829 0.419323,-0.474017 0.920687,-0.8386455 1.504092,-1.0938855 0.601637,-0.25524 1.2762,-0.38286 2.023689,-0.38286 0.838646,0 1.567903,0.1367357 2.187771,0.4102072 0.619869,0.25524 1.130349,0.6198684 1.53144,1.0938853 0.401092,0.455786 0.692795,1.002729 0.875109,1.640829 0.200546,0.619869 0.300819,1.294432 0.30082,2.023689 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Monofonto;-inkscape-font-specification:Monofonto;fill:#3366cc;fill-opacity:1;stroke-width:3.4183929px"
+ id="path855" /></g><circle
+ style="fill:#3366cc;fill-opacity:1"
+ cx="-26.38899"
+ cy="25.466606"
+ r="1.8"
+ id="circle6-6" /></g></svg> \ No newline at end of file
diff --git a/application/resources/iOS/scalable/worlds.svg b/application/resources/iOS/scalable/worlds.svg
new file mode 100644
index 00000000..1596fd76
--- /dev/null
+++ b/application/resources/iOS/scalable/worlds.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xml:space="preserve"
+ enable-background="new 0 0 32 32"
+ viewBox="0 0 32 32"
+ y="0px"
+ x="0px"
+ id="Calque_1"
+ version="1.1"><metadata
+ id="metadata12"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs10" /><g
+ id="_x36__21_"><g
+ id="g4"><path
+ style="fill:#3366cc;fill-opacity:1"
+ id="path2"
+ d="M 4,0 C 1.8,0 0,1.8 0,4 v 24 c 0,2.2 1.8,4 4,4 h 24 c 2.2,0 4,-1.8 4,-4 V 4 C 32,1.8 30.2,0 28,0 Z m 0,2 h 24 c 0.1375,0 0.272461,0.014258 0.402344,0.041016 6.24e-4,1.264e-4 0.0013,-1.27e-4 0.002,0 0.782578,0.1593282 1.395359,0.7721094 1.554687,1.5546875 C 29.98599,3.7261594 30,3.8618476 30,4 v 24 c 0,0.1375 -0.01426,0.272461 -0.04102,0.402344 -1.26e-4,6.24e-4 1.27e-4,0.0013 0,0.002 -0.159328,0.782578 -0.772109,1.395359 -1.554687,1.554687 C 28.273841,29.98599 28.138152,30 28,30 H 4 c -0.1378377,0 -0.2724931,-0.01471 -0.4023438,-0.04102 -6.162e-4,-1.27e-4 -0.00134,1.28e-4 -0.00195,0 -0.7825781,-0.159328 -1.3953593,-0.772109 -1.5546875,-1.554687 -1.27e-4,-6.24e-4 1.264e-4,-0.0013 0,-0.002 C 2.0142578,28.272461 2,28.1375 2,28 V 4 c 0,-0.1378377 0.014708,-0.2724931 0.041016,-0.4023438 1.27e-4,-6.162e-4 -1.275e-4,-0.00134 0,-0.00195 C 2.2003438,2.813125 2.813125,2.2003438 3.5957031,2.0410156 3.7261328,2.0144609 3.8615,2 4,2 Z" /></g></g><g
+ style="stroke:#3366cc;stroke-width:1.63695813;stroke-opacity:1"
+ transform="matrix(1.0584012,0.61035173,-0.61035173,1.0584012,8.831209,-10.700046)"
+ id="g881"><ellipse
+ ry="8.9473686"
+ rx="8.9473696"
+ cy="16"
+ cx="16"
+ id="path845"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#3366cc;stroke-width:1.63695813;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /><ellipse
+ ry="8.9473686"
+ rx="3.4915254"
+ cy="15.947369"
+ cx="16"
+ id="path845-3"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#3366cc;stroke-width:1.63695813;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /><path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#3366cc;stroke-width:1.63695813;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 8.1848294,12.430327 C 12.570183,14.790801 20.662272,13.548526 23.355,11.76263"
+ id="path870" /><path
+ id="path872"
+ d="M 8.2166335,20.492522 C 12.601987,18.132048 21.148735,17.776739 23.841463,19.562635"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#3366cc;stroke-width:1.63695813;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /></g></svg> \ No newline at end of file
diff --git a/application/resources/multimc/128x128/instances/infinity.png b/application/resources/multimc/128x128/instances/infinity.png
index 226847fb..cc7ca7bc 100644
--- a/application/resources/multimc/128x128/instances/infinity.png
+++ b/application/resources/multimc/128x128/instances/infinity.png
Binary files differ
diff --git a/application/resources/multimc/multimc.qrc b/application/resources/multimc/multimc.qrc
index b4bc5c16..780e458d 100644
--- a/application/resources/multimc/multimc.qrc
+++ b/application/resources/multimc/multimc.qrc
@@ -2,7 +2,10 @@
<RCC version="1.0">
<qresource prefix="/icons/multimc">
<file>index.theme</file>
- <!-- Logo. Our own. -->
+ <!-- Logo. Our own. For use in branding. -->
+ <file>scalable/logo.svg</file>
+
+ <!-- Logo. Our own. For use within the application (Settings pages and similar). -->
<file>scalable/multimc.svg</file>
<!-- REDDIT logo icon, needs reddit license! -->
@@ -59,6 +62,9 @@
<file>64x64/screenshots.png</file>
<file>scalable/screenshots.svg</file>
+ <!-- Custom commands. -->
+ <file>scalable/custom-commands.svg</file>
+
<!-- Patron logo. (C) 2014 Patreon, Inc., http://www.patreon.com/toolbox?ftyp=media -->
<file>16x16/patreon.png</file>
<file>22x22/patreon.png</file>
diff --git a/application/resources/multimc/scalable/custom-commands.svg b/application/resources/multimc/scalable/custom-commands.svg
new file mode 100644
index 00000000..b7f1a149
--- /dev/null
+++ b/application/resources/multimc/scalable/custom-commands.svg
@@ -0,0 +1,338 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg2"
+ height="64"
+ width="64"
+ version="1.1"
+ sodipodi:docname="custom-commands.svg"
+ inkscape:version="0.92.2 5c3e80d, 2017-08-06">
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="3840"
+ inkscape:window-height="2123"
+ id="namedview52"
+ showgrid="false"
+ inkscape:zoom="20.85965"
+ inkscape:cx="28.409224"
+ inkscape:cy="33.675543"
+ inkscape:window-x="1200"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:bbox-nodes="true">
+ <inkscape:grid
+ type="xygrid"
+ id="grid858" />
+ </sodipodi:namedview>
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient3931">
+ <stop
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:0"
+ id="stop3933" />
+ <stop
+ offset="0.69999987"
+ style="stop-color:#ffffff;stop-opacity:0.10396039"
+ id="stop3939" />
+ <stop
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:0.14356436"
+ id="stop3935" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3900">
+ <stop
+ offset="0"
+ style="stop-color:#f6f6f6;stop-opacity:1"
+ id="stop3902" />
+ <stop
+ offset="0.75714284"
+ style="stop-color:#494949;stop-opacity:1"
+ id="stop3904" />
+ <stop
+ offset="1"
+ style="stop-color:#2c2c2c;stop-opacity:1"
+ id="stop3906" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3808">
+ <stop
+ offset="0"
+ style="stop-color:#333333;stop-opacity:1"
+ id="stop3810" />
+ <stop
+ offset="1"
+ style="stop-color:#c8c8c8;stop-opacity:1"
+ id="stop3812" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3030">
+ <stop
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1"
+ id="stop3032" />
+ <stop
+ offset="0.75714284"
+ style="stop-color:#333333;stop-opacity:1"
+ id="stop3038" />
+ <stop
+ offset="1"
+ style="stop-color:#4d4d4d;stop-opacity:1"
+ id="stop3034" />
+ </linearGradient>
+ <radialGradient
+ gradientTransform="matrix(1.3519242,1.8838281,-1.5359217,1.1022493,15.935733,948.08165)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient3030"
+ id="radialGradient3036"
+ fy="14.242621"
+ fx="29.381905"
+ r="16.375"
+ cy="14.242621"
+ cx="29.381905" />
+ <linearGradient
+ gradientTransform="matrix(1.5,0,0,1,-16,4)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient3808"
+ id="linearGradient3824"
+ y2="1033.8622"
+ x2="34"
+ y1="1033.8622"
+ x1="30" />
+ <linearGradient
+ gradientTransform="matrix(0.82142857,0,0,1.500001,6.7142857,-522.68214)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient3808"
+ id="linearGradient3834"
+ y2="1039.3622"
+ x2="32"
+ y1="1043.3622"
+ x1="32" />
+ <radialGradient
+ gradientTransform="matrix(6.479993,1.9525666,-10.415476,2.1794781,10657.845,-1282.8793)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient3900"
+ id="radialGradient3844"
+ fy="1039.813"
+ fx="30.724609"
+ r="3"
+ cy="1039.813"
+ cx="30.724609" />
+ <radialGradient
+ gradientTransform="matrix(2.5191507,2.9862959,-4.0491019,3.333339,4186.8847,-2518.44)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient3900"
+ id="radialGradient3852"
+ fy="1039.813"
+ fx="30.724609"
+ r="3"
+ cy="1039.813"
+ cx="30.724609" />
+ <radialGradient
+ gradientTransform="matrix(-2.5191507,2.9863064,4.0491022,3.3333507,-4122.8849,-2518.4524)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient3900"
+ id="radialGradient3857"
+ fy="1039.813"
+ fx="30.724609"
+ r="3"
+ cy="1039.813"
+ cx="30.724609" />
+ <radialGradient
+ gradientTransform="matrix(-0.69414478,2.3073251,-1.6952184,-0.67174747,96.941544,960.82172)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient3900"
+ id="radialGradient3937"
+ fy="21.976955"
+ fx="31.946348"
+ r="19.25"
+ cy="21.976955"
+ cx="31.946348" />
+ </defs>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ transform="translate(0,-988.36218)">
+ <rect
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient3036);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.25954175;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="rect2997"
+ y="992.99194"
+ x="5.6297708"
+ ry="0.70710492"
+ rx="0.70710504"
+ height="53.740437"
+ width="53.740459" />
+ </g>
+ <g
+ id="g1021"
+ transform="translate(1.7703716e-7,-0.42472956)">
+ <g
+ style="fill:#008000"
+ transform="matrix(0.08572572,0,0,0.08572572,9.999999,10.424713)"
+ id="g899">
+ <g
+ style="fill:#008000"
+ id="g867">
+ <g
+ style="fill:#008000"
+ id="g865">
+ <path
+ style="fill:#008000"
+ d="m 226.434,249.503 c 0,-6.995 -2.705,-13.403 -7.846,-18.556 L 61.8,74.165 c -5.128,-5.141 -11.554,-7.852 -18.568,-7.852 -7.026,0 -13.452,2.717 -18.556,7.846 l -16.83,16.83 c -5.129,5.135 -7.84,11.549 -7.84,18.538 0,7.026 2.717,13.452 7.846,18.556 L 129.267,249.503 7.84,370.936 C 2.711,376.071 0,382.491 0,389.486 c 0,7.02 2.717,13.439 7.846,18.544 l 16.775,16.774 c 5.116,5.165 11.555,7.895 18.611,7.895 7.044,0 13.47,-2.723 18.556,-7.846 l 156.813,-156.8 c 5.128,-5.14 7.833,-11.549 7.833,-18.55 z"
+ id="path860"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#008000"
+ d="m 498.866,384.951 h -323.02 c -7.203,0 -13.611,2.583 -18.581,7.528 -4.896,4.92 -7.484,11.327 -7.484,18.531 v 21.536 c 0,7.252 2.607,13.672 7.491,18.543 4.915,4.927 11.34,7.528 18.574,7.528 h 323.02 c 7.239,0 13.659,-2.607 18.531,-7.497 4.927,-4.908 7.533,-11.334 7.533,-18.58 v -21.537 c 0,-7.209 -2.589,-13.616 -7.54,-18.592 -4.913,-4.877 -11.321,-7.46 -18.524,-7.46 z"
+ id="path862"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="fill:#008000"
+ id="g869" />
+ <g
+ style="fill:#008000"
+ id="g871" />
+ <g
+ style="fill:#008000"
+ id="g873" />
+ <g
+ style="fill:#008000"
+ id="g875" />
+ <g
+ style="fill:#008000"
+ id="g877" />
+ <g
+ style="fill:#008000"
+ id="g879" />
+ <g
+ style="fill:#008000"
+ id="g881" />
+ <g
+ style="fill:#008000"
+ id="g883" />
+ <g
+ style="fill:#008000"
+ id="g885" />
+ <g
+ style="fill:#008000"
+ id="g887" />
+ <g
+ style="fill:#008000"
+ id="g889" />
+ <g
+ style="fill:#008000"
+ id="g891" />
+ <g
+ style="fill:#008000"
+ id="g893" />
+ <g
+ style="fill:#008000"
+ id="g895" />
+ <g
+ style="fill:#008000"
+ id="g897" />
+ </g>
+ <g
+ id="g914"
+ transform="matrix(0.08572572,0,0,0.08572572,9.9999994,8.4247072)"
+ style="fill:#00ff00">
+ <g
+ id="g856"
+ style="fill:#00ff00">
+ <g
+ id="g854"
+ style="fill:#00ff00">
+ <path
+ inkscape:connector-curvature="0"
+ id="path850"
+ d="m 226.434,249.503 c 0,-6.995 -2.705,-13.403 -7.846,-18.556 L 61.8,74.165 c -5.128,-5.141 -11.554,-7.852 -18.568,-7.852 -7.026,0 -13.452,2.717 -18.556,7.846 l -16.83,16.83 c -5.129,5.135 -7.84,11.549 -7.84,18.538 0,7.026 2.717,13.452 7.846,18.556 L 129.267,249.503 7.84,370.936 C 2.711,376.071 0,382.491 0,389.486 c 0,7.02 2.717,13.439 7.846,18.544 l 16.775,16.774 c 5.116,5.165 11.555,7.895 18.611,7.895 7.044,0 13.47,-2.723 18.556,-7.846 l 156.813,-156.8 c 5.128,-5.14 7.833,-11.549 7.833,-18.55 z"
+ style="fill:#00ff00" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path852"
+ d="m 498.866,384.951 h -323.02 c -7.203,0 -13.611,2.583 -18.581,7.528 -4.896,4.92 -7.484,11.327 -7.484,18.531 v 21.536 c 0,7.252 2.607,13.672 7.491,18.543 4.915,4.927 11.34,7.528 18.574,7.528 h 323.02 c 7.239,0 13.659,-2.607 18.531,-7.497 4.927,-4.908 7.533,-11.334 7.533,-18.58 v -21.537 c 0,-7.209 -2.589,-13.616 -7.54,-18.592 -4.913,-4.877 -11.321,-7.46 -18.524,-7.46 z"
+ style="fill:#00ff00" />
+ </g>
+ </g>
+ <g
+ id="g858"
+ style="fill:#00ff00" />
+ <g
+ id="g860"
+ style="fill:#00ff00" />
+ <g
+ id="g862"
+ style="fill:#00ff00" />
+ <g
+ id="g864"
+ style="fill:#00ff00" />
+ <g
+ id="g866"
+ style="fill:#00ff00" />
+ <g
+ id="g868"
+ style="fill:#00ff00" />
+ <g
+ id="g870"
+ style="fill:#00ff00" />
+ <g
+ id="g872"
+ style="fill:#00ff00" />
+ <g
+ id="g874"
+ style="fill:#00ff00" />
+ <g
+ id="g876"
+ style="fill:#00ff00" />
+ <g
+ id="g878"
+ style="fill:#00ff00" />
+ <g
+ id="g880"
+ style="fill:#00ff00" />
+ <g
+ id="g882"
+ style="fill:#00ff00" />
+ <g
+ id="g884"
+ style="fill:#00ff00" />
+ <g
+ id="g886"
+ style="fill:#00ff00" />
+ </g>
+ </g>
+</svg>
diff --git a/application/resources/multimc/scalable/logo.svg b/application/resources/multimc/scalable/logo.svg
new file mode 100644
index 00000000..8bb0e289
--- /dev/null
+++ b/application/resources/multimc/scalable/logo.svg
@@ -0,0 +1,353 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="68.26667"
+ height="68.26667"
+ id="svg4427"
+ version="1.1"
+ inkscape:version="0.92.1 r"
+ sodipodi:docname="multimc-smooth-biginfinity.svg"
+ inkscape:export-filename="/home/peterix/playground/MultiMC-icons/multimc-smooth-biginfinity.png"
+ inkscape:export-xdpi="180"
+ inkscape:export-ydpi="180">
+ <defs
+ id="defs4429">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient4809">
+ <stop
+ style="stop-color:#98c867;stop-opacity:1"
+ offset="0"
+ id="stop4805" />
+ <stop
+ style="stop-color:#5c9a33;stop-opacity:1"
+ offset="1"
+ id="stop4807" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5668"
+ inkscape:collect="always">
+ <stop
+ id="stop5670"
+ offset="0"
+ style="stop-color:#75b54b;stop-opacity:1;" />
+ <stop
+ id="stop5672"
+ offset="1"
+ style="stop-color:#75b54b;stop-opacity:0.6" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5084"
+ inkscape:collect="always">
+ <stop
+ id="stop5086"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:0.8" />
+ <stop
+ id="stop5088"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0.35" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5668"
+ id="linearGradient5072"
+ x1="6.7342591"
+ y1="28.510933"
+ x2="50.506943"
+ y2="61.773685"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.01532073,-0.00938002)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5084"
+ id="linearGradient5082"
+ x1="14.312115"
+ y1="9.7948904"
+ x2="44.097023"
+ y2="82.973114"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5668"
+ id="linearGradient3281"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.01532073,-0.00938002)"
+ x1="6.7342591"
+ y1="28.510933"
+ x2="50.506943"
+ y2="61.773685" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5668"
+ id="linearGradient3283"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.01532073,-0.00938002)"
+ x1="6.7342591"
+ y1="28.510933"
+ x2="50.506943"
+ y2="61.773685" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5668"
+ id="linearGradient3286"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2671525,0,0,0.89790119,-0.01941371,-0.00842234)"
+ x1="6.7342591"
+ y1="28.510933"
+ x2="50.506943"
+ y2="61.773685" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5084"
+ id="linearGradient3288"
+ gradientUnits="userSpaceOnUse"
+ x1="14.312115"
+ y1="9.7948904"
+ x2="44.097023"
+ y2="82.973114" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5084"
+ id="linearGradient3290"
+ gradientUnits="userSpaceOnUse"
+ x1="14.312115"
+ y1="9.7948904"
+ x2="44.097023"
+ y2="82.973114" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5084"
+ id="linearGradient3293"
+ gradientUnits="userSpaceOnUse"
+ x1="14.312115"
+ y1="9.7948904"
+ x2="44.097023"
+ y2="82.973114"
+ gradientTransform="scale(1.2671525,0.89790119)" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5580">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.0627451"
+ offset="0"
+ id="stop5576" />
+ <stop
+ style="stop-color:#322217;stop-opacity:0.58823532"
+ offset="1"
+ id="stop5578" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3999"
+ inkscape:collect="always">
+ <stop
+ id="stop3995"
+ offset="0"
+ style="stop-color:#a3704b;stop-opacity:1" />
+ <stop
+ id="stop3997"
+ offset="1"
+ style="stop-color:#6a4a33;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2727"
+ inkscape:collect="always">
+ <stop
+ id="stop2723"
+ offset="0"
+ style="stop-color:#966c4a;stop-opacity:1" />
+ <stop
+ id="stop2725"
+ offset="1"
+ style="stop-color:#593d29;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2727"
+ id="linearGradient2050"
+ gradientUnits="userSpaceOnUse"
+ x1="36.546478"
+ y1="33.80484"
+ x2="86.415741"
+ y2="97.065842" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3999"
+ id="radialGradient2052"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-9.105292e-4,-0.00104444)"
+ cx="34.133331"
+ cy="34.133335"
+ fx="34.133331"
+ fy="34.133335"
+ r="29.866665" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5580"
+ id="linearGradient2140"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.0010513,-9.083059e-4)"
+ x1="29.866674"
+ y1="29.867579"
+ x2="38.400005"
+ y2="38.400913" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5084"
+ id="linearGradient4790"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2671525,0,0,0.89790119,-0.82864077,-1.0012743)"
+ x1="14.312115"
+ y1="9.7948904"
+ x2="44.097023"
+ y2="82.973114" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4809"
+ id="radialGradient4803"
+ cx="-42.66758"
+ cy="-34.134373"
+ fx="-42.66758"
+ fy="-34.134373"
+ r="34.132812"
+ gradientTransform="matrix(1.7500268,0.1250019,-0.01781176,0.24936465,95.393964,18.110151)"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="3.6203867"
+ inkscape:cx="52.171166"
+ inkscape:cy="11.292073"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:document-units="px"
+ inkscape:grid-bbox="true"
+ inkscape:window-width="1368"
+ inkscape:window-height="905"
+ inkscape:window-x="2452"
+ inkscape:window-y="723"
+ inkscape:window-maximized="0"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="false"
+ inkscape:snap-bbox-edge-midpoints="false"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-midpoints="false"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:snap-midpoints="false"
+ inkscape:snap-intersection-paths="true"
+ inkscape:object-paths="true"
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-text-baseline="true"
+ inkscape:snap-center="true">
+ <inkscape:grid
+ type="xygrid"
+ id="grid4446"
+ empspacing="16"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ spacingx="4.2666667"
+ spacingy="4.2666667"
+ originx="0"
+ originy="0" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata4432">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <g
+ id="g2048"
+ transform="translate(9.113e-4,0.00104183)">
+ <rect
+ rx="8.5333338"
+ ry="8.5333338"
+ style="fill:url(#linearGradient2050);fill-opacity:1;stroke:none;stroke-width:17.06666756"
+ id="rect2026"
+ width="68.26667"
+ height="68.26667"
+ x="-1.3322676e-15"
+ y="3.0270508e-06" />
+ <rect
+ rx="4.2666626"
+ y="4.2656283"
+ x="4.2657552"
+ height="59.733334"
+ width="59.73333"
+ id="rect2028"
+ style="fill:url(#radialGradient2052);fill-opacity:1;stroke:none;stroke-width:14.93333435"
+ ry="4.2666669" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4811"
+ d="m 4.2669272,4.2645856 -9.11e-4,8.5333334 h 4.267577 v 4.267579 h 8.5332038 v 4.265625 h 4.265625 V 8.5322946 H 25.6 v 8.5332034 h 4.265625 v -4.267579 h 4.267578 v 8.533204 h 4.265625 v -4.265625 h 4.267578 v 4.265625 h 4.267579 v -4.265625 h 4.265624 v -4.267579 h 4.267579 v 4.267579 h 8.533203 l -1.3e-4,-12.8009124 z"
+ style="opacity:0.6;fill:#593d29;fill-opacity:1;stroke:none;stroke-width:17.06666756"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccc" />
+ <path
+ style="fill:url(#radialGradient4803);fill-opacity:1;stroke:none;stroke-width:17.06666756"
+ d="m 8.5329442,-0.0018207 c -4.7274675,0 -8.5332035,3.805736 -8.5332035,8.533203 v 4.2675787 h 4.265625 V 8.5313823 c 0,-0.521698 0.105433,-1.01339 0.27539,-1.47461 -0.169616,0.460814 -0.27539,0.953462 -0.27539,1.47461 h 4.2675785 v 4.2675787 h 4.2656248 4.267578 v 4.265625 h 4.265625 V 12.798961 8.5313823 4.2657573 h 4.267578 v 4.265625 4.2675787 h 4.265625 V 8.5313823 h 4.267578 v 4.2675787 4.265625 h 4.265625 v -4.265625 h 4.267578 v 4.265625 h 4.267579 v -4.265625 h 4.265624 V 8.5313823 h 4.267579 v 4.2675787 h 4.265625 4.267578 V 8.5313823 h 4.265625 c 0,-4.727467 -3.805737,-8.533203 -8.533203,-8.533203 z m -3.019531,5.513671 c -0.318089,0.317888 -0.570428,0.695824 -0.7753915,1.101563 0.2048795,-0.405231 0.4576385,-0.784012 0.7753915,-1.101563 z"
+ id="path4794"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:1;fill:url(#linearGradient2140);fill-opacity:1;stroke:none;stroke-width:17.06666756"
+ d="m 8.5322887,-9.083059e-4 c -4.72747,0 -8.5332,3.8057359059 -8.5332,8.5332029059 V 59.731515 c 0,4.727467 3.80573,8.535156 8.5332,8.535156 H 59.731502 c 4.72747,0 8.5332,-3.807689 8.5332,-8.535156 V 8.5322946 c 0,-4.727467 -3.80573,-8.5332029059 -8.5332,-8.5332029059 z m 0,4.2675779059 H 59.731502 c 2.36373,0 4.26758,1.901892 4.26758,4.265625 V 59.731515 c 0,2.363733 -1.90385,4.267578 -4.26758,4.267578 H 8.5322887 c -2.36373,0 -4.26758,-1.903845 -4.26758,-4.267578 V 8.5322946 c 0,-2.363733 1.90385,-4.265625 4.26758,-4.265625 z"
+ id="path2046"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g1092">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4786"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:76.18933868px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient4790);fill-opacity:1;stroke:none;stroke-width:1.06666672;opacity:0.5"
+ d="m 38.886673,44.940882 c -0.974277,-0.801673 -2.231353,-2.137814 -3.771231,-4.008427 -2.105641,2.672298 -4.085536,4.598569 -5.939688,5.778816 -2.325625,1.425227 -5.295467,2.137836 -8.909534,2.137828 -4.242656,8e-6 -7.762467,-1.124578 -10.5594458,-3.37376 C 6.7526311,43.114834 5.275567,39.986037 5.2755773,36.088937 5.275567,32.347763 6.7526311,29.207831 9.7067742,26.669132 12.346618,24.419991 15.897857,23.295407 20.360501,23.295373 c 2.294138,3.4e-5 4.289747,0.334069 5.986829,1.002107 1.979863,0.73491 3.645488,1.737016 4.996881,3.00632 1.257039,1.135751 2.514115,2.471891 3.771231,4.008428 2.105563,-2.672257 4.085457,-4.598527 5.939689,-5.778816 2.325544,-1.425186 5.295385,-2.137794 8.909533,-2.137828 4.242577,3.4e-5 7.762388,1.124618 10.559447,3.37376 2.954063,2.360546 4.431127,5.489343 4.431197,9.386401 -7e-5,3.741216 -1.477134,6.881147 -4.431197,9.419806 -2.639925,2.24918 -6.191163,3.373767 -10.653727,3.373758 -2.294219,9e-6 -4.289826,-0.334026 -5.98683,-1.002106 -1.697101,-0.601255 -3.362726,-1.603361 -4.996881,-3.006321 M 19.747676,44.473233 c 5.185412,1.1e-5 9.333763,-2.672271 12.445062,-8.016856 -3.991253,-5.834464 -8.139602,-8.751705 -12.445062,-8.751733 -3.142715,2.8e-5 -5.515446,0.801713 -7.118198,2.405057 -1.728498,1.71474 -2.592737,3.707818 -2.592722,5.979236 -1.5e-5,2.494152 0.864224,4.509499 2.592722,6.046046 1.759887,1.558846 4.132618,2.338261 7.118198,2.33825 M 50.483209,27.77145 c -4.682663,2.9e-5 -8.831013,2.672312 -12.445062,8.016856 3.959745,5.834503 8.108095,8.751746 12.445062,8.751733 3.142633,1.3e-5 5.515364,-0.801671 7.118198,-2.405056 1.728416,-1.714701 2.592656,-3.707778 2.592722,-5.979238 -6.6e-5,-2.49411 -0.864306,-4.509456 -2.592722,-6.046044 -1.759968,-1.558805 -4.132699,-2.338222 -7.118198,-2.338251" />
+ <path
+ d="m 39.715314,45.942156 c -0.974277,-0.801673 -2.231353,-2.137814 -3.771231,-4.008427 -2.105641,2.672298 -4.085536,4.598569 -5.939688,5.778816 -2.325625,1.425227 -5.295467,2.137836 -8.909534,2.137828 -4.242656,8e-6 -7.762467,-1.124578 -10.559446,-3.37376 -2.9541431,-2.360505 -4.4312072,-5.489302 -4.4311969,-9.386402 -1.03e-5,-3.741174 1.4770538,-6.881106 4.4311969,-9.419805 2.639844,-2.249141 6.191083,-3.373725 10.653727,-3.373759 2.294138,3.4e-5 4.289747,0.334069 5.986829,1.002107 1.979863,0.73491 3.645488,1.737016 4.996881,3.00632 1.257039,1.135751 2.514115,2.471891 3.771231,4.008428 2.105563,-2.672257 4.085457,-4.598527 5.939689,-5.778816 2.325544,-1.425186 5.295385,-2.137794 8.909533,-2.137828 4.242577,3.4e-5 7.762388,1.124618 10.559447,3.37376 2.954063,2.360546 4.431127,5.489343 4.431197,9.386401 -7e-5,3.741216 -1.477134,6.881147 -4.431197,9.419806 -2.639925,2.24918 -6.191163,3.373767 -10.653727,3.373758 -2.294219,9e-6 -4.289826,-0.334026 -5.98683,-1.002106 -1.697101,-0.601255 -3.362726,-1.603361 -4.996881,-3.006321 M 20.576317,45.474507 c 5.185412,1.1e-5 9.333763,-2.672271 12.445062,-8.016856 -3.991253,-5.834464 -8.139602,-8.751705 -12.445062,-8.751733 -3.142715,2.8e-5 -5.515446,0.801713 -7.118198,2.405057 -1.728498,1.71474 -2.592737,3.707818 -2.592722,5.979236 -1.5e-5,2.494152 0.864224,4.509499 2.592722,6.046046 1.759887,1.558846 4.132618,2.338261 7.118198,2.33825 M 51.31185,28.772724 c -4.682663,2.9e-5 -8.831013,2.672312 -12.445062,8.016856 3.959745,5.834503 8.108095,8.751746 12.445062,8.751733 3.142633,1.3e-5 5.515364,-0.801671 7.118198,-2.405056 1.728416,-1.714701 2.592656,-3.707778 2.592722,-5.979238 -6.6e-5,-2.49411 -0.864306,-4.509456 -2.592722,-6.046044 C 56.67008,29.55217 54.297349,28.772753 51.31185,28.772724"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:76.18933868px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient3293);fill-opacity:1;stroke:none;stroke-width:1.06666672;opacity:0.5"
+ id="path3279"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 37.904564,42.951873 c -0.974278,-0.801672 -2.231352,-2.137814 -3.771231,-4.008428 -2.105642,2.672298 -4.085537,4.598568 -5.939688,5.778817 -2.325625,1.425227 -5.295466,2.137836 -8.909534,2.137828 -4.242656,8e-6 -7.762467,-1.124577 -10.5594464,-3.37376 -2.9541428,-2.360505 -4.4312068,-5.489302 -4.4311963,-9.386401 -1.05e-5,-3.741175 1.4770535,-6.881107 4.4311963,-9.419805 2.6398444,-2.249142 6.1910824,-3.373727 10.6537284,-3.37376 2.294137,3.3e-5 4.289745,0.334068 5.986829,1.002107 1.979863,0.734909 3.645487,1.737016 4.99688,3.00632 1.257039,1.13575 2.514116,2.471891 3.771231,4.008428 2.105562,-2.672257 4.085456,-4.598528 5.939689,-5.778817 2.325544,-1.425185 5.295387,-2.137795 8.909534,-2.137828 4.242576,3.3e-5 7.762387,1.12462 10.559446,3.373761 2.954062,2.360545 4.431127,5.489343 4.431197,9.386401 -7e-5,3.741216 -1.477135,6.881148 -4.431197,9.419805 -2.639924,2.249182 -6.191164,3.373767 -10.653728,3.37376 -2.294217,7e-6 -4.289826,-0.334028 -5.986828,-1.002107 -1.697101,-0.601254 -3.362727,-1.603361 -4.996882,-3.006321 m -19.138997,-0.46765 c 5.185412,1.3e-5 9.333762,-2.67227 12.445062,-8.016856 -3.991252,-5.834462 -8.139602,-8.751704 -12.445062,-8.751733 -3.142714,2.9e-5 -5.515444,0.801714 -7.118198,2.405056 -1.7284972,1.714743 -2.5927368,3.707819 -2.5927216,5.979239 -1.52e-5,2.49415 0.8642244,4.509496 2.5927216,6.046045 1.759888,1.558845 4.132618,2.338262 7.118198,2.338249 M 49.5011,25.782442 c -4.682663,2.8e-5 -8.831014,2.672311 -12.445063,8.016855 3.959745,5.834504 8.108096,8.751745 12.445063,8.751733 3.142634,1.2e-5 5.515365,-0.801673 7.118198,-2.405056 1.728417,-1.7147 2.592657,-3.707778 2.592721,-5.979238 -6.4e-5,-2.49411 -0.864304,-4.509456 -2.592721,-6.046046 C 54.85933,26.561886 52.486599,25.78247 49.5011,25.782442"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:76.18933868px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient3286);fill-opacity:1;stroke:none;stroke-width:1.06666672"
+ id="path3272"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccscsccccccccccccccccccccscscccccsccscccccc"
+ inkscape:connector-curvature="0"
+ id="text5100"
+ d="m 19.4,21.166667 c -4.462644,3.3e-5 -8.026822,1.150858 -10.6666667,3.4 -2.9541428,2.538698 -4.4333436,5.658825 -4.4333333,9.4 -1.03e-5,3.897098 1.4791905,7.039495 4.4333333,9.4 -1.622701,-2.044271 -2.433341,-4.51168 -2.4333333,-7.4 -1.03e-5,-3.741175 1.4791905,-6.861302 4.433333,-9.4 2.639845,-2.249142 6.204023,-3.399967 10.666667,-3.4 2.294138,3.3e-5 4.302916,0.365295 6,1.033333 1.979862,0.73491 3.615274,1.730695 4.966667,3 0.06836,0.06177 0.131637,0.137049 0.2,0.2 -0.731813,-0.797005 -1.468213,-1.538822 -2.2,-2.2 -1.351393,-1.269305 -2.986805,-2.26509 -4.966667,-3 -1.697084,-0.668038 -3.705862,-1.0333 -6,-1.033333 z m 29.6,0.1 c -3.614148,3.3e-5 -6.574457,0.74148 -8.9,2.166666 -1.818222,1.157367 -3.923451,3.291388 -5.983333,5.883334 0.618278,0.658774 1.248369,1.377605 1.866666,2.133333 2.105562,-2.672257 4.262434,-4.836378 6.116667,-6.016667 2.325543,-1.425186 5.285852,-2.166633 8.9,-2.166666 4.242576,3.3e-5 7.769607,1.150858 10.566667,3.4 -0.570388,-0.722129 -1.227721,-1.382884 -2,-2 C 56.769607,22.417525 53.242576,21.2667 49,21.266667 Z m 8.866667,8.1 c 0.9092,1.305235 1.366619,2.857751 1.366666,4.666666 -6.5e-5,2.271461 -0.871584,4.285301 -2.6,6 -1.602834,1.603384 -3.957366,2.400012 -7.1,2.4 -2.653707,8e-6 -5.320858,-1.032242 -7.833333,-3.216666 3.136636,3.509305 6.469807,5.216676 9.833333,5.216666 3.142634,1.2e-5 5.497166,-0.796616 7.1,-2.4 1.728416,-1.714699 2.599935,-3.728539 2.6,-6 -6.5e-5,-2.49411 -0.871584,-4.496744 -2.6,-6.033333 -0.24943,-0.220921 -0.49262,-0.443723 -0.766666,-0.633333 z m -26.633334,4.966666 c -3.1113,5.344585 -7.247921,8.033345 -12.433333,8.033334 -2.58055,1e-5 -4.543473,-0.352086 -6.208333,-1.516667 0.348871,0.50642 0.590094,0.752276 1.075,1.183333 1.759888,1.558846 4.147753,2.333345 7.133333,2.333334 5.185412,1.1e-5 9.322033,-2.688749 12.433333,-8.033334 z m 4.933334,6.5 c -0.04103,0.05207 -0.09239,0.08182 -0.133334,0.133334 0.687326,0.744419 1.306949,1.359747 1.833334,1.8 -0.529404,-0.580895 -1.078447,-1.178283 -1.7,-1.933334 z"
+ style="font-style:normal;font-weight:normal;font-size:76.18933868px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;opacity:0.3;fill:#ccff00;fill-opacity:1;stroke:none;stroke-width:1.06666672" />
+ <path
+ sodipodi:nodetypes="ccsccscccccccccccccccccccscscccccsccsccccccc"
+ id="text5058-0"
+ d="m 19.730474,21.54714 c -4.462645,3.3e-5 -8.026823,1.150859 -10.6666669,3.4 -2.9541429,2.538699 -4.433344,5.658826 -4.4333333,9.4 -1.07e-5,3.897099 1.4791904,7.039495 4.4333333,9.4 0.042837,0.03444 0.090155,0.06608 0.1333334,0.1 -2.2392086,-2.228193 -3.3666752,-5.040417 -3.3666667,-8.433333 -1.07e-5,-3.741174 1.4791904,-6.861301 4.4333332,-9.4 2.639844,-2.249141 6.204022,-3.399967 10.666667,-3.4 2.294137,3.3e-5 4.302916,0.365295 6,1.033333 1.870874,0.694455 3.42364,1.628367 4.733333,2.8 -0.314265,-0.308986 -0.652406,-0.582729 -0.966667,-0.866666 -1.351393,-1.269305 -2.986804,-2.265091 -4.966666,-3 -1.697084,-0.668039 -3.705863,-1.033301 -6,-1.033334 z m 29.6,0.1 c -3.614149,3.3e-5 -6.574457,0.741481 -8.9,2.166667 -1.813279,1.154221 -3.963039,3.235656 -6.016667,5.816667 0.355649,0.402628 0.711011,0.798625 1.066667,1.233333 2.105561,-2.672257 4.295767,-4.803044 6.15,-5.983333 2.325543,-1.425187 5.285851,-2.166634 8.9,-2.166667 4.22442,3.3e-5 7.742084,1.136734 10.533333,3.366667 -0.36096,-0.367566 -0.745726,-0.696967 -1.166667,-1.033334 -2.797059,-2.249141 -6.32409,-3.399967 -10.566666,-3.4 z m 8.233333,7.333334 c 1.323326,1.449243 1.999942,3.250987 2,5.433333 -6.5e-5,2.27146 -0.871584,4.2853 -2.6,6 -1.602834,1.603383 -3.957366,2.400012 -7.1,2.4 -2.406328,6e-6 -4.776468,-0.90386 -7.066667,-2.7 2.669147,2.483838 5.436929,3.766674 8.266667,3.766667 3.142634,1.1e-5 5.497166,-0.796617 7.1,-2.4 1.728416,-1.7147 2.599935,-3.72854 2.6,-6 -6.5e-5,-2.49411 -0.871584,-4.496745 -2.6,-6.033334 -0.185641,-0.164422 -0.400724,-0.319587 -0.6,-0.466666 z m -26,5.733333 c -3.1113,5.344584 -7.247921,8.033345 -12.433333,8.033333 -2.612382,1.1e-5 -4.759372,-0.60651 -6.433334,-1.8 0.166027,0.176488 0.313947,0.367942 0.5,0.533334 1.759888,1.558845 4.147754,2.333345 7.133334,2.333333 5.185412,1.2e-5 9.322033,-2.688749 12.433333,-8.033333 z m 4.133333,5.566667 c -0.04657,0.05909 -0.08689,0.108298 -0.133333,0.166666 1.038571,1.18897 1.9748,2.169945 2.7,2.766667 0.06249,0.05364 0.137426,0.08086 0.2,0.133333 -0.792178,-0.781249 -1.706288,-1.778539 -2.766667,-3.066666 z"
+ style="font-style:normal;font-weight:normal;font-size:76.18933868px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;opacity:0.6;fill:#ccff00;fill-opacity:1;stroke:none;stroke-width:1.06666672"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+</svg>
diff --git a/application/resources/multimc/scalable/multimc.svg b/application/resources/multimc/scalable/multimc.svg
index 178509ac..8bb0e289 100644
--- a/application/resources/multimc/scalable/multimc.svg
+++ b/application/resources/multimc/scalable/multimc.svg
@@ -10,18 +10,30 @@
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="64px"
- height="64px"
+ width="68.26667"
+ height="68.26667"
id="svg4427"
version="1.1"
- inkscape:version="0.48.4 r9939"
- sodipodi:docname="multimc.svg"
- inkscape:export-filename="/home/peterix/projects/MultiMC4/src/resources/insticons/infinity128.png"
+ inkscape:version="0.92.1 r"
+ sodipodi:docname="multimc-smooth-biginfinity.svg"
+ inkscape:export-filename="/home/peterix/playground/MultiMC-icons/multimc-smooth-biginfinity.png"
inkscape:export-xdpi="180"
inkscape:export-ydpi="180">
<defs
id="defs4429">
<linearGradient
+ inkscape:collect="always"
+ id="linearGradient4809">
+ <stop
+ style="stop-color:#98c867;stop-opacity:1"
+ offset="0"
+ id="stop4805" />
+ <stop
+ style="stop-color:#5c9a33;stop-opacity:1"
+ offset="1"
+ id="stop4807" />
+ </linearGradient>
+ <linearGradient
id="linearGradient5668"
inkscape:collect="always">
<stop
@@ -89,7 +101,7 @@
xlink:href="#linearGradient5668"
id="linearGradient3286"
gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.1879555,0,0,0.84178237,-0.01820035,-0.00789594)"
+ gradientTransform="matrix(1.2671525,0,0,0.89790119,-0.01941371,-0.00842234)"
x1="6.7342591"
y1="28.510933"
x2="50.506943"
@@ -121,7 +133,94 @@
y1="9.7948904"
x2="44.097023"
y2="82.973114"
- gradientTransform="scale(1.1879555,0.84178237)" />
+ gradientTransform="scale(1.2671525,0.89790119)" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5580">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.0627451"
+ offset="0"
+ id="stop5576" />
+ <stop
+ style="stop-color:#322217;stop-opacity:0.58823532"
+ offset="1"
+ id="stop5578" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3999"
+ inkscape:collect="always">
+ <stop
+ id="stop3995"
+ offset="0"
+ style="stop-color:#a3704b;stop-opacity:1" />
+ <stop
+ id="stop3997"
+ offset="1"
+ style="stop-color:#6a4a33;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2727"
+ inkscape:collect="always">
+ <stop
+ id="stop2723"
+ offset="0"
+ style="stop-color:#966c4a;stop-opacity:1" />
+ <stop
+ id="stop2725"
+ offset="1"
+ style="stop-color:#593d29;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2727"
+ id="linearGradient2050"
+ gradientUnits="userSpaceOnUse"
+ x1="36.546478"
+ y1="33.80484"
+ x2="86.415741"
+ y2="97.065842" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3999"
+ id="radialGradient2052"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-9.105292e-4,-0.00104444)"
+ cx="34.133331"
+ cy="34.133335"
+ fx="34.133331"
+ fy="34.133335"
+ r="29.866665" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5580"
+ id="linearGradient2140"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.0010513,-9.083059e-4)"
+ x1="29.866674"
+ y1="29.867579"
+ x2="38.400005"
+ y2="38.400913" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5084"
+ id="linearGradient4790"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2671525,0,0,0.89790119,-0.82864077,-1.0012743)"
+ x1="14.312115"
+ y1="9.7948904"
+ x2="44.097023"
+ y2="82.973114" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4809"
+ id="radialGradient4803"
+ cx="-42.66758"
+ cy="-34.134373"
+ fx="-42.66758"
+ fy="-34.134373"
+ r="34.132812"
+ gradientTransform="matrix(1.7500268,0.1250019,-0.01781176,0.24936465,95.393964,18.110151)"
+ gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
@@ -130,18 +229,30 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="6"
- inkscape:cx="10.09561"
- inkscape:cy="35.232628"
+ inkscape:zoom="3.6203867"
+ inkscape:cx="52.171166"
+ inkscape:cy="11.292073"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:document-units="px"
inkscape:grid-bbox="true"
- inkscape:window-width="1607"
- inkscape:window-height="1030"
- inkscape:window-x="1676"
- inkscape:window-y="-3"
- inkscape:window-maximized="1">
+ inkscape:window-width="1368"
+ inkscape:window-height="905"
+ inkscape:window-x="2452"
+ inkscape:window-y="723"
+ inkscape:window-maximized="0"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="false"
+ inkscape:snap-bbox-edge-midpoints="false"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-midpoints="false"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:snap-midpoints="false"
+ inkscape:snap-intersection-paths="true"
+ inkscape:object-paths="true"
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-text-baseline="true"
+ inkscape:snap-center="true">
<inkscape:grid
type="xygrid"
id="grid4446"
@@ -149,8 +260,10 @@
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
- spacingx="4px"
- spacingy="4px" />
+ spacingx="4.2666667"
+ spacingy="4.2666667"
+ originx="0"
+ originy="0" />
</sodipodi:namedview>
<metadata
id="metadata4432">
@@ -168,1826 +281,73 @@
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
- <rect
- style="opacity:0.34999999999999998;fill:#552200;fill-opacity:1;stroke:none"
- id="rect5674"
- width="64.125"
- height="64"
- x="-0.125"
- y="0.1249999" />
- <rect
- style="fill:#74b44a;fill-opacity:1;stroke:none"
- id="rect4448"
- width="4"
- height="4"
- x="0"
- y="0" />
- <rect
- y="0"
- x="4"
- height="4"
- width="4"
- id="rect4450"
- style="fill:#76b64c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#73b349;fill-opacity:1;stroke:none"
- id="rect4452"
- width="4"
- height="4"
- x="8"
- y="0" />
- <rect
- y="0"
- x="12"
- height="4"
- width="4"
- id="rect4454"
- style="fill:#66a63c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#66a63c;fill-opacity:1;stroke:none"
- id="rect4456"
- width="4"
- height="4"
- x="16"
- y="0" />
- <rect
- y="0"
- x="20"
- height="4"
- width="4"
- id="rect4458"
- style="fill:#6faf45;fill-opacity:1;stroke:none" />
- <rect
- y="4"
- x="0"
- height="4"
- width="4"
- id="rect4460"
- style="fill:#75b54b;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#6cac42;fill-opacity:1;stroke:none"
- id="rect4462"
- width="4"
- height="4"
- x="4"
- y="4" />
- <rect
- y="4"
- x="8"
- height="4"
- width="4"
- id="rect4464"
- style="fill:#8ab95a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#81b051;fill-opacity:1;stroke:none"
- id="rect4466"
- width="4"
- height="4"
- x="12"
- y="4" />
- <rect
- y="4"
- x="16"
- height="4"
- width="4"
- id="rect4468"
- style="fill:#83b253;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4470"
- width="4"
- height="4"
- x="20"
- y="4" />
- <rect
- y="0"
- x="24"
- height="4"
- width="4"
- id="rect4472"
- style="fill:#5f9f35;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#6cac42;fill-opacity:1;stroke:none"
- id="rect4474"
- width="4"
- height="4"
- x="28"
- y="0" />
- <rect
- y="0"
- x="32"
- height="4"
- width="4"
- id="rect4476"
- style="fill:#7ebe54;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#76b64c;fill-opacity:1;stroke:none"
- id="rect4478"
- width="4"
- height="4"
- x="36"
- y="0" />
- <rect
- y="0"
- x="40"
- height="4"
- width="4"
- id="rect4480"
- style="fill:#6aaa40;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#67a73d;fill-opacity:1;stroke:none"
- id="rect4482"
- width="4"
- height="4"
- x="44"
- y="0" />
- <rect
- style="fill:#68a83e;fill-opacity:1;stroke:none"
- id="rect4484"
- width="4"
- height="4"
- x="24"
- y="4" />
- <rect
- y="4"
- x="28"
- height="4"
- width="4"
- id="rect4486"
- style="fill:#62a238;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#5f9f35;fill-opacity:1;stroke:none"
- id="rect4488"
- width="4"
- height="4"
- x="32"
- y="4" />
- <rect
- y="4"
- x="36"
- height="4"
- width="4"
- id="rect4490"
- style="fill:#93c263;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#90bf60;fill-opacity:1;stroke:none"
- id="rect4492"
- width="4"
- height="4"
- x="40"
- y="4" />
- <rect
- y="4"
- x="44"
- height="4"
- width="4"
- id="rect4494"
- style="fill:#73b349;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#69a93f;fill-opacity:1;stroke:none"
- id="rect4496"
- width="4"
- height="4"
- x="48"
- y="0" />
- <rect
- y="0"
- x="52"
- height="4"
- width="4"
- id="rect4498"
- style="fill:#61a137;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#509026;fill-opacity:1;stroke:none"
- id="rect4500"
- width="4"
- height="4"
- x="56"
- y="0" />
- <rect
- y="0"
- x="60"
- height="4"
- width="4"
- id="rect4502"
- style="fill:#6dad43;fill-opacity:1;stroke:none" />
- <rect
- y="4"
- x="48"
- height="4"
- width="4"
- id="rect4508"
- style="fill:#61a137;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#6cac42;fill-opacity:1;stroke:none"
- id="rect4510"
- width="4"
- height="4"
- x="52"
- y="4" />
- <rect
- y="4"
- x="56"
- height="4"
- width="4"
- id="rect4512"
- style="fill:#67a73d;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#6bab41;fill-opacity:1;stroke:none"
- id="rect4514"
- width="4"
- height="4"
- x="60"
- y="4" />
- <rect
- y="8"
- x="0"
- height="4"
- width="4"
- id="rect4520"
- style="fill:#8dbc5d;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4522"
- width="4"
- height="4"
- x="4"
- y="8" />
- <rect
- y="8"
- x="8"
- height="4"
- width="4"
- id="rect4524"
- style="fill:#9ccb6c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#64a43a;fill-opacity:1;stroke:none"
- id="rect4526"
- width="4"
- height="4"
- x="12"
- y="8" />
- <rect
- y="8"
- x="16"
- height="4"
- width="4"
- id="rect4528"
- style="fill:#69a93f;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4530"
- width="4"
- height="4"
- x="20"
- y="8" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4532"
- width="4"
- height="4"
- x="0"
- y="12" />
- <rect
- y="12"
- x="4"
- height="4"
- width="4"
- id="rect4534"
- style="fill:#6c6c6c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4536"
- width="4"
- height="4"
- x="8"
- y="12" />
- <rect
- y="12"
- x="12"
- height="4"
- width="4"
- id="rect4538"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#71b147;fill-opacity:1;stroke:none"
- id="rect4540"
- width="4"
- height="4"
- x="16"
- y="12" />
- <rect
- y="12"
- x="20"
- height="4"
- width="4"
- id="rect4542"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#70b046;fill-opacity:1;stroke:none"
- id="rect4544"
- width="4"
- height="4"
- x="24"
- y="8" />
- <rect
- y="8"
- x="28"
- height="4"
- width="4"
- id="rect4546"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#74b44a;fill-opacity:1;stroke:none"
- id="rect4548"
- width="4"
- height="4"
- x="32"
- y="8" />
- <rect
- y="8"
- x="36"
- height="4"
- width="4"
- id="rect4550"
- style="fill:#7fbf55;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#92c162;fill-opacity:1;stroke:none"
- id="rect4552"
- width="4"
- height="4"
- x="40"
- y="8" />
- <rect
- y="8"
- x="44"
- height="4"
- width="4"
- id="rect4554"
- style="fill:#97c667;fill-opacity:1;stroke:none" />
- <rect
- y="12"
- x="24"
- height="4"
- width="4"
- id="rect4556"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4558"
- width="4"
- height="4"
- x="28"
- y="12" />
- <rect
- y="12"
- x="32"
- height="4"
- width="4"
- id="rect4560"
- style="fill:#5f9f35;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4562"
- width="4"
- height="4"
- x="36"
- y="12" />
- <rect
- y="12"
- x="40"
- height="4"
- width="4"
- id="rect4564"
- style="fill:#6dad43;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4566"
- width="4"
- height="4"
- x="44"
- y="12" />
- <rect
- y="8"
- x="48"
- height="4"
- width="4"
- id="rect4568"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#57972d;fill-opacity:1;stroke:none"
- id="rect4570"
- width="4"
- height="4"
- x="52"
- y="8" />
- <rect
- y="8"
- x="56"
- height="4"
- width="4"
- id="rect4572"
- style="fill:#60a036;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4574"
- width="4"
- height="4"
- x="60"
- y="8" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4576"
- width="4"
- height="4"
- x="48"
- y="12" />
- <rect
- y="12"
- x="52"
- height="4"
- width="4"
- id="rect4578"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4580"
- width="4"
- height="4"
- x="56"
- y="12" />
- <rect
- y="12"
- x="60"
- height="4"
- width="4"
- id="rect4582"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- y="16"
- x="0"
- height="4"
- width="4"
- id="rect4584"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4586"
- width="4"
- height="4"
- x="4"
- y="16" />
- <rect
- y="16"
- x="8"
- height="4"
- width="4"
- id="rect4588"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#b9855c;fill-opacity:1;stroke:none"
- id="rect4590"
- width="4"
- height="4"
- x="12"
- y="16" />
- <rect
- y="16"
- x="16"
- height="4"
- width="4"
- id="rect4592"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4594"
- width="4"
- height="4"
- x="20"
- y="16" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4596"
- width="4"
- height="4"
- x="0"
- y="20" />
- <rect
- y="20"
- x="4"
- height="4"
- width="4"
- id="rect4598"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4600"
- width="4"
- height="4"
- x="8"
- y="20" />
- <rect
- y="20"
- x="12"
- height="4"
- width="4"
- id="rect4602"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4604"
- width="4"
- height="4"
- x="16"
- y="20" />
- <rect
- y="20"
- x="20"
- height="4"
- width="4"
- id="rect4606"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4608"
- width="4"
- height="4"
- x="24"
- y="16" />
- <rect
- y="16"
- x="28"
- height="4"
- width="4"
- id="rect4610"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4612"
- width="4"
- height="4"
- x="32"
- y="16" />
- <rect
- y="16"
- x="36"
- height="4"
- width="4"
- id="rect4614"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4616"
- width="4"
- height="4"
- x="40"
- y="16" />
- <rect
- y="16"
- x="44"
- height="4"
- width="4"
- id="rect4618"
- style="fill:#6c6c6c;fill-opacity:1;stroke:none" />
- <rect
- y="20"
- x="24"
- height="4"
- width="4"
- id="rect4620"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4622"
- width="4"
- height="4"
- x="28"
- y="20" />
- <rect
- y="20"
- x="32"
- height="4"
- width="4"
- id="rect4624"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4626"
- width="4"
- height="4"
- x="36"
- y="20" />
- <rect
- y="20"
- x="40"
- height="4"
- width="4"
- id="rect4628"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4630"
- width="4"
- height="4"
- x="44"
- y="20" />
- <rect
- y="16"
- x="48"
- height="4"
- width="4"
- id="rect4632"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4634"
- width="4"
- height="4"
- x="52"
- y="16" />
- <rect
- y="16"
- x="56"
- height="4"
- width="4"
- id="rect4636"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4638"
- width="4"
- height="4"
- x="60"
- y="16" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4640"
- width="4"
- height="4"
- x="48"
- y="20" />
- <rect
- y="20"
- x="52"
- height="4"
- width="4"
- id="rect4642"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4644"
- width="4"
- height="4"
- x="56"
- y="20" />
- <rect
- y="20"
- x="60"
- height="4"
- width="4"
- id="rect4646"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#b9855c;fill-opacity:1;stroke:none"
- id="rect4648"
- width="4"
- height="4"
- x="0"
- y="24" />
- <rect
- y="24"
- x="4"
- height="4"
- width="4"
- id="rect4650"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4652"
- width="4"
- height="4"
- x="8"
- y="24" />
- <rect
- y="24"
- x="12"
- height="4"
- width="4"
- id="rect4654"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#878787;fill-opacity:1;stroke:none"
- id="rect4656"
- width="4"
- height="4"
- x="16"
- y="24" />
- <rect
- y="24"
- x="20"
- height="4"
- width="4"
- id="rect4658"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- y="28"
- x="0"
- height="4"
- width="4"
- id="rect4660"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4662"
- width="4"
- height="4"
- x="4"
- y="28" />
- <rect
- y="28"
- x="8"
- height="4"
- width="4"
- id="rect4664"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#b9855c;fill-opacity:1;stroke:none"
- id="rect4666"
- width="4"
- height="4"
- x="12"
- y="28" />
- <rect
- y="28"
- x="16"
- height="4"
- width="4"
- id="rect4668"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4670"
- width="4"
- height="4"
- x="20"
- y="28" />
- <rect
- y="24"
- x="24"
- height="4"
- width="4"
- id="rect4672"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#b9855c;fill-opacity:1;stroke:none"
- id="rect4674"
- width="4"
- height="4"
- x="28"
- y="24" />
- <rect
- y="24"
- x="32"
- height="4"
- width="4"
- id="rect4676"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4678"
- width="4"
- height="4"
- x="36"
- y="24" />
- <rect
- y="24"
- x="40"
- height="4"
- width="4"
- id="rect4680"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#b9855c;fill-opacity:1;stroke:none"
- id="rect4682"
- width="4"
- height="4"
- x="44"
- y="24" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4684"
- width="4"
- height="4"
- x="24"
- y="28" />
- <rect
- y="28"
- x="28"
- height="4"
- width="4"
- id="rect4686"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4688"
- width="4"
- height="4"
- x="32"
- y="28" />
- <rect
- y="28"
- x="36"
- height="4"
- width="4"
- id="rect4690"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4692"
- width="4"
- height="4"
- x="40"
- y="28" />
- <rect
- y="28"
- x="44"
- height="4"
- width="4"
- id="rect4694"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4696"
- width="4"
- height="4"
- x="48"
- y="24" />
- <rect
- y="24"
- x="52"
- height="4"
- width="4"
- id="rect4698"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4700"
- width="4"
- height="4"
- x="56"
- y="24" />
- <rect
- y="24"
- x="60"
- height="4"
- width="4"
- id="rect4702"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- y="28"
- x="48"
- height="4"
- width="4"
- id="rect4704"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4706"
- width="4"
- height="4"
- x="52"
- y="28" />
- <rect
- y="28"
- x="56"
- height="4"
- width="4"
- id="rect4708"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4710"
- width="4"
- height="4"
- x="60"
- y="28" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4448-5"
- width="4"
- height="4"
- x="0"
- y="32" />
- <rect
- y="32"
- x="4"
- height="4"
- width="4"
- id="rect4450-2"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4452-3"
- width="4"
- height="4"
- x="8"
- y="32" />
- <rect
- y="32"
- x="12"
- height="4"
- width="4"
- id="rect4454-7"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4456-2"
- width="4"
- height="4"
- x="16"
- y="32" />
- <rect
- y="32"
- x="20"
- height="4"
- width="4"
- id="rect4458-4"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- y="36"
- x="0"
- height="4"
- width="4"
- id="rect4460-9"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4462-7"
- width="4"
- height="4"
- x="4"
- y="36" />
- <rect
- y="36"
- x="8"
- height="4"
- width="4"
- id="rect4464-3"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4466-7"
- width="4"
- height="4"
- x="12"
- y="36" />
- <rect
- y="36"
- x="16"
- height="4"
- width="4"
- id="rect4468-8"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4470-9"
- width="4"
- height="4"
- x="20"
- y="36" />
- <rect
- y="32"
- x="24"
- height="4"
- width="4"
- id="rect4472-9"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4474-6"
- width="4"
- height="4"
- x="28"
- y="32" />
- <rect
- y="32"
- x="32"
- height="4"
- width="4"
- id="rect4476-7"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4478-8"
- width="4"
- height="4"
- x="36"
- y="32" />
- <rect
- y="32"
- x="40"
- height="4"
- width="4"
- id="rect4480-1"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4482-6"
- width="4"
- height="4"
- x="44"
- y="32" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4484-7"
- width="4"
- height="4"
- x="24"
- y="36" />
- <rect
- y="36"
- x="28"
- height="4"
- width="4"
- id="rect4486-1"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4488-9"
- width="4"
- height="4"
- x="32"
- y="36" />
- <rect
- y="36"
- x="36"
- height="4"
- width="4"
- id="rect4490-9"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4492-3"
- width="4"
- height="4"
- x="40"
- y="36" />
- <rect
- y="36"
- x="44"
- height="4"
- width="4"
- id="rect4494-9"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4496-4"
- width="4"
- height="4"
- x="48"
- y="32" />
- <rect
- y="32"
- x="52"
- height="4"
- width="4"
- id="rect4498-2"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4500-1"
- width="4"
- height="4"
- x="56"
- y="32" />
- <rect
- y="32"
- x="60"
- height="4"
- width="4"
- id="rect4502-7"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- y="36"
- x="48"
- height="4"
- width="4"
- id="rect4508-4"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#b9855c;fill-opacity:1;stroke:none"
- id="rect4510-6"
- width="4"
- height="4"
- x="52"
- y="36" />
- <rect
- y="36"
- x="56"
- height="4"
- width="4"
- id="rect4512-8"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4514-1"
- width="4"
- height="4"
- x="60"
- y="36" />
- <rect
- y="40"
- x="0"
- height="4"
- width="4"
- id="rect4520-0"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4522-3"
- width="4"
- height="4"
- x="4"
- y="40" />
- <rect
- y="40"
- x="8"
- height="4"
- width="4"
- id="rect4524-1"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#b9855c;fill-opacity:1;stroke:none"
- id="rect4526-3"
- width="4"
- height="4"
- x="12"
- y="40" />
- <rect
- y="40"
- x="16"
- height="4"
- width="4"
- id="rect4528-7"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4530-0"
- width="4"
- height="4"
- x="20"
- y="40" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4532-2"
- width="4"
- height="4"
- x="0"
- y="44" />
- <rect
- y="44"
- x="4"
- height="4"
- width="4"
- id="rect4534-0"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4536-9"
- width="4"
- height="4"
- x="8"
- y="44" />
- <rect
- y="44"
- x="12"
- height="4"
- width="4"
- id="rect4538-0"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4540-2"
- width="4"
- height="4"
- x="16"
- y="44" />
- <rect
- y="44"
- x="20"
- height="4"
- width="4"
- id="rect4542-9"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#b9855c;fill-opacity:1;stroke:none"
- id="rect4544-6"
- width="4"
- height="4"
- x="24"
- y="40" />
- <rect
- y="40"
- x="28"
- height="4"
- width="4"
- id="rect4546-9"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4548-9"
- width="4"
- height="4"
- x="32"
- y="40" />
- <rect
- y="40"
- x="36"
- height="4"
- width="4"
- id="rect4550-8"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#b9855c;fill-opacity:1;stroke:none"
- id="rect4552-7"
- width="4"
- height="4"
- x="40"
- y="40" />
- <rect
- y="40"
- x="44"
- height="4"
- width="4"
- id="rect4554-6"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- y="44"
- x="24"
- height="4"
- width="4"
- id="rect4556-1"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4558-9"
- width="4"
- height="4"
- x="28"
- y="44" />
- <rect
- y="44"
- x="32"
- height="4"
- width="4"
- id="rect4560-7"
- style="fill:#6c6c6c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4562-5"
- width="4"
- height="4"
- x="36"
- y="44" />
- <rect
- y="44"
- x="40"
- height="4"
- width="4"
- id="rect4564-8"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4566-2"
- width="4"
- height="4"
- x="44"
- y="44" />
- <rect
- y="40"
- x="48"
- height="4"
- width="4"
- id="rect4568-9"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4570-1"
- width="4"
- height="4"
- x="52"
- y="40" />
- <rect
- y="40"
- x="56"
- height="4"
- width="4"
- id="rect4572-9"
- style="fill:#878787;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4574-5"
- width="4"
- height="4"
- x="60"
- y="40" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4576-8"
- width="4"
- height="4"
- x="48"
- y="44" />
- <rect
- y="44"
- x="52"
- height="4"
- width="4"
- id="rect4578-7"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4580-6"
- width="4"
- height="4"
- x="56"
- y="44" />
- <rect
- y="44"
- x="60"
- height="4"
- width="4"
- id="rect4582-0"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- y="48"
- x="0"
- height="4"
- width="4"
- id="rect4930"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4932"
- width="4"
- height="4"
- x="4"
- y="48" />
- <rect
- y="48"
- x="8"
- height="4"
- width="4"
- id="rect4934"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4936"
- width="4"
- height="4"
- x="12"
- y="48" />
- <rect
- y="48"
- x="16"
- height="4"
- width="4"
- id="rect4938"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4940"
- width="4"
- height="4"
- x="20"
- y="48" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4942"
- width="4"
- height="4"
- x="0"
- y="52" />
- <rect
- y="52"
- x="4"
- height="4"
- width="4"
- id="rect4944"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4946"
- width="4"
- height="4"
- x="8"
- y="52" />
- <rect
- y="52"
- x="12"
- height="4"
- width="4"
- id="rect4948"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4950"
- width="4"
- height="4"
- x="16"
- y="52" />
- <rect
- y="52"
- x="20"
- height="4"
- width="4"
- id="rect4952"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#b9855c;fill-opacity:1;stroke:none"
- id="rect4954"
- width="4"
- height="4"
- x="24"
- y="48" />
- <rect
- y="48"
- x="28"
- height="4"
- width="4"
- id="rect4956"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4958"
- width="4"
- height="4"
- x="32"
- y="48" />
- <rect
- y="48"
- x="36"
- height="4"
- width="4"
- id="rect4960"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4962"
- width="4"
- height="4"
- x="40"
- y="48" />
- <rect
- y="48"
- x="44"
- height="4"
- width="4"
- id="rect4964"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- y="52"
- x="24"
- height="4"
- width="4"
- id="rect4966"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4968"
- width="4"
- height="4"
- x="28"
- y="52" />
- <rect
- y="52"
- x="32"
- height="4"
- width="4"
- id="rect4970"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4972"
- width="4"
- height="4"
- x="36"
- y="52" />
- <rect
- y="52"
- x="40"
- height="4"
- width="4"
- id="rect4974"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4976"
- width="4"
- height="4"
- x="44"
- y="52" />
- <rect
- y="48"
- x="48"
- height="4"
- width="4"
- id="rect4978"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4980"
- width="4"
- height="4"
- x="52"
- y="48" />
- <rect
- y="48"
- x="56"
- height="4"
- width="4"
- id="rect4982"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#b9855c;fill-opacity:1;stroke:none"
- id="rect4984"
- width="4"
- height="4"
- x="60"
- y="48" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect4986"
- width="4"
- height="4"
- x="48"
- y="52" />
- <rect
- y="52"
- x="52"
- height="4"
- width="4"
- id="rect4988"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4990"
- width="4"
- height="4"
- x="56"
- y="52" />
- <rect
- y="52"
- x="60"
- height="4"
- width="4"
- id="rect4992"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect4994"
- width="4"
- height="4"
- x="0"
- y="56" />
- <rect
- y="56"
- x="4"
- height="4"
- width="4"
- id="rect4996"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect4998"
- width="4"
- height="4"
- x="8"
- y="56" />
- <rect
- y="56"
- x="12"
- height="4"
- width="4"
- id="rect5000"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect5002"
- width="4"
- height="4"
- x="16"
- y="56" />
- <rect
- y="56"
- x="20"
- height="4"
- width="4"
- id="rect5004"
- style="fill:#593d29;fill-opacity:1;stroke:none" />
- <rect
- y="60"
- x="0"
- height="4"
- width="4"
- id="rect5006"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect5008"
- width="4"
- height="4"
- x="4"
- y="60" />
- <rect
- y="60"
- x="8"
- height="4"
- width="4"
- id="rect5010"
- style="fill:#b9855c;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect5012"
- width="4"
- height="4"
- x="12"
- y="60" />
- <rect
- y="60"
- x="16"
- height="4"
- width="4"
- id="rect5014"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect5016"
- width="4"
- height="4"
- x="20"
- y="60" />
- <rect
- y="56"
- x="24"
- height="4"
- width="4"
- id="rect5018"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect5020"
- width="4"
- height="4"
- x="28"
- y="56" />
- <rect
- y="56"
- x="32"
- height="4"
- width="4"
- id="rect5022"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect5024"
- width="4"
- height="4"
- x="36"
- y="56" />
- <rect
- y="56"
- x="40"
- height="4"
- width="4"
- id="rect5026"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect5028"
- width="4"
- height="4"
- x="44"
- y="56" />
- <rect
- style="fill:#878787;fill-opacity:1;stroke:none"
- id="rect5030"
- width="4"
- height="4"
- x="24"
- y="60" />
- <rect
- y="60"
- x="28"
- height="4"
- width="4"
- id="rect5032"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect5034"
- width="4"
- height="4"
- x="32"
- y="60" />
- <rect
- y="60"
- x="36"
- height="4"
- width="4"
- id="rect5036"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect5038"
- width="4"
- height="4"
- x="40"
- y="60" />
- <rect
- y="60"
- x="44"
- height="4"
- width="4"
- id="rect5040"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#79553a;fill-opacity:1;stroke:none"
- id="rect5042"
- width="4"
- height="4"
- x="48"
- y="56" />
- <rect
- y="56"
- x="52"
- height="4"
- width="4"
- id="rect5044"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect5046"
- width="4"
- height="4"
- x="56"
- y="56" />
- <rect
- y="56"
- x="60"
- height="4"
- width="4"
- id="rect5048"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- y="60"
- x="48"
- height="4"
- width="4"
- id="rect5050"
- style="fill:#966c4a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#966c4a;fill-opacity:1;stroke:none"
- id="rect5052"
- width="4"
- height="4"
- x="52"
- y="60" />
- <rect
- y="60"
- x="56"
- height="4"
- width="4"
- id="rect5054"
- style="fill:#79553a;fill-opacity:1;stroke:none" />
- <rect
- style="fill:#593d29;fill-opacity:1;stroke:none"
- id="rect5056"
- width="4"
- height="4"
- x="60"
- y="60" />
- <path
- inkscape:connector-curvature="0"
- id="path3279"
- style="font-size:76.18933868px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient3293);fill-opacity:1;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"
- d="m 37.233107,43.070771 c -0.913385,-0.751568 -2.091894,-2.0042 -3.535529,-3.7579 -1.974039,2.505279 -3.83019,4.311158 -5.568458,5.41764 -2.180273,1.33615 -4.9645,2.004221 -8.352688,2.004214 -3.97749,7e-6 -7.277313,-1.054292 -9.8994808,-3.1629 -2.7695088,-2.212974 -4.1542564,-5.146221 -4.1542467,-8.799752 -9.7e-6,-3.507351 1.3847379,-6.451037 4.1542467,-8.831067 2.4748538,-2.10857 5.8041408,-3.162868 9.9878698,-3.162899 2.150754,3.1e-5 4.021637,0.313189 5.612652,0.939475 1.856121,0.688978 3.417645,1.628452 4.684576,2.818425 1.178474,1.064766 2.356983,2.317398 3.535529,3.757901 1.973965,-2.505241 3.830116,-4.311119 5.568458,-5.41764 2.180198,-1.336112 4.964424,-2.004182 8.352687,-2.004214 3.977416,3.2e-5 7.277239,1.05433 9.899482,3.1629 2.769434,2.213012 4.154182,5.146259 4.154247,8.799751 -6.5e-5,3.50739 -1.384813,6.451076 -4.154247,8.831068 -2.47493,2.108607 -5.804215,3.162907 -9.987869,3.162899 -2.15083,8e-6 -4.021712,-0.31315 -5.612653,-0.939475 -1.591032,-0.563676 -3.152556,-1.503151 -4.684576,-2.818426 M 19.290297,42.63235 c 4.861324,1.1e-5 8.750403,-2.505254 11.667246,-7.515802 -3.7418,-5.46981 -7.630877,-8.204724 -11.667246,-8.20475 -2.946295,2.6e-5 -5.17073,0.751606 -6.67331,2.254741 -1.620467,1.607569 -2.430691,3.476079 -2.430677,5.605534 -1.4e-5,2.338267 0.81021,4.227655 2.430677,5.668168 1.649894,1.461418 3.874329,2.19212 6.67331,2.192109 M 48.104859,26.974429 c -4.389996,2.7e-5 -8.279074,2.505292 -11.667245,7.515802 3.712261,5.469847 7.601339,8.204762 11.667245,8.20475 2.946219,1.2e-5 5.170654,-0.751567 6.673311,-2.25474 1.62039,-1.607532 2.430615,-3.476042 2.430677,-5.605536 -6.2e-5,-2.338228 -0.810287,-4.227615 -2.430677,-5.668166 -1.64997,-1.46138 -3.874405,-2.192083 -6.673311,-2.19211" />
- <path
- inkscape:connector-curvature="0"
- id="path3272"
- style="font-size:76.18933868px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient3286);fill-opacity:1;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"
- d="M 35.535529,40.267381 C 34.622143,39.515813 33.443636,38.26318 32,36.50948 c -1.97404,2.505279 -3.830191,4.311157 -5.568458,5.417641 -2.180273,1.33615 -4.964499,2.004221 -8.352688,2.004213 -3.97749,8e-6 -7.277313,-1.054291 -9.8994809,-3.1629 -2.7695089,-2.212973 -4.1542564,-5.14622 -4.1542466,-8.799751 -9.8e-6,-3.507351 1.3847377,-6.451037 4.1542466,-8.831067 2.4748539,-2.10857 5.8041399,-3.162869 9.9878699,-3.1629 2.150754,3.1e-5 4.021636,0.313189 5.612653,0.939476 1.856121,0.688977 3.417644,1.628452 4.684575,2.818425 1.178474,1.064765 2.356983,2.317397 3.535529,3.757901 1.973964,-2.505241 3.830115,-4.31112 5.568458,-5.417641 2.180198,-1.336111 4.964425,-2.004183 8.352688,-2.004214 3.977415,3.1e-5 7.277238,1.054331 9.899481,3.162901 2.769433,2.213011 4.154181,5.146259 4.154247,8.799751 -6.6e-5,3.50739 -1.384814,6.451076 -4.154247,8.831067 -2.474929,2.108608 -5.804216,3.162907 -9.98787,3.1629 -2.150829,7e-6 -4.021712,-0.313151 -5.612651,-0.939475 -1.591033,-0.563676 -3.152557,-1.503151 -4.684577,-2.818426 m -17.94281,-0.438422 c 4.861324,1.2e-5 8.750402,-2.505253 11.667246,-7.515802 -3.741799,-5.469809 -7.630877,-8.204723 -11.667246,-8.20475 -2.946294,2.7e-5 -5.170729,0.751607 -6.673311,2.25474 -1.6204657,1.607571 -2.4306903,3.47608 -2.4306761,5.605536 -1.42e-5,2.338266 0.8102104,4.227653 2.4306761,5.668168 1.649895,1.461417 3.87433,2.19212 6.673311,2.192108 m 28.814562,-15.65792 c -4.389996,2.7e-5 -8.279075,2.505292 -11.667246,7.515802 3.712261,5.469847 7.60134,8.204761 11.667246,8.20475 2.94622,1.1e-5 5.170655,-0.751569 6.673311,-2.25474 1.620391,-1.607532 2.430616,-3.476042 2.430676,-5.605536 -6e-5,-2.338228 -0.810285,-4.227615 -2.430676,-5.668168 -1.64997,-1.461379 -3.874405,-2.192081 -6.673311,-2.192108" />
- <path
- style="font-size:76.18933868px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;opacity:0.3;fill:#ccff00;fill-opacity:1;stroke:none;font-family:Sans"
- d="m 18.1875,19.84375 c -4.183729,3.1e-5 -7.525146,1.07893 -10,3.1875 -2.7695089,2.38003 -4.1562597,5.305149 -4.15625,8.8125 -9.7e-6,3.65353 1.3867411,6.599527 4.15625,8.8125 -1.5212822,-1.916504 -2.2812572,-4.2297 -2.28125,-6.9375 -9.7e-6,-3.507351 1.3867411,-6.43247 4.15625,-8.8125 2.474854,-2.10857 5.816271,-3.187469 10,-3.1875 2.150754,3.1e-5 4.033984,0.342464 5.625,0.96875 1.856121,0.688978 3.389319,1.622527 4.65625,2.8125 0.06409,0.05791 0.12341,0.128483 0.1875,0.1875 -0.686074,-0.747192 -1.376449,-1.442646 -2.0625,-2.0625 -1.266931,-1.189973 -2.800129,-2.123522 -4.65625,-2.8125 -1.591016,-0.626286 -3.474246,-0.968719 -5.625,-0.96875 z m 27.75,0.09375 c -3.388264,3.1e-5 -6.163553,0.695138 -8.34375,2.03125 -1.704583,1.085031 -3.678235,3.085676 -5.609375,5.515625 0.579636,0.617601 1.170346,1.291505 1.75,2 1.973964,-2.505241 3.996032,-4.534104 5.734375,-5.640625 2.180197,-1.336112 4.955486,-2.031219 8.34375,-2.03125 3.977415,3.1e-5 7.284007,1.07893 9.90625,3.1875 -0.534738,-0.676996 -1.150988,-1.296453 -1.875,-1.875 -2.622243,-2.10857 -5.928835,-3.187469 -9.90625,-3.1875 z m 8.3125,7.59375 c 0.852375,1.223658 1.281206,2.679142 1.28125,4.375 -6.1e-5,2.129494 -0.81711,4.017469 -2.4375,5.625 -1.502657,1.503172 -3.710031,2.250011 -6.65625,2.25 -2.487851,7e-6 -4.988305,-0.967727 -7.34375,-3.015625 2.940596,3.289974 6.065444,4.890634 9.21875,4.890625 2.946219,1.1e-5 5.153593,-0.746828 6.65625,-2.25 1.62039,-1.607531 2.437439,-3.495506 2.4375,-5.625 -6.1e-5,-2.338228 -0.81711,-4.215698 -2.4375,-5.65625 C 54.734909,27.917887 54.506918,27.70901 54.25,27.53125 z M 29.28125,32.1875 c -2.916844,5.010548 -6.794926,7.531261 -11.65625,7.53125 -2.419266,1e-5 -4.259506,-0.33008 -5.820312,-1.421875 0.327066,0.474769 0.553213,0.705259 1.007812,1.109375 1.649895,1.461418 3.888519,2.187511 6.6875,2.1875 4.861324,1.1e-5 8.739406,-2.520702 11.65625,-7.53125 z m 4.625,6.09375 c -0.03847,0.04882 -0.08662,0.07671 -0.125,0.125 0.644368,0.697893 1.225264,1.274763 1.71875,1.6875 -0.496316,-0.544589 -1.011044,-1.10464 -1.59375,-1.8125 z"
- id="text5100"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccscsccccccccccccccccccccscscccccsccscccccc" />
- <path
- inkscape:connector-curvature="0"
- style="font-size:76.18933868px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;opacity:0.6;fill:#ccff00;fill-opacity:1;stroke:none;font-family:Sans"
- d="m 18.497319,20.200444 c -4.183729,3.1e-5 -7.525146,1.07893 -9.9999998,3.1875 -2.769509,2.38003 -4.15626,5.305149 -4.15625,8.8125 -10e-6,3.65353 1.386741,6.599526 4.15625,8.8125 0.04016,0.03229 0.08452,0.06195 0.125,0.09375 -2.099258,-2.088931 -3.156258,-4.725391 -3.15625,-7.90625 -10e-6,-3.507351 1.386741,-6.43247 4.15625,-8.8125 2.4748538,-2.10857 5.8162708,-3.187469 9.9999998,-3.1875 2.150754,3.1e-5 4.033984,0.342464 5.625,0.96875 1.753945,0.651051 3.209663,1.526594 4.4375,2.625 -0.294623,-0.289675 -0.611631,-0.546309 -0.90625,-0.8125 -1.266931,-1.189973 -2.800129,-2.123522 -4.65625,-2.8125 -1.591016,-0.626286 -3.474246,-0.968719 -5.625,-0.96875 z m 27.75,0.09375 c -3.388264,3.1e-5 -6.163553,0.695138 -8.34375,2.03125 -1.699949,1.082082 -3.715349,3.033428 -5.640625,5.453125 0.333421,0.377464 0.666573,0.748711 1,1.15625 1.973964,-2.505241 4.027282,-4.502854 5.765625,-5.609375 2.180197,-1.336112 4.955486,-2.031219 8.34375,-2.03125 3.960394,3.1e-5 7.258204,1.065688 9.875,3.15625 -0.3384,-0.344593 -0.699118,-0.653406 -1.09375,-0.96875 -2.622243,-2.10857 -5.928835,-3.187469 -9.90625,-3.1875 z m 7.71875,6.875 c 1.240618,1.358666 1.874946,3.047801 1.875,5.09375 -6.1e-5,2.129494 -0.81711,4.017469 -2.4375,5.625 -1.502657,1.503172 -3.710031,2.250011 -6.65625,2.25 -2.255932,6e-6 -4.477939,-0.847369 -6.625,-2.53125 2.502325,2.328598 5.097121,3.531257 7.75,3.53125 2.946219,1.1e-5 5.153593,-0.746828 6.65625,-2.25 1.62039,-1.607531 2.437439,-3.495506 2.4375,-5.625 -6.1e-5,-2.338228 -0.81711,-4.215698 -2.4375,-5.65625 -0.174038,-0.154146 -0.375679,-0.299613 -0.5625,-0.4375 z m -24.375,5.375 c -2.916844,5.010548 -6.794926,7.531261 -11.65625,7.53125 -2.449108,1e-5 -4.461911,-0.568603 -6.03125,-1.6875 0.15565,0.165457 0.294325,0.344945 0.46875,0.5 1.649895,1.461418 3.888519,2.187511 6.6875,2.1875 4.861324,1.1e-5 8.739406,-2.520702 11.65625,-7.53125 z m 3.875,5.21875 c -0.04366,0.0554 -0.08146,0.10153 -0.125,0.15625 0.97366,1.114659 1.851375,2.034323 2.53125,2.59375 0.05858,0.05029 0.128837,0.07581 0.1875,0.125 -0.742667,-0.732421 -1.599645,-1.667381 -2.59375,-2.875 z"
- id="text5058-0"
- sodipodi:nodetypes="ccsccscccccccccccccccccccscscccccsccsccccccc" />
+ <g
+ id="g2048"
+ transform="translate(9.113e-4,0.00104183)">
+ <rect
+ rx="8.5333338"
+ ry="8.5333338"
+ style="fill:url(#linearGradient2050);fill-opacity:1;stroke:none;stroke-width:17.06666756"
+ id="rect2026"
+ width="68.26667"
+ height="68.26667"
+ x="-1.3322676e-15"
+ y="3.0270508e-06" />
+ <rect
+ rx="4.2666626"
+ y="4.2656283"
+ x="4.2657552"
+ height="59.733334"
+ width="59.73333"
+ id="rect2028"
+ style="fill:url(#radialGradient2052);fill-opacity:1;stroke:none;stroke-width:14.93333435"
+ ry="4.2666669" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4811"
+ d="m 4.2669272,4.2645856 -9.11e-4,8.5333334 h 4.267577 v 4.267579 h 8.5332038 v 4.265625 h 4.265625 V 8.5322946 H 25.6 v 8.5332034 h 4.265625 v -4.267579 h 4.267578 v 8.533204 h 4.265625 v -4.265625 h 4.267578 v 4.265625 h 4.267579 v -4.265625 h 4.265624 v -4.267579 h 4.267579 v 4.267579 h 8.533203 l -1.3e-4,-12.8009124 z"
+ style="opacity:0.6;fill:#593d29;fill-opacity:1;stroke:none;stroke-width:17.06666756"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccc" />
+ <path
+ style="fill:url(#radialGradient4803);fill-opacity:1;stroke:none;stroke-width:17.06666756"
+ d="m 8.5329442,-0.0018207 c -4.7274675,0 -8.5332035,3.805736 -8.5332035,8.533203 v 4.2675787 h 4.265625 V 8.5313823 c 0,-0.521698 0.105433,-1.01339 0.27539,-1.47461 -0.169616,0.460814 -0.27539,0.953462 -0.27539,1.47461 h 4.2675785 v 4.2675787 h 4.2656248 4.267578 v 4.265625 h 4.265625 V 12.798961 8.5313823 4.2657573 h 4.267578 v 4.265625 4.2675787 h 4.265625 V 8.5313823 h 4.267578 v 4.2675787 4.265625 h 4.265625 v -4.265625 h 4.267578 v 4.265625 h 4.267579 v -4.265625 h 4.265624 V 8.5313823 h 4.267579 v 4.2675787 h 4.265625 4.267578 V 8.5313823 h 4.265625 c 0,-4.727467 -3.805737,-8.533203 -8.533203,-8.533203 z m -3.019531,5.513671 c -0.318089,0.317888 -0.570428,0.695824 -0.7753915,1.101563 0.2048795,-0.405231 0.4576385,-0.784012 0.7753915,-1.101563 z"
+ id="path4794"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:1;fill:url(#linearGradient2140);fill-opacity:1;stroke:none;stroke-width:17.06666756"
+ d="m 8.5322887,-9.083059e-4 c -4.72747,0 -8.5332,3.8057359059 -8.5332,8.5332029059 V 59.731515 c 0,4.727467 3.80573,8.535156 8.5332,8.535156 H 59.731502 c 4.72747,0 8.5332,-3.807689 8.5332,-8.535156 V 8.5322946 c 0,-4.727467 -3.80573,-8.5332029059 -8.5332,-8.5332029059 z m 0,4.2675779059 H 59.731502 c 2.36373,0 4.26758,1.901892 4.26758,4.265625 V 59.731515 c 0,2.363733 -1.90385,4.267578 -4.26758,4.267578 H 8.5322887 c -2.36373,0 -4.26758,-1.903845 -4.26758,-4.267578 V 8.5322946 c 0,-2.363733 1.90385,-4.265625 4.26758,-4.265625 z"
+ id="path2046"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g1092">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4786"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:76.18933868px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient4790);fill-opacity:1;stroke:none;stroke-width:1.06666672;opacity:0.5"
+ d="m 38.886673,44.940882 c -0.974277,-0.801673 -2.231353,-2.137814 -3.771231,-4.008427 -2.105641,2.672298 -4.085536,4.598569 -5.939688,5.778816 -2.325625,1.425227 -5.295467,2.137836 -8.909534,2.137828 -4.242656,8e-6 -7.762467,-1.124578 -10.5594458,-3.37376 C 6.7526311,43.114834 5.275567,39.986037 5.2755773,36.088937 5.275567,32.347763 6.7526311,29.207831 9.7067742,26.669132 12.346618,24.419991 15.897857,23.295407 20.360501,23.295373 c 2.294138,3.4e-5 4.289747,0.334069 5.986829,1.002107 1.979863,0.73491 3.645488,1.737016 4.996881,3.00632 1.257039,1.135751 2.514115,2.471891 3.771231,4.008428 2.105563,-2.672257 4.085457,-4.598527 5.939689,-5.778816 2.325544,-1.425186 5.295385,-2.137794 8.909533,-2.137828 4.242577,3.4e-5 7.762388,1.124618 10.559447,3.37376 2.954063,2.360546 4.431127,5.489343 4.431197,9.386401 -7e-5,3.741216 -1.477134,6.881147 -4.431197,9.419806 -2.639925,2.24918 -6.191163,3.373767 -10.653727,3.373758 -2.294219,9e-6 -4.289826,-0.334026 -5.98683,-1.002106 -1.697101,-0.601255 -3.362726,-1.603361 -4.996881,-3.006321 M 19.747676,44.473233 c 5.185412,1.1e-5 9.333763,-2.672271 12.445062,-8.016856 -3.991253,-5.834464 -8.139602,-8.751705 -12.445062,-8.751733 -3.142715,2.8e-5 -5.515446,0.801713 -7.118198,2.405057 -1.728498,1.71474 -2.592737,3.707818 -2.592722,5.979236 -1.5e-5,2.494152 0.864224,4.509499 2.592722,6.046046 1.759887,1.558846 4.132618,2.338261 7.118198,2.33825 M 50.483209,27.77145 c -4.682663,2.9e-5 -8.831013,2.672312 -12.445062,8.016856 3.959745,5.834503 8.108095,8.751746 12.445062,8.751733 3.142633,1.3e-5 5.515364,-0.801671 7.118198,-2.405056 1.728416,-1.714701 2.592656,-3.707778 2.592722,-5.979238 -6.6e-5,-2.49411 -0.864306,-4.509456 -2.592722,-6.046044 -1.759968,-1.558805 -4.132699,-2.338222 -7.118198,-2.338251" />
+ <path
+ d="m 39.715314,45.942156 c -0.974277,-0.801673 -2.231353,-2.137814 -3.771231,-4.008427 -2.105641,2.672298 -4.085536,4.598569 -5.939688,5.778816 -2.325625,1.425227 -5.295467,2.137836 -8.909534,2.137828 -4.242656,8e-6 -7.762467,-1.124578 -10.559446,-3.37376 -2.9541431,-2.360505 -4.4312072,-5.489302 -4.4311969,-9.386402 -1.03e-5,-3.741174 1.4770538,-6.881106 4.4311969,-9.419805 2.639844,-2.249141 6.191083,-3.373725 10.653727,-3.373759 2.294138,3.4e-5 4.289747,0.334069 5.986829,1.002107 1.979863,0.73491 3.645488,1.737016 4.996881,3.00632 1.257039,1.135751 2.514115,2.471891 3.771231,4.008428 2.105563,-2.672257 4.085457,-4.598527 5.939689,-5.778816 2.325544,-1.425186 5.295385,-2.137794 8.909533,-2.137828 4.242577,3.4e-5 7.762388,1.124618 10.559447,3.37376 2.954063,2.360546 4.431127,5.489343 4.431197,9.386401 -7e-5,3.741216 -1.477134,6.881147 -4.431197,9.419806 -2.639925,2.24918 -6.191163,3.373767 -10.653727,3.373758 -2.294219,9e-6 -4.289826,-0.334026 -5.98683,-1.002106 -1.697101,-0.601255 -3.362726,-1.603361 -4.996881,-3.006321 M 20.576317,45.474507 c 5.185412,1.1e-5 9.333763,-2.672271 12.445062,-8.016856 -3.991253,-5.834464 -8.139602,-8.751705 -12.445062,-8.751733 -3.142715,2.8e-5 -5.515446,0.801713 -7.118198,2.405057 -1.728498,1.71474 -2.592737,3.707818 -2.592722,5.979236 -1.5e-5,2.494152 0.864224,4.509499 2.592722,6.046046 1.759887,1.558846 4.132618,2.338261 7.118198,2.33825 M 51.31185,28.772724 c -4.682663,2.9e-5 -8.831013,2.672312 -12.445062,8.016856 3.959745,5.834503 8.108095,8.751746 12.445062,8.751733 3.142633,1.3e-5 5.515364,-0.801671 7.118198,-2.405056 1.728416,-1.714701 2.592656,-3.707778 2.592722,-5.979238 -6.6e-5,-2.49411 -0.864306,-4.509456 -2.592722,-6.046044 C 56.67008,29.55217 54.297349,28.772753 51.31185,28.772724"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:76.18933868px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient3293);fill-opacity:1;stroke:none;stroke-width:1.06666672;opacity:0.5"
+ id="path3279"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 37.904564,42.951873 c -0.974278,-0.801672 -2.231352,-2.137814 -3.771231,-4.008428 -2.105642,2.672298 -4.085537,4.598568 -5.939688,5.778817 -2.325625,1.425227 -5.295466,2.137836 -8.909534,2.137828 -4.242656,8e-6 -7.762467,-1.124577 -10.5594464,-3.37376 -2.9541428,-2.360505 -4.4312068,-5.489302 -4.4311963,-9.386401 -1.05e-5,-3.741175 1.4770535,-6.881107 4.4311963,-9.419805 2.6398444,-2.249142 6.1910824,-3.373727 10.6537284,-3.37376 2.294137,3.3e-5 4.289745,0.334068 5.986829,1.002107 1.979863,0.734909 3.645487,1.737016 4.99688,3.00632 1.257039,1.13575 2.514116,2.471891 3.771231,4.008428 2.105562,-2.672257 4.085456,-4.598528 5.939689,-5.778817 2.325544,-1.425185 5.295387,-2.137795 8.909534,-2.137828 4.242576,3.3e-5 7.762387,1.12462 10.559446,3.373761 2.954062,2.360545 4.431127,5.489343 4.431197,9.386401 -7e-5,3.741216 -1.477135,6.881148 -4.431197,9.419805 -2.639924,2.249182 -6.191164,3.373767 -10.653728,3.37376 -2.294217,7e-6 -4.289826,-0.334028 -5.986828,-1.002107 -1.697101,-0.601254 -3.362727,-1.603361 -4.996882,-3.006321 m -19.138997,-0.46765 c 5.185412,1.3e-5 9.333762,-2.67227 12.445062,-8.016856 -3.991252,-5.834462 -8.139602,-8.751704 -12.445062,-8.751733 -3.142714,2.9e-5 -5.515444,0.801714 -7.118198,2.405056 -1.7284972,1.714743 -2.5927368,3.707819 -2.5927216,5.979239 -1.52e-5,2.49415 0.8642244,4.509496 2.5927216,6.046045 1.759888,1.558845 4.132618,2.338262 7.118198,2.338249 M 49.5011,25.782442 c -4.682663,2.8e-5 -8.831014,2.672311 -12.445063,8.016855 3.959745,5.834504 8.108096,8.751745 12.445063,8.751733 3.142634,1.2e-5 5.515365,-0.801673 7.118198,-2.405056 1.728417,-1.7147 2.592657,-3.707778 2.592721,-5.979238 -6.4e-5,-2.49411 -0.864304,-4.509456 -2.592721,-6.046046 C 54.85933,26.561886 52.486599,25.78247 49.5011,25.782442"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:76.18933868px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient3286);fill-opacity:1;stroke:none;stroke-width:1.06666672"
+ id="path3272"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccscsccccccccccccccccccccscscccccsccscccccc"
+ inkscape:connector-curvature="0"
+ id="text5100"
+ d="m 19.4,21.166667 c -4.462644,3.3e-5 -8.026822,1.150858 -10.6666667,3.4 -2.9541428,2.538698 -4.4333436,5.658825 -4.4333333,9.4 -1.03e-5,3.897098 1.4791905,7.039495 4.4333333,9.4 -1.622701,-2.044271 -2.433341,-4.51168 -2.4333333,-7.4 -1.03e-5,-3.741175 1.4791905,-6.861302 4.433333,-9.4 2.639845,-2.249142 6.204023,-3.399967 10.666667,-3.4 2.294138,3.3e-5 4.302916,0.365295 6,1.033333 1.979862,0.73491 3.615274,1.730695 4.966667,3 0.06836,0.06177 0.131637,0.137049 0.2,0.2 -0.731813,-0.797005 -1.468213,-1.538822 -2.2,-2.2 -1.351393,-1.269305 -2.986805,-2.26509 -4.966667,-3 -1.697084,-0.668038 -3.705862,-1.0333 -6,-1.033333 z m 29.6,0.1 c -3.614148,3.3e-5 -6.574457,0.74148 -8.9,2.166666 -1.818222,1.157367 -3.923451,3.291388 -5.983333,5.883334 0.618278,0.658774 1.248369,1.377605 1.866666,2.133333 2.105562,-2.672257 4.262434,-4.836378 6.116667,-6.016667 2.325543,-1.425186 5.285852,-2.166633 8.9,-2.166666 4.242576,3.3e-5 7.769607,1.150858 10.566667,3.4 -0.570388,-0.722129 -1.227721,-1.382884 -2,-2 C 56.769607,22.417525 53.242576,21.2667 49,21.266667 Z m 8.866667,8.1 c 0.9092,1.305235 1.366619,2.857751 1.366666,4.666666 -6.5e-5,2.271461 -0.871584,4.285301 -2.6,6 -1.602834,1.603384 -3.957366,2.400012 -7.1,2.4 -2.653707,8e-6 -5.320858,-1.032242 -7.833333,-3.216666 3.136636,3.509305 6.469807,5.216676 9.833333,5.216666 3.142634,1.2e-5 5.497166,-0.796616 7.1,-2.4 1.728416,-1.714699 2.599935,-3.728539 2.6,-6 -6.5e-5,-2.49411 -0.871584,-4.496744 -2.6,-6.033333 -0.24943,-0.220921 -0.49262,-0.443723 -0.766666,-0.633333 z m -26.633334,4.966666 c -3.1113,5.344585 -7.247921,8.033345 -12.433333,8.033334 -2.58055,1e-5 -4.543473,-0.352086 -6.208333,-1.516667 0.348871,0.50642 0.590094,0.752276 1.075,1.183333 1.759888,1.558846 4.147753,2.333345 7.133333,2.333334 5.185412,1.1e-5 9.322033,-2.688749 12.433333,-8.033334 z m 4.933334,6.5 c -0.04103,0.05207 -0.09239,0.08182 -0.133334,0.133334 0.687326,0.744419 1.306949,1.359747 1.833334,1.8 -0.529404,-0.580895 -1.078447,-1.178283 -1.7,-1.933334 z"
+ style="font-style:normal;font-weight:normal;font-size:76.18933868px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;opacity:0.3;fill:#ccff00;fill-opacity:1;stroke:none;stroke-width:1.06666672" />
+ <path
+ sodipodi:nodetypes="ccsccscccccccccccccccccccscscccccsccsccccccc"
+ id="text5058-0"
+ d="m 19.730474,21.54714 c -4.462645,3.3e-5 -8.026823,1.150859 -10.6666669,3.4 -2.9541429,2.538699 -4.433344,5.658826 -4.4333333,9.4 -1.07e-5,3.897099 1.4791904,7.039495 4.4333333,9.4 0.042837,0.03444 0.090155,0.06608 0.1333334,0.1 -2.2392086,-2.228193 -3.3666752,-5.040417 -3.3666667,-8.433333 -1.07e-5,-3.741174 1.4791904,-6.861301 4.4333332,-9.4 2.639844,-2.249141 6.204022,-3.399967 10.666667,-3.4 2.294137,3.3e-5 4.302916,0.365295 6,1.033333 1.870874,0.694455 3.42364,1.628367 4.733333,2.8 -0.314265,-0.308986 -0.652406,-0.582729 -0.966667,-0.866666 -1.351393,-1.269305 -2.986804,-2.265091 -4.966666,-3 -1.697084,-0.668039 -3.705863,-1.033301 -6,-1.033334 z m 29.6,0.1 c -3.614149,3.3e-5 -6.574457,0.741481 -8.9,2.166667 -1.813279,1.154221 -3.963039,3.235656 -6.016667,5.816667 0.355649,0.402628 0.711011,0.798625 1.066667,1.233333 2.105561,-2.672257 4.295767,-4.803044 6.15,-5.983333 2.325543,-1.425187 5.285851,-2.166634 8.9,-2.166667 4.22442,3.3e-5 7.742084,1.136734 10.533333,3.366667 -0.36096,-0.367566 -0.745726,-0.696967 -1.166667,-1.033334 -2.797059,-2.249141 -6.32409,-3.399967 -10.566666,-3.4 z m 8.233333,7.333334 c 1.323326,1.449243 1.999942,3.250987 2,5.433333 -6.5e-5,2.27146 -0.871584,4.2853 -2.6,6 -1.602834,1.603383 -3.957366,2.400012 -7.1,2.4 -2.406328,6e-6 -4.776468,-0.90386 -7.066667,-2.7 2.669147,2.483838 5.436929,3.766674 8.266667,3.766667 3.142634,1.1e-5 5.497166,-0.796617 7.1,-2.4 1.728416,-1.7147 2.599935,-3.72854 2.6,-6 -6.5e-5,-2.49411 -0.871584,-4.496745 -2.6,-6.033334 -0.185641,-0.164422 -0.400724,-0.319587 -0.6,-0.466666 z m -26,5.733333 c -3.1113,5.344584 -7.247921,8.033345 -12.433333,8.033333 -2.612382,1.1e-5 -4.759372,-0.60651 -6.433334,-1.8 0.166027,0.176488 0.313947,0.367942 0.5,0.533334 1.759888,1.558845 4.147754,2.333345 7.133334,2.333333 5.185412,1.2e-5 9.322033,-2.688749 12.433333,-8.033333 z m 4.133333,5.566667 c -0.04657,0.05909 -0.08689,0.108298 -0.133333,0.166666 1.038571,1.18897 1.9748,2.169945 2.7,2.766667 0.06249,0.05364 0.137426,0.08086 0.2,0.133333 -0.792178,-0.781249 -1.706288,-1.778539 -2.766667,-3.066666 z"
+ style="font-style:normal;font-weight:normal;font-size:76.18933868px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;opacity:0.6;fill:#ccff00;fill-opacity:1;stroke:none;stroke-width:1.06666672"
+ inkscape:connector-curvature="0" />
+ </g>
</g>
</svg>
diff --git a/application/resources/pe_blue/pe_blue.qrc b/application/resources/pe_blue/pe_blue.qrc
index a4525d2e..1706371a 100644
--- a/application/resources/pe_blue/pe_blue.qrc
+++ b/application/resources/pe_blue/pe_blue.qrc
@@ -10,6 +10,7 @@
<file>scalable/copy.svg</file>
<file>scalable/coremods.svg</file>
<file>scalable/externaltools.svg</file>
+ <file>scalable/help.svg</file>
<file>scalable/instance-settings.svg</file>
<file>scalable/jarmods.svg</file>
<file>scalable/java.svg</file>
@@ -31,5 +32,6 @@
<file>scalable/status-good.svg</file>
<file>scalable/status-yellow.svg</file>
<file>scalable/viewfolder.svg</file>
+ <file>scalable/worlds.svg</file>
</qresource>
</RCC>
diff --git a/application/resources/pe_blue/scalable/help.svg b/application/resources/pe_blue/scalable/help.svg
new file mode 100644
index 00000000..e98540cb
--- /dev/null
+++ b/application/resources/pe_blue/scalable/help.svg
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xml:space="preserve"
+ enable-background="new 0 0 32 32"
+ viewBox="0 0 32 32"
+ y="0px"
+ x="0px"
+ id="Calque_1"
+ version="1.1"><metadata
+ id="metadata19"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs17" /><g
+ id="g12"><circle
+ id="circle2"
+ r="12"
+ cy="16"
+ cx="16"
+ fill="#DAEEFF" /><path
+ id="path10"
+ d="M16,32C7.2,32,0,24.8,0,16C0,7.2,7.2,0,16,0c8.8,0,16,7.2,16,16C32,24.8,24.8,32,16,32L16,32z M16,4 C9.4,4,4,9.4,4,16s5.4,12,12,12s12-5.4,12-12S22.6,4,16,4z"
+ fill="#3366CC" /></g><g
+ transform="translate(41.863574,-2.0092638)"
+ id="g861"><g
+ aria-label="?"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.34714317px;line-height:85.45981598px;font-family:'Nimbus Sans L';-inkscape-font-specification:'Nimbus Sans L';letter-spacing:0px;word-spacing:0px;fill:#666666;fill-opacity:1;stroke:none;stroke-width:3.4183929px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="text832"><path
+ d="m -20.968435,13.920532 c 0,0.6381 -0.07293,1.239737 -0.218777,1.804911 -0.145852,0.565174 -0.401092,1.066538 -0.76572,1.504093 -0.401092,0.492249 -0.774836,0.902456 -1.121233,1.230621 -0.346397,0.328166 -0.656332,0.6381 -0.929803,0.929803 -0.25524,0.273471 -0.464902,0.556059 -0.628985,0.847762 -0.145851,0.291703 -0.218777,0.656331 -0.218777,1.093885 v 0.38286 h -3.144921 V 20.72997 c 0,-0.601637 0.136736,-1.221505 0.410207,-1.859605 0.273471,-0.656332 0.756604,-1.285316 1.449399,-1.886953 0.346397,-0.309935 0.638099,-0.583406 0.875108,-0.820415 0.237009,-0.25524 0.428439,-0.492248 0.57429,-0.711025 0.145851,-0.237009 0.246124,-0.483133 0.300819,-0.738373 0.05469,-0.273471 0.08204,-0.57429 0.08204,-0.902456 0,-0.528711 -0.12762,-0.984497 -0.38286,-1.367357 -0.237009,-0.401091 -0.656331,-0.601637 -1.257968,-0.601637 -1.057423,0 -1.640829,0.692794 -1.750218,2.078383 h -3.06288 c 0.01823,-0.747489 0.145853,-1.431167 0.38286,-2.051036 0.237009,-0.6381 0.565175,-1.185043 0.984498,-1.640829 0.419323,-0.474017 0.920687,-0.8386455 1.504092,-1.0938855 0.601637,-0.25524 1.2762,-0.38286 2.023689,-0.38286 0.838646,0 1.567903,0.1367357 2.187771,0.4102072 0.619869,0.25524 1.130349,0.6198684 1.53144,1.0938853 0.401092,0.455786 0.692795,1.002729 0.875109,1.640829 0.200546,0.619869 0.300819,1.294432 0.30082,2.023689 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Monofonto;-inkscape-font-specification:Monofonto;fill:#666666;fill-opacity:1;stroke-width:3.4183929px"
+ id="path855" /></g><circle
+ style="fill:#666666"
+ cx="-26.38899"
+ cy="25.466606"
+ r="1.8"
+ id="circle6-6" /></g></svg> \ No newline at end of file
diff --git a/application/resources/pe_blue/scalable/worlds.svg b/application/resources/pe_blue/scalable/worlds.svg
new file mode 100644
index 00000000..1670c035
--- /dev/null
+++ b/application/resources/pe_blue/scalable/worlds.svg
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xml:space="preserve"
+ enable-background="new 0 0 32 32"
+ viewBox="0 0 32 32"
+ y="0px"
+ x="0px"
+ id="Calque_1"
+ version="1.1"><metadata
+ id="metadata45"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs43" /><path
+ id="path2"
+ d="M26,32H6c-3.3,0-6-2.7-6-6V6c0-3.3,2.7-6,6-6h20c3.3,0,6,2.7,6,6 v20C32,29.3,29.3,32,26,32z"
+ fill="#3366CC"
+ clip-rule="evenodd"
+ fill-rule="evenodd" /><path
+ fill="#DAEEFF"
+ fill-rule="evenodd"
+ clip-rule="evenodd"
+ id="path4"
+ d="M28,6c0-1.1-0.9-2-2-2H6C4.9,4,4,4.9,4,6v20c0,1.1,0.9,2,2,2h20 c1.1,0,2-0.9,2-2V6z" /><g
+ id="g10" /><g
+ id="g12" /><g
+ id="g14" /><g
+ id="g16" /><g
+ id="g18" /><g
+ id="g20" /><g
+ id="g22" /><g
+ id="g24" /><g
+ id="g26" /><g
+ id="g28" /><g
+ id="g30" /><g
+ id="g32" /><g
+ id="g34" /><g
+ id="g36" /><g
+ id="g38" /><g
+ transform="rotate(29.970903,16,16)"
+ id="g881"><ellipse
+ ry="8.9473686"
+ rx="8.9473696"
+ cy="16"
+ cx="16"
+ id="path845"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#666666;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /><ellipse
+ ry="8.9473686"
+ rx="3.4915254"
+ cy="15.947369"
+ cx="16"
+ id="path845-3"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#666666;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /><path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 8.1848294,12.430327 C 12.570183,14.790801 20.250652,13.785896 22.94338,12"
+ id="path870" /><path
+ id="path872"
+ d="M 8.2166335,20.492522 C 12.601987,18.132048 21.148735,17.776739 23.841463,19.562635"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /></g></svg> \ No newline at end of file
diff --git a/application/resources/pe_colored/pe_colored.qrc b/application/resources/pe_colored/pe_colored.qrc
index 7de8d5ab..588e3ac0 100644
--- a/application/resources/pe_colored/pe_colored.qrc
+++ b/application/resources/pe_colored/pe_colored.qrc
@@ -10,6 +10,7 @@
<file>scalable/copy.svg</file>
<file>scalable/coremods.svg</file>
<file>scalable/externaltools.svg</file>
+ <file>scalable/help.svg</file>
<file>scalable/instance-settings.svg</file>
<file>scalable/jarmods.svg</file>
<file>scalable/java.svg</file>
@@ -31,5 +32,6 @@
<file>scalable/status-good.svg</file>
<file>scalable/status-yellow.svg</file>
<file>scalable/viewfolder.svg</file>
+ <file>scalable/worlds.svg</file>
</qresource>
</RCC>
diff --git a/application/resources/pe_colored/scalable/help.svg b/application/resources/pe_colored/scalable/help.svg
new file mode 100644
index 00000000..c1ee5258
--- /dev/null
+++ b/application/resources/pe_colored/scalable/help.svg
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xml:space="preserve"
+ enable-background="new 0 0 32 32"
+ viewBox="0 0 32 32"
+ y="0px"
+ x="0px"
+ id="Calque_1"
+ version="1.1"><metadata
+ id="metadata23"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs21" /><circle
+ id="circle2"
+ r="12"
+ cy="16"
+ cx="16"
+ fill="#F2F2F2" /><g
+ id="g16"><path
+ id="path10"
+ d="M16,4c-4,0-7.6,2-9.7,5C4.8,11,4,13.4,4,16c0,6.6,5.4,12,12,12c6.6,0,12-5.4,12-12c0-2.6-0.8-5-2.3-7 C23.6,6,20,4,16,4z"
+ fill="none" /><path
+ id="path12"
+ d="M16,4c4,0,7.6,2,9.7,5h4.6c-2.6-5.3-8-9-14.4-9S4.2,3.7,1.6,9h4.6C8.4,6,12,4,16,4z"
+ fill="#39B54A" /><path
+ id="path14"
+ d="M32,16L32,16c0-2.6-0.6-4.9-1.6-7h-4.6c1.4,2,2.3,4.4,2.3,7c0,6.6-5.4,12-12,12C9.4,28,4,22.6,4,16 c0-2.6,0.8-5,2.3-7H1.6c-1,2.1-1.6,4.5-1.6,7c0,8.8,7.2,16,16,16h0C24.8,32,32,24.9,32,16z"
+ fill="#8C6239" /></g><g
+ transform="translate(41.863574,-2.0092638)"
+ id="g861"><g
+ aria-label="?"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.34714317px;line-height:85.45981598px;font-family:'Nimbus Sans L';-inkscape-font-specification:'Nimbus Sans L';letter-spacing:0px;word-spacing:0px;fill:#666666;fill-opacity:1;stroke:none;stroke-width:3.4183929px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="text832"><path
+ d="m -20.968435,13.920532 c 0,0.6381 -0.07293,1.239737 -0.218777,1.804911 -0.145852,0.565174 -0.401092,1.066538 -0.76572,1.504093 -0.401092,0.492249 -0.774836,0.902456 -1.121233,1.230621 -0.346397,0.328166 -0.656332,0.6381 -0.929803,0.929803 -0.25524,0.273471 -0.464902,0.556059 -0.628985,0.847762 -0.145851,0.291703 -0.218777,0.656331 -0.218777,1.093885 v 0.38286 h -3.144921 V 20.72997 c 0,-0.601637 0.136736,-1.221505 0.410207,-1.859605 0.273471,-0.656332 0.756604,-1.285316 1.449399,-1.886953 0.346397,-0.309935 0.638099,-0.583406 0.875108,-0.820415 0.237009,-0.25524 0.428439,-0.492248 0.57429,-0.711025 0.145851,-0.237009 0.246124,-0.483133 0.300819,-0.738373 0.05469,-0.273471 0.08204,-0.57429 0.08204,-0.902456 0,-0.528711 -0.12762,-0.984497 -0.38286,-1.367357 -0.237009,-0.401091 -0.656331,-0.601637 -1.257968,-0.601637 -1.057423,0 -1.640829,0.692794 -1.750218,2.078383 h -3.06288 c 0.01823,-0.747489 0.145853,-1.431167 0.38286,-2.051036 0.237009,-0.6381 0.565175,-1.185043 0.984498,-1.640829 0.419323,-0.474017 0.920687,-0.8386455 1.504092,-1.0938855 0.601637,-0.25524 1.2762,-0.38286 2.023689,-0.38286 0.838646,0 1.567903,0.1367357 2.187771,0.4102072 0.619869,0.25524 1.130349,0.6198684 1.53144,1.0938853 0.401092,0.455786 0.692795,1.002729 0.875109,1.640829 0.200546,0.619869 0.300819,1.294432 0.30082,2.023689 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Monofonto;-inkscape-font-specification:Monofonto;fill:#666666;fill-opacity:1;stroke-width:3.4183929px"
+ id="path855" /></g><circle
+ style="fill:#666666"
+ cx="-26.38899"
+ cy="25.466606"
+ r="1.8"
+ id="circle6-6" /></g></svg> \ No newline at end of file
diff --git a/application/resources/pe_colored/scalable/worlds.svg b/application/resources/pe_colored/scalable/worlds.svg
new file mode 100644
index 00000000..087ba7c9
--- /dev/null
+++ b/application/resources/pe_colored/scalable/worlds.svg
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xml:space="preserve"
+ enable-background="new 0 0 32 32"
+ viewBox="0 0 32 32"
+ y="0px"
+ x="0px"
+ id="Calque_1"
+ version="1.1"><metadata
+ id="metadata19"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs17" /><g
+ id="g6"><path
+ id="path2"
+ d="M26,0H6C2.7,0,0,2.7,0,6v3h32V6C32,2.7,29.3,0,26,0z"
+ fill="#39B54A" /><path
+ id="path4"
+ d="M0,26c0,3.3,2.7,6,6,6h20c3.3,0,6-2.7,6-6V9H0V26z"
+ fill="#8C6239" /></g><path
+ fill="#F2F2F2"
+ fill-rule="evenodd"
+ clip-rule="evenodd"
+ id="path8"
+ d="M28,6c0-1.1-0.9-2-2-2H6C4.9,4,4,4.9,4,6v20c0,1.1,0.9,2,2,2h20 c1.1,0,2-0.9,2-2V6z" /><g
+ transform="rotate(29.970903,16,15.973684)"
+ id="g881"><ellipse
+ ry="8.9473686"
+ rx="8.9473696"
+ cy="16"
+ cx="16"
+ id="path845"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#666666;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /><ellipse
+ ry="8.9473686"
+ rx="3.4915254"
+ cy="15.947369"
+ cx="16"
+ id="path845-3"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#666666;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /><path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 8.1848294,12.430327 C 12.570183,14.790801 20.250652,13.785896 22.94338,12"
+ id="path870" /><path
+ id="path872"
+ d="M 8.2166335,20.492522 C 12.601987,18.132048 21.148735,17.776739 23.841463,19.562635"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /></g></svg> \ No newline at end of file
diff --git a/application/resources/pe_dark/pe_dark.qrc b/application/resources/pe_dark/pe_dark.qrc
index cafc2559..3543f590 100644
--- a/application/resources/pe_dark/pe_dark.qrc
+++ b/application/resources/pe_dark/pe_dark.qrc
@@ -10,6 +10,7 @@
<file>scalable/copy.svg</file>
<file>scalable/coremods.svg</file>
<file>scalable/externaltools.svg</file>
+ <file>scalable/help.svg</file>
<file>scalable/instance-settings.svg</file>
<file>scalable/jarmods.svg</file>
<file>scalable/java.svg</file>
@@ -31,5 +32,6 @@
<file>scalable/status-good.svg</file>
<file>scalable/status-yellow.svg</file>
<file>scalable/viewfolder.svg</file>
+ <file>scalable/worlds.svg</file>
</qresource>
</RCC>
diff --git a/application/resources/pe_dark/scalable/help.svg b/application/resources/pe_dark/scalable/help.svg
new file mode 100644
index 00000000..2a1518ae
--- /dev/null
+++ b/application/resources/pe_dark/scalable/help.svg
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xml:space="preserve"
+ enable-background="new 0 0 32 32"
+ viewBox="0 0 32 32"
+ y="0px"
+ x="0px"
+ id="Calque_1"
+ version="1.1"><metadata
+ id="metadata17"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs15" /><g
+ id="g10"><path
+ id="path8"
+ d="M16,32C7.2,32,0,24.8,0,16C0,7.2,7.2,0,16,0c8.8,0,16,7.2,16,16C32,24.8,24.8,32,16,32L16,32z M16,4C9.4,4,4,9.4,4,16 s5.4,12,12,12s12-5.4,12-12S22.6,4,16,4z" /><g
+ transform="translate(41.863574,-2.0092638)"
+ id="g861"><g
+ aria-label="?"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.34714317px;line-height:85.45981598px;font-family:'Nimbus Sans L';-inkscape-font-specification:'Nimbus Sans L';letter-spacing:0px;word-spacing:0px;fill:#666666;fill-opacity:1;stroke:none;stroke-width:3.4183929px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="text832"><path
+ d="m -20.968435,13.920532 c 0,0.6381 -0.07293,1.239737 -0.218777,1.804911 -0.145852,0.565174 -0.401092,1.066538 -0.76572,1.504093 -0.401092,0.492249 -0.774836,0.902456 -1.121233,1.230621 -0.346397,0.328166 -0.656332,0.6381 -0.929803,0.929803 -0.25524,0.273471 -0.464902,0.556059 -0.628985,0.847762 -0.145851,0.291703 -0.218777,0.656331 -0.218777,1.093885 v 0.38286 h -3.144921 V 20.72997 c 0,-0.601637 0.136736,-1.221505 0.410207,-1.859605 0.273471,-0.656332 0.756604,-1.285316 1.449399,-1.886953 0.346397,-0.309935 0.638099,-0.583406 0.875108,-0.820415 0.237009,-0.25524 0.428439,-0.492248 0.57429,-0.711025 0.145851,-0.237009 0.246124,-0.483133 0.300819,-0.738373 0.05469,-0.273471 0.08204,-0.57429 0.08204,-0.902456 0,-0.528711 -0.12762,-0.984497 -0.38286,-1.367357 -0.237009,-0.401091 -0.656331,-0.601637 -1.257968,-0.601637 -1.057423,0 -1.640829,0.692794 -1.750218,2.078383 h -3.06288 c 0.01823,-0.747489 0.145853,-1.431167 0.38286,-2.051036 0.237009,-0.6381 0.565175,-1.185043 0.984498,-1.640829 0.419323,-0.474017 0.920687,-0.8386455 1.504092,-1.0938855 0.601637,-0.25524 1.2762,-0.38286 2.023689,-0.38286 0.838646,0 1.567903,0.1367357 2.187771,0.4102072 0.619869,0.25524 1.130349,0.6198684 1.53144,1.0938853 0.401092,0.455786 0.692795,1.002729 0.875109,1.640829 0.200546,0.619869 0.300819,1.294432 0.30082,2.023689 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Monofonto;-inkscape-font-specification:Monofonto;fill:#666666;fill-opacity:1;stroke-width:3.4183929px"
+ id="path855" /></g><circle
+ style="fill:#666666"
+ cx="-26.38899"
+ cy="25.466606"
+ r="1.8"
+ id="circle6-6" /></g></g></svg> \ No newline at end of file
diff --git a/application/resources/pe_dark/scalable/worlds.svg b/application/resources/pe_dark/scalable/worlds.svg
new file mode 100644
index 00000000..2b01070f
--- /dev/null
+++ b/application/resources/pe_dark/scalable/worlds.svg
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xml:space="preserve"
+ enable-background="new 0 0 32 32"
+ viewBox="0 0 32 32"
+ y="0px"
+ x="0px"
+ id="Calque_1"
+ version="1.1"><metadata
+ id="metadata45"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs43" /><path
+ id="path2"
+ d="M26,32H6c-3.3,0-6-2.7-6-6V6c0-3.3,2.7-6,6-6h20c3.3,0,6,2.7,6,6v20 C32,29.3,29.3,32,26,32z"
+ clip-rule="evenodd"
+ fill-rule="evenodd" /><path
+ id="path4"
+ d="M28,6c0-1.1-0.9-2-2-2H6C4.9,4,4,4.9,4,6v20c0,1.1,0.9,2,2,2h20 c1.1,0,2-0.9,2-2V6z"
+ fill="#F2F2F2"
+ clip-rule="evenodd"
+ fill-rule="evenodd" /><g
+ id="g10" /><g
+ id="g12" /><g
+ id="g14" /><g
+ id="g16" /><g
+ id="g18" /><g
+ id="g20" /><g
+ id="g22" /><g
+ id="g24" /><g
+ id="g26" /><g
+ id="g28" /><g
+ id="g30" /><g
+ id="g32" /><g
+ id="g34" /><g
+ id="g36" /><g
+ id="g38" /><g
+ style="stroke:#666666;stroke-opacity:1"
+ transform="rotate(29.970903,16,16)"
+ id="g881"><ellipse
+ ry="8.9473686"
+ rx="8.9473696"
+ cy="16"
+ cx="16"
+ id="path845"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#666666;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /><ellipse
+ ry="8.9473686"
+ rx="3.4915254"
+ cy="15.947369"
+ cx="16"
+ id="path845-3"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#666666;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /><path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 8.1848294,12.430327 C 12.570183,14.790801 20.250652,13.785896 22.94338,12"
+ id="path870" /><path
+ id="path872"
+ d="M 8.2166335,20.492522 C 12.601987,18.132048 21.148735,17.776739 23.841463,19.562635"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /></g></svg> \ No newline at end of file
diff --git a/application/resources/pe_light/pe_light.qrc b/application/resources/pe_light/pe_light.qrc
index 53d0890b..f83d6eba 100644
--- a/application/resources/pe_light/pe_light.qrc
+++ b/application/resources/pe_light/pe_light.qrc
@@ -10,6 +10,7 @@
<file>scalable/copy.svg</file>
<file>scalable/coremods.svg</file>
<file>scalable/externaltools.svg</file>
+ <file>scalable/help.svg</file>
<file>scalable/instance-settings.svg</file>
<file>scalable/jarmods.svg</file>
<file>scalable/java.svg</file>
@@ -31,6 +32,7 @@
<file>scalable/status-good.svg</file>
<file>scalable/status-yellow.svg</file>
<file>scalable/viewfolder.svg</file>
+ <file>scalable/worlds.svg</file>
</qresource>
</RCC>
diff --git a/application/resources/pe_light/scalable/help.svg b/application/resources/pe_light/scalable/help.svg
new file mode 100644
index 00000000..f820c679
--- /dev/null
+++ b/application/resources/pe_light/scalable/help.svg
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xml:space="preserve"
+ enable-background="new 0 0 32 32"
+ viewBox="0 0 32 32"
+ y="0px"
+ x="0px"
+ id="Calque_1"
+ version="1.1"><metadata
+ id="metadata17"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs15" /><g
+ id="g10"><path
+ id="path8"
+ d="M16,32C7.2,32,0,24.8,0,16C0,7.2,7.2,0,16,0c8.8,0,16,7.2,16,16C32,24.8,24.8,32,16,32L16,32z M16,4 C9.4,4,4,9.4,4,16s5.4,12,12,12s12-5.4,12-12S22.6,4,16,4z"
+ fill="#F2F2F2" /></g><g
+ style="fill:#f2f2f2;fill-opacity:1"
+ transform="translate(41.863574,-2.0092638)"
+ id="g861"><g
+ aria-label="?"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.34714317px;line-height:85.45981598px;font-family:'Nimbus Sans L';-inkscape-font-specification:'Nimbus Sans L';letter-spacing:0px;word-spacing:0px;fill:#f2f2f2;fill-opacity:1;stroke:none;stroke-width:3.4183929px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="text832"><path
+ d="m -20.968435,13.920532 c 0,0.6381 -0.07293,1.239737 -0.218777,1.804911 -0.145852,0.565174 -0.401092,1.066538 -0.76572,1.504093 -0.401092,0.492249 -0.774836,0.902456 -1.121233,1.230621 -0.346397,0.328166 -0.656332,0.6381 -0.929803,0.929803 -0.25524,0.273471 -0.464902,0.556059 -0.628985,0.847762 -0.145851,0.291703 -0.218777,0.656331 -0.218777,1.093885 v 0.38286 h -3.144921 V 20.72997 c 0,-0.601637 0.136736,-1.221505 0.410207,-1.859605 0.273471,-0.656332 0.756604,-1.285316 1.449399,-1.886953 0.346397,-0.309935 0.638099,-0.583406 0.875108,-0.820415 0.237009,-0.25524 0.428439,-0.492248 0.57429,-0.711025 0.145851,-0.237009 0.246124,-0.483133 0.300819,-0.738373 0.05469,-0.273471 0.08204,-0.57429 0.08204,-0.902456 0,-0.528711 -0.12762,-0.984497 -0.38286,-1.367357 -0.237009,-0.401091 -0.656331,-0.601637 -1.257968,-0.601637 -1.057423,0 -1.640829,0.692794 -1.750218,2.078383 h -3.06288 c 0.01823,-0.747489 0.145853,-1.431167 0.38286,-2.051036 0.237009,-0.6381 0.565175,-1.185043 0.984498,-1.640829 0.419323,-0.474017 0.920687,-0.8386455 1.504092,-1.0938855 0.601637,-0.25524 1.2762,-0.38286 2.023689,-0.38286 0.838646,0 1.567903,0.1367357 2.187771,0.4102072 0.619869,0.25524 1.130349,0.6198684 1.53144,1.0938853 0.401092,0.455786 0.692795,1.002729 0.875109,1.640829 0.200546,0.619869 0.300819,1.294432 0.30082,2.023689 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Monofonto;-inkscape-font-specification:Monofonto;fill:#f2f2f2;fill-opacity:1;stroke-width:3.4183929px"
+ id="path855" /></g><circle
+ style="fill:#f2f2f2;fill-opacity:1"
+ cx="-26.38899"
+ cy="25.466606"
+ r="1.8"
+ id="circle6-6" /></g></svg> \ No newline at end of file
diff --git a/application/resources/pe_light/scalable/worlds.svg b/application/resources/pe_light/scalable/worlds.svg
new file mode 100644
index 00000000..bf4c21a3
--- /dev/null
+++ b/application/resources/pe_light/scalable/worlds.svg
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xml:space="preserve"
+ enable-background="new 0 0 32 32"
+ viewBox="0 0 32 32"
+ y="0px"
+ x="0px"
+ id="Calque_1"
+ version="1.1"><metadata
+ id="metadata45"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs43" /><path
+ id="path2"
+ d="M26,32H6c-3.3,0-6-2.7-6-6V6c0-3.3,2.7-6,6-6h20c3.3,0,6,2.7,6,6 v20C32,29.3,29.3,32,26,32z"
+ fill="#F2F2F2"
+ clip-rule="evenodd"
+ fill-rule="evenodd" /><path
+ id="path4"
+ d="M28,6c0-1.1-0.9-2-2-2H6C4.9,4,4,4.9,4,6v20c0,1.1,0.9,2,2,2h20 c1.1,0,2-0.9,2-2V6z"
+ fill="#4D4D4D"
+ clip-rule="evenodd"
+ fill-rule="evenodd" /><g
+ id="g10" /><g
+ id="g12" /><g
+ id="g14" /><g
+ id="g16" /><g
+ id="g18" /><g
+ id="g20" /><g
+ id="g22" /><g
+ id="g24" /><g
+ id="g26" /><g
+ id="g28" /><g
+ id="g30" /><g
+ id="g32" /><g
+ id="g34" /><g
+ id="g36" /><g
+ id="g38" /><g
+ style="stroke:#ffffff;stroke-opacity:1"
+ transform="rotate(29.970903,16,16)"
+ id="g881"><ellipse
+ ry="8.9473686"
+ rx="8.9473696"
+ cy="16"
+ cx="16"
+ id="path845"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /><ellipse
+ ry="8.9473686"
+ rx="3.4915254"
+ cy="15.947369"
+ cx="16"
+ id="path845-3"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /><path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 8.1848294,12.430327 C 12.570183,14.790801 20.250652,13.785896 22.94338,12"
+ id="path870" /><path
+ id="path872"
+ d="M 8.2166335,20.492522 C 12.601987,18.132048 21.148735,17.776739 23.841463,19.562635"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /></g></svg> \ No newline at end of file
diff --git a/application/resources/sources/multimc-discord.svg b/application/resources/sources/multimc-discord.svg
new file mode 100644
index 00000000..c3c73044
--- /dev/null
+++ b/application/resources/sources/multimc-discord.svg
@@ -0,0 +1,265 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ id="svg4427"
+ height="68.26667"
+ width="68.26667">
+ <defs
+ id="defs4429">
+ <linearGradient
+ id="linearGradient4809">
+ <stop
+ id="stop4805"
+ offset="0"
+ style="stop-color:#98c867;stop-opacity:1" />
+ <stop
+ id="stop4807"
+ offset="1"
+ style="stop-color:#5c9a33;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5668">
+ <stop
+ style="stop-color:#75b54b;stop-opacity:1;"
+ offset="0"
+ id="stop5670" />
+ <stop
+ style="stop-color:#75b54b;stop-opacity:0.6"
+ offset="1"
+ id="stop5672" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5084">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.8"
+ offset="0"
+ id="stop5086" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0.35"
+ offset="1"
+ id="stop5088" />
+ </linearGradient>
+ <linearGradient
+ gradientTransform="translate(-0.01532073,-0.00938002)"
+ gradientUnits="userSpaceOnUse"
+ y2="61.773685"
+ x2="50.506943"
+ y1="28.510933"
+ x1="6.7342591"
+ id="linearGradient5072"
+ xlink:href="#linearGradient5668" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="82.973114"
+ x2="44.097023"
+ y1="9.7948904"
+ x1="14.312115"
+ id="linearGradient5082"
+ xlink:href="#linearGradient5084" />
+ <linearGradient
+ y2="61.773685"
+ x2="50.506943"
+ y1="28.510933"
+ x1="6.7342591"
+ gradientTransform="translate(-0.01532073,-0.00938002)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3281"
+ xlink:href="#linearGradient5668" />
+ <linearGradient
+ y2="61.773685"
+ x2="50.506943"
+ y1="28.510933"
+ x1="6.7342591"
+ gradientTransform="translate(-0.01532073,-0.00938002)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3283"
+ xlink:href="#linearGradient5668" />
+ <linearGradient
+ y2="61.773685"
+ x2="50.506943"
+ y1="28.510933"
+ x1="6.7342591"
+ gradientTransform="matrix(1.2671525,0,0,0.89790119,-0.01941371,-0.00842234)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3286"
+ xlink:href="#linearGradient5668" />
+ <linearGradient
+ y2="82.973114"
+ x2="44.097023"
+ y1="9.7948904"
+ x1="14.312115"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3288"
+ xlink:href="#linearGradient5084" />
+ <linearGradient
+ y2="82.973114"
+ x2="44.097023"
+ y1="9.7948904"
+ x1="14.312115"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3290"
+ xlink:href="#linearGradient5084" />
+ <linearGradient
+ gradientTransform="scale(1.2671525,0.89790119)"
+ y2="82.973114"
+ x2="44.097023"
+ y1="9.7948904"
+ x1="14.312115"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3293"
+ xlink:href="#linearGradient5084" />
+ <linearGradient
+ id="linearGradient5580">
+ <stop
+ id="stop5576"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:0.0627451" />
+ <stop
+ id="stop5578"
+ offset="1"
+ style="stop-color:#322217;stop-opacity:0.58823532" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3999">
+ <stop
+ style="stop-color:#a3704b;stop-opacity:1"
+ offset="0"
+ id="stop3995" />
+ <stop
+ style="stop-color:#6a4a33;stop-opacity:1"
+ offset="1"
+ id="stop3997" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2727">
+ <stop
+ style="stop-color:#966c4a;stop-opacity:1"
+ offset="0"
+ id="stop2723" />
+ <stop
+ style="stop-color:#593d29;stop-opacity:1"
+ offset="1"
+ id="stop2725" />
+ </linearGradient>
+ <linearGradient
+ y2="97.065842"
+ x2="86.415741"
+ y1="33.80484"
+ x1="36.546478"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2050"
+ xlink:href="#linearGradient2727" />
+ <radialGradient
+ r="29.866665"
+ fy="34.133335"
+ fx="34.133331"
+ cy="34.133335"
+ cx="34.133331"
+ gradientTransform="matrix(1.1428572,0,0,1.1428572,-4.8771039,-4.8772393)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient2052"
+ xlink:href="#linearGradient3999" />
+ <linearGradient
+ y2="38.400913"
+ x2="38.400005"
+ y1="29.867579"
+ x1="29.866674"
+ gradientTransform="translate(77.635668,-7.276299)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2140"
+ xlink:href="#linearGradient5580" />
+ <linearGradient
+ y2="82.973114"
+ x2="44.097023"
+ y1="9.7948904"
+ x1="14.312115"
+ gradientTransform="matrix(1.2671525,0,0,0.89790119,-0.82864077,-1.0012743)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4790"
+ xlink:href="#linearGradient5084" />
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.7500268,0.1250019,-0.01781176,0.24936465,95.393964,18.110151)"
+ r="34.132812"
+ fy="-34.134373"
+ fx="-42.66758"
+ cy="-34.134373"
+ cx="-42.66758"
+ id="radialGradient4803"
+ xlink:href="#linearGradient4809" />
+ </defs>
+ <metadata
+ id="metadata4432">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1">
+ <g
+ transform="translate(9.113e-4,0.00104183)"
+ id="g2048">
+ <rect
+ y="3.0270508e-06"
+ x="-1.3322676e-15"
+ height="68.26667"
+ width="68.26667"
+ id="rect2026"
+ style="fill:url(#linearGradient2050);fill-opacity:1;stroke:none;stroke-width:17.06666756"
+ ry="8.5333338"
+ rx="8.5333338" />
+ <rect
+ ry="0"
+ style="fill:url(#radialGradient2052);fill-opacity:1;stroke:none;stroke-width:17.06666946"
+ id="rect2028"
+ width="68.26667"
+ height="68.26667"
+ x="-0.00091432704"
+ y="-0.0010418301"
+ rx="0" />
+ <path
+ style="opacity:0.6;fill:#593d29;fill-opacity:1;stroke:none;stroke-width:17.06666756"
+ d="m 4.2669272,4.2645856 -9.11e-4,8.5333334 h 4.267577 v 4.267579 h 8.5332038 v 4.265625 h 4.265625 V 8.5322946 H 25.6 v 8.5332034 h 4.265625 v -4.267579 h 4.267578 v 8.533204 h 4.265625 v -4.265625 h 4.267578 v 4.265625 h 4.267579 v -4.265625 h 4.265624 v -4.267579 h 4.267579 v 4.267579 h 8.533203 l -1.3e-4,-12.8009124 z"
+ id="path4811" />
+ <path
+ id="path4794"
+ d="m -9.113e-4,-0.0010388 6.52e-4,8.5324211 v 4.2675787 h 4.265625 V 8.5313823 c 0,-0.521698 0.105433,-1.01339 0.27539,-1.47461 -0.169616,0.460814 -0.27539,0.953462 -0.27539,1.47461 h 4.2675785 v 4.2675787 h 4.2656248 4.267578 v 4.265625 h 4.265625 V 12.798961 8.5313823 4.2657573 h 4.267578 v 4.265625 4.2675787 h 4.265625 V 8.5313823 h 4.267578 v 4.2675787 4.265625 h 4.265625 v -4.265625 h 4.267578 v 4.265625 h 4.267579 v -4.265625 h 4.265624 V 8.5313823 h 4.267579 v 4.2675787 h 4.265625 4.267578 V 8.5313823 h 4.265625 l 3.9e-4,-8.5324211 z m 5.5143245,5.5128891 c -0.318089,0.317888 -0.570428,0.695824 -0.7753915,1.101563 0.2048795,-0.405231 0.4576385,-0.784012 0.7753915,-1.101563 z"
+ style="fill:url(#radialGradient4803);fill-opacity:1;stroke:none;stroke-width:17.06666756" />
+ </g>
+ <g
+ id="g1092">
+ <path
+ d="m 38.886673,44.940882 c -0.974277,-0.801673 -2.231353,-2.137814 -3.771231,-4.008427 -2.105641,2.672298 -4.085536,4.598569 -5.939688,5.778816 -2.325625,1.425227 -5.295467,2.137836 -8.909534,2.137828 -4.242656,8e-6 -7.762467,-1.124578 -10.5594458,-3.37376 C 6.7526311,43.114834 5.275567,39.986037 5.2755773,36.088937 5.275567,32.347763 6.7526311,29.207831 9.7067742,26.669132 12.346618,24.419991 15.897857,23.295407 20.360501,23.295373 c 2.294138,3.4e-5 4.289747,0.334069 5.986829,1.002107 1.979863,0.73491 3.645488,1.737016 4.996881,3.00632 1.257039,1.135751 2.514115,2.471891 3.771231,4.008428 2.105563,-2.672257 4.085457,-4.598527 5.939689,-5.778816 2.325544,-1.425186 5.295385,-2.137794 8.909533,-2.137828 4.242577,3.4e-5 7.762388,1.124618 10.559447,3.37376 2.954063,2.360546 4.431127,5.489343 4.431197,9.386401 -7e-5,3.741216 -1.477134,6.881147 -4.431197,9.419806 -2.639925,2.24918 -6.191163,3.373767 -10.653727,3.373758 -2.294219,9e-6 -4.289826,-0.334026 -5.98683,-1.002106 -1.697101,-0.601255 -3.362726,-1.603361 -4.996881,-3.006321 M 19.747676,44.473233 c 5.185412,1.1e-5 9.333763,-2.672271 12.445062,-8.016856 -3.991253,-5.834464 -8.139602,-8.751705 -12.445062,-8.751733 -3.142715,2.8e-5 -5.515446,0.801713 -7.118198,2.405057 -1.728498,1.71474 -2.592737,3.707818 -2.592722,5.979236 -1.5e-5,2.494152 0.864224,4.509499 2.592722,6.046046 1.759887,1.558846 4.132618,2.338261 7.118198,2.33825 M 50.483209,27.77145 c -4.682663,2.9e-5 -8.831013,2.672312 -12.445062,8.016856 3.959745,5.834503 8.108095,8.751746 12.445062,8.751733 3.142633,1.3e-5 5.515364,-0.801671 7.118198,-2.405056 1.728416,-1.714701 2.592656,-3.707778 2.592722,-5.979238 -6.6e-5,-2.49411 -0.864306,-4.509456 -2.592722,-6.046044 -1.759968,-1.558805 -4.132699,-2.338222 -7.118198,-2.338251"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:76.18933868px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient4790);fill-opacity:1;stroke:none;stroke-width:1.06666672;opacity:0.5"
+ id="path4786" />
+ <path
+ id="path3279"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:76.18933868px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient3293);fill-opacity:1;stroke:none;stroke-width:1.06666672;opacity:0.5"
+ d="m 39.715314,45.942156 c -0.974277,-0.801673 -2.231353,-2.137814 -3.771231,-4.008427 -2.105641,2.672298 -4.085536,4.598569 -5.939688,5.778816 -2.325625,1.425227 -5.295467,2.137836 -8.909534,2.137828 -4.242656,8e-6 -7.762467,-1.124578 -10.559446,-3.37376 -2.9541431,-2.360505 -4.4312072,-5.489302 -4.4311969,-9.386402 -1.03e-5,-3.741174 1.4770538,-6.881106 4.4311969,-9.419805 2.639844,-2.249141 6.191083,-3.373725 10.653727,-3.373759 2.294138,3.4e-5 4.289747,0.334069 5.986829,1.002107 1.979863,0.73491 3.645488,1.737016 4.996881,3.00632 1.257039,1.135751 2.514115,2.471891 3.771231,4.008428 2.105563,-2.672257 4.085457,-4.598527 5.939689,-5.778816 2.325544,-1.425186 5.295385,-2.137794 8.909533,-2.137828 4.242577,3.4e-5 7.762388,1.124618 10.559447,3.37376 2.954063,2.360546 4.431127,5.489343 4.431197,9.386401 -7e-5,3.741216 -1.477134,6.881147 -4.431197,9.419806 -2.639925,2.24918 -6.191163,3.373767 -10.653727,3.373758 -2.294219,9e-6 -4.289826,-0.334026 -5.98683,-1.002106 -1.697101,-0.601255 -3.362726,-1.603361 -4.996881,-3.006321 M 20.576317,45.474507 c 5.185412,1.1e-5 9.333763,-2.672271 12.445062,-8.016856 -3.991253,-5.834464 -8.139602,-8.751705 -12.445062,-8.751733 -3.142715,2.8e-5 -5.515446,0.801713 -7.118198,2.405057 -1.728498,1.71474 -2.592737,3.707818 -2.592722,5.979236 -1.5e-5,2.494152 0.864224,4.509499 2.592722,6.046046 1.759887,1.558846 4.132618,2.338261 7.118198,2.33825 M 51.31185,28.772724 c -4.682663,2.9e-5 -8.831013,2.672312 -12.445062,8.016856 3.959745,5.834503 8.108095,8.751746 12.445062,8.751733 3.142633,1.3e-5 5.515364,-0.801671 7.118198,-2.405056 1.728416,-1.714701 2.592656,-3.707778 2.592722,-5.979238 -6.6e-5,-2.49411 -0.864306,-4.509456 -2.592722,-6.046044 C 56.67008,29.55217 54.297349,28.772753 51.31185,28.772724" />
+ <path
+ id="path3272"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:76.18933868px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient3286);fill-opacity:1;stroke:none;stroke-width:1.06666672"
+ d="m 37.904564,42.951873 c -0.974278,-0.801672 -2.231352,-2.137814 -3.771231,-4.008428 -2.105642,2.672298 -4.085537,4.598568 -5.939688,5.778817 -2.325625,1.425227 -5.295466,2.137836 -8.909534,2.137828 -4.242656,8e-6 -7.762467,-1.124577 -10.5594464,-3.37376 -2.9541428,-2.360505 -4.4312068,-5.489302 -4.4311963,-9.386401 -1.05e-5,-3.741175 1.4770535,-6.881107 4.4311963,-9.419805 2.6398444,-2.249142 6.1910824,-3.373727 10.6537284,-3.37376 2.294137,3.3e-5 4.289745,0.334068 5.986829,1.002107 1.979863,0.734909 3.645487,1.737016 4.99688,3.00632 1.257039,1.13575 2.514116,2.471891 3.771231,4.008428 2.105562,-2.672257 4.085456,-4.598528 5.939689,-5.778817 2.325544,-1.425185 5.295387,-2.137795 8.909534,-2.137828 4.242576,3.3e-5 7.762387,1.12462 10.559446,3.373761 2.954062,2.360545 4.431127,5.489343 4.431197,9.386401 -7e-5,3.741216 -1.477135,6.881148 -4.431197,9.419805 -2.639924,2.249182 -6.191164,3.373767 -10.653728,3.37376 -2.294217,7e-6 -4.289826,-0.334028 -5.986828,-1.002107 -1.697101,-0.601254 -3.362727,-1.603361 -4.996882,-3.006321 m -19.138997,-0.46765 c 5.185412,1.3e-5 9.333762,-2.67227 12.445062,-8.016856 -3.991252,-5.834462 -8.139602,-8.751704 -12.445062,-8.751733 -3.142714,2.9e-5 -5.515444,0.801714 -7.118198,2.405056 -1.7284972,1.714743 -2.5927368,3.707819 -2.5927216,5.979239 -1.52e-5,2.49415 0.8642244,4.509496 2.5927216,6.046045 1.759888,1.558845 4.132618,2.338262 7.118198,2.338249 M 49.5011,25.782442 c -4.682663,2.8e-5 -8.831014,2.672311 -12.445063,8.016855 3.959745,5.834504 8.108096,8.751745 12.445063,8.751733 3.142634,1.2e-5 5.515365,-0.801673 7.118198,-2.405056 1.728417,-1.7147 2.592657,-3.707778 2.592721,-5.979238 -6.4e-5,-2.49411 -0.864304,-4.509456 -2.592721,-6.046046 C 54.85933,26.561886 52.486599,25.78247 49.5011,25.782442" />
+ <path
+ style="font-style:normal;font-weight:normal;font-size:76.18933868px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;opacity:0.3;fill:#ccff00;fill-opacity:1;stroke:none;stroke-width:1.06666672"
+ d="m 19.4,21.166667 c -4.462644,3.3e-5 -8.026822,1.150858 -10.6666667,3.4 -2.9541428,2.538698 -4.4333436,5.658825 -4.4333333,9.4 -1.03e-5,3.897098 1.4791905,7.039495 4.4333333,9.4 -1.622701,-2.044271 -2.433341,-4.51168 -2.4333333,-7.4 -1.03e-5,-3.741175 1.4791905,-6.861302 4.433333,-9.4 2.639845,-2.249142 6.204023,-3.399967 10.666667,-3.4 2.294138,3.3e-5 4.302916,0.365295 6,1.033333 1.979862,0.73491 3.615274,1.730695 4.966667,3 0.06836,0.06177 0.131637,0.137049 0.2,0.2 -0.731813,-0.797005 -1.468213,-1.538822 -2.2,-2.2 -1.351393,-1.269305 -2.986805,-2.26509 -4.966667,-3 -1.697084,-0.668038 -3.705862,-1.0333 -6,-1.033333 z m 29.6,0.1 c -3.614148,3.3e-5 -6.574457,0.74148 -8.9,2.166666 -1.818222,1.157367 -3.923451,3.291388 -5.983333,5.883334 0.618278,0.658774 1.248369,1.377605 1.866666,2.133333 2.105562,-2.672257 4.262434,-4.836378 6.116667,-6.016667 2.325543,-1.425186 5.285852,-2.166633 8.9,-2.166666 4.242576,3.3e-5 7.769607,1.150858 10.566667,3.4 -0.570388,-0.722129 -1.227721,-1.382884 -2,-2 C 56.769607,22.417525 53.242576,21.2667 49,21.266667 Z m 8.866667,8.1 c 0.9092,1.305235 1.366619,2.857751 1.366666,4.666666 -6.5e-5,2.271461 -0.871584,4.285301 -2.6,6 -1.602834,1.603384 -3.957366,2.400012 -7.1,2.4 -2.653707,8e-6 -5.320858,-1.032242 -7.833333,-3.216666 3.136636,3.509305 6.469807,5.216676 9.833333,5.216666 3.142634,1.2e-5 5.497166,-0.796616 7.1,-2.4 1.728416,-1.714699 2.599935,-3.728539 2.6,-6 -6.5e-5,-2.49411 -0.871584,-4.496744 -2.6,-6.033333 -0.24943,-0.220921 -0.49262,-0.443723 -0.766666,-0.633333 z m -26.633334,4.966666 c -3.1113,5.344585 -7.247921,8.033345 -12.433333,8.033334 -2.58055,1e-5 -4.543473,-0.352086 -6.208333,-1.516667 0.348871,0.50642 0.590094,0.752276 1.075,1.183333 1.759888,1.558846 4.147753,2.333345 7.133333,2.333334 5.185412,1.1e-5 9.322033,-2.688749 12.433333,-8.033334 z m 4.933334,6.5 c -0.04103,0.05207 -0.09239,0.08182 -0.133334,0.133334 0.687326,0.744419 1.306949,1.359747 1.833334,1.8 -0.529404,-0.580895 -1.078447,-1.178283 -1.7,-1.933334 z"
+ id="text5100" />
+ <path
+ style="font-style:normal;font-weight:normal;font-size:76.18933868px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;opacity:0.6;fill:#ccff00;fill-opacity:1;stroke:none;stroke-width:1.06666672"
+ d="m 19.730474,21.54714 c -4.462645,3.3e-5 -8.026823,1.150859 -10.6666669,3.4 -2.9541429,2.538699 -4.433344,5.658826 -4.4333333,9.4 -1.07e-5,3.897099 1.4791904,7.039495 4.4333333,9.4 0.042837,0.03444 0.090155,0.06608 0.1333334,0.1 -2.2392086,-2.228193 -3.3666752,-5.040417 -3.3666667,-8.433333 -1.07e-5,-3.741174 1.4791904,-6.861301 4.4333332,-9.4 2.639844,-2.249141 6.204022,-3.399967 10.666667,-3.4 2.294137,3.3e-5 4.302916,0.365295 6,1.033333 1.870874,0.694455 3.42364,1.628367 4.733333,2.8 -0.314265,-0.308986 -0.652406,-0.582729 -0.966667,-0.866666 -1.351393,-1.269305 -2.986804,-2.265091 -4.966666,-3 -1.697084,-0.668039 -3.705863,-1.033301 -6,-1.033334 z m 29.6,0.1 c -3.614149,3.3e-5 -6.574457,0.741481 -8.9,2.166667 -1.813279,1.154221 -3.963039,3.235656 -6.016667,5.816667 0.355649,0.402628 0.711011,0.798625 1.066667,1.233333 2.105561,-2.672257 4.295767,-4.803044 6.15,-5.983333 2.325543,-1.425187 5.285851,-2.166634 8.9,-2.166667 4.22442,3.3e-5 7.742084,1.136734 10.533333,3.366667 -0.36096,-0.367566 -0.745726,-0.696967 -1.166667,-1.033334 -2.797059,-2.249141 -6.32409,-3.399967 -10.566666,-3.4 z m 8.233333,7.333334 c 1.323326,1.449243 1.999942,3.250987 2,5.433333 -6.5e-5,2.27146 -0.871584,4.2853 -2.6,6 -1.602834,1.603383 -3.957366,2.400012 -7.1,2.4 -2.406328,6e-6 -4.776468,-0.90386 -7.066667,-2.7 2.669147,2.483838 5.436929,3.766674 8.266667,3.766667 3.142634,1.1e-5 5.497166,-0.796617 7.1,-2.4 1.728416,-1.7147 2.599935,-3.72854 2.6,-6 -6.5e-5,-2.49411 -0.871584,-4.496745 -2.6,-6.033334 -0.185641,-0.164422 -0.400724,-0.319587 -0.6,-0.466666 z m -26,5.733333 c -3.1113,5.344584 -7.247921,8.033345 -12.433333,8.033333 -2.612382,1.1e-5 -4.759372,-0.60651 -6.433334,-1.8 0.166027,0.176488 0.313947,0.367942 0.5,0.533334 1.759888,1.558845 4.147754,2.333345 7.133334,2.333333 5.185412,1.2e-5 9.322033,-2.688749 12.433333,-8.033333 z m 4.133333,5.566667 c -0.04657,0.05909 -0.08689,0.108298 -0.133333,0.166666 1.038571,1.18897 1.9748,2.169945 2.7,2.766667 0.06249,0.05364 0.137426,0.08086 0.2,0.133333 -0.792178,-0.781249 -1.706288,-1.778539 -2.766667,-3.066666 z"
+ id="text5058-0" />
+ </g>
+ </g>
+</svg>
diff --git a/application/setupwizard/JavaWizardPage.cpp b/application/setupwizard/JavaWizardPage.cpp
index 46b6ee3f..cd2bca46 100644
--- a/application/setupwizard/JavaWizardPage.cpp
+++ b/application/setupwizard/JavaWizardPage.cpp
@@ -17,184 +17,35 @@
#include <sys.h>
#include <QFileDialog>
#include <JavaCommon.h>
+#include "widgets/JavaSettingsWidget.h"
JavaWizardPage::JavaWizardPage(QWidget *parent)
:BaseWizardPage(parent)
{
- m_availableMemory = Sys::getSystemRam() / (1024ull * 1024ull);
-
- goodIcon = MMC->getThemedIcon("status-good");
- yellowIcon = MMC->getThemedIcon("status-yellow");
- badIcon = MMC->getThemedIcon("status-bad");
setupUi();
-
- connect(m_minMemSpinBox, SIGNAL(valueChanged(int)), this, SLOT(memoryValueChanged(int)));
- connect(m_maxMemSpinBox, SIGNAL(valueChanged(int)), this, SLOT(memoryValueChanged(int)));
- connect(m_permGenSpinBox, SIGNAL(valueChanged(int)), this, SLOT(memoryValueChanged(int)));
- connect(m_versionWidget, &VersionSelectWidget::selectedVersionChanged, this, &JavaWizardPage::javaVersionSelected);
- connect(m_javaBrowseBtn, &QPushButton::clicked, this, &JavaWizardPage::on_javaBrowseBtn_clicked);
- connect(m_javaPathTextBox, &QLineEdit::textEdited, this, &JavaWizardPage::javaPathEdited);
- connect(m_javaStatusBtn, &QToolButton::clicked, this, &JavaWizardPage::on_javaStatusBtn_clicked);
}
void JavaWizardPage::setupUi()
{
setObjectName(QStringLiteral("javaPage"));
- m_verticalLayout = new QVBoxLayout(this);
- m_verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
-
- m_versionWidget = new VersionSelectWidget(MMC->javalist().get(), this);
- m_versionWidget->setResizeOn(2);
- m_verticalLayout->addWidget(m_versionWidget);
-
- m_horizontalLayout = new QHBoxLayout();
- m_horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
- m_javaPathTextBox = new QLineEdit(this);
- m_javaPathTextBox->setObjectName(QStringLiteral("javaPathTextBox"));
-
- m_horizontalLayout->addWidget(m_javaPathTextBox);
-
- m_javaBrowseBtn = new QPushButton(this);
- m_javaBrowseBtn->setObjectName(QStringLiteral("javaBrowseBtn"));
- /*
- QSizePolicy sizePolicy2(QSizePolicy::Fixed, QSizePolicy::Fixed);
- sizePolicy2.setHorizontalStretch(0);
- sizePolicy2.setVerticalStretch(0);
- sizePolicy2.setHeightForWidth(m_javaBrowseBtn->sizePolicy().hasHeightForWidth());
- m_javaBrowseBtn->setSizePolicy(sizePolicy2);
- m_javaBrowseBtn->setMaximumSize(QSize(28, 16777215));
- */
- m_horizontalLayout->addWidget(m_javaBrowseBtn);
-
- m_javaStatusBtn = new QToolButton(this);
- m_javaStatusBtn->setIcon(yellowIcon);
- m_horizontalLayout->addWidget(m_javaStatusBtn);
-
- m_verticalLayout->addLayout(m_horizontalLayout);
-
- m_memoryGroupBox = new QGroupBox(this);
- m_memoryGroupBox->setObjectName(QStringLiteral("memoryGroupBox"));
- m_gridLayout_2 = new QGridLayout(m_memoryGroupBox);
- m_gridLayout_2->setObjectName(QStringLiteral("gridLayout_2"));
-
- m_labelMinMem = new QLabel(m_memoryGroupBox);
- m_labelMinMem->setObjectName(QStringLiteral("labelMinMem"));
- m_gridLayout_2->addWidget(m_labelMinMem, 0, 0, 1, 1);
-
- m_minMemSpinBox = new QSpinBox(m_memoryGroupBox);
- m_minMemSpinBox->setObjectName(QStringLiteral("minMemSpinBox"));
- m_minMemSpinBox->setSuffix(QStringLiteral(" MB"));
- m_minMemSpinBox->setMinimum(128);
- m_minMemSpinBox->setMaximum(m_availableMemory);
- m_minMemSpinBox->setSingleStep(128);
- m_labelMinMem->setBuddy(m_minMemSpinBox);
- m_gridLayout_2->addWidget(m_minMemSpinBox, 0, 1, 1, 1);
-
- m_labelMaxMem = new QLabel(m_memoryGroupBox);
- m_labelMaxMem->setObjectName(QStringLiteral("labelMaxMem"));
- m_gridLayout_2->addWidget(m_labelMaxMem, 1, 0, 1, 1);
-
- m_maxMemSpinBox = new QSpinBox(m_memoryGroupBox);
- m_maxMemSpinBox->setObjectName(QStringLiteral("maxMemSpinBox"));
- m_maxMemSpinBox->setSuffix(QStringLiteral(" MB"));
- m_maxMemSpinBox->setMinimum(128);
- m_maxMemSpinBox->setMaximum(m_availableMemory);
- m_maxMemSpinBox->setSingleStep(128);
- m_labelMaxMem->setBuddy(m_maxMemSpinBox);
- m_gridLayout_2->addWidget(m_maxMemSpinBox, 1, 1, 1, 1);
+ QVBoxLayout * layout = new QVBoxLayout(this);
- m_labelPermGen = new QLabel(m_memoryGroupBox);
- m_labelPermGen->setObjectName(QStringLiteral("labelPermGen"));
- m_labelPermGen->setText(QStringLiteral("PermGen:"));
- m_gridLayout_2->addWidget(m_labelPermGen, 2, 0, 1, 1);
- m_labelPermGen->setVisible(false);
-
- m_permGenSpinBox = new QSpinBox(m_memoryGroupBox);
- m_permGenSpinBox->setObjectName(QStringLiteral("permGenSpinBox"));
- m_permGenSpinBox->setSuffix(QStringLiteral(" MB"));
- m_permGenSpinBox->setMinimum(64);
- m_permGenSpinBox->setMaximum(m_availableMemory);
- m_permGenSpinBox->setSingleStep(8);
- m_gridLayout_2->addWidget(m_permGenSpinBox, 2, 1, 1, 1);
- m_permGenSpinBox->setVisible(false);
-
- m_verticalLayout->addWidget(m_memoryGroupBox);
+ m_java_widget = new JavaSettingsWidget(this);
+ layout->addWidget(m_java_widget);
+ setLayout(layout);
retranslate();
}
void JavaWizardPage::refresh()
{
- m_versionWidget->loadList();
+ m_java_widget->refresh();
}
void JavaWizardPage::initializePage()
{
- m_versionWidget->initialize();
- auto s = MMC->settings();
- // Memory
- observedMinMemory = s->get("MinMemAlloc").toInt();
- observedMaxMemory = s->get("MaxMemAlloc").toInt();
- observedPermGenMemory = s->get("PermGen").toInt();
- m_minMemSpinBox->setValue(observedMinMemory);
- m_maxMemSpinBox->setValue(observedMaxMemory);
- m_permGenSpinBox->setValue(observedPermGenMemory);
-}
-
-bool JavaWizardPage::validatePage()
-{
- auto settings = MMC->settings();
- auto path = m_javaPathTextBox->text();
- switch(javaStatus)
- {
- case JavaStatus::NotSet:
- case JavaStatus::DoesNotExist:
- case JavaStatus::DoesNotStart:
- case JavaStatus::ReturnedInvalidData:
- {
- int button = CustomMessageBox::selectable(
- this,
- tr("No Java version selected"),
- tr("You didn't select a Java version or selected something that doesn't work.\n"
- "MultiMC will not be able to start Minecraft.\n"
- "Do you wish to proceed without any Java?"
- "\n\n"
- "You can change the Java version in the settings later.\n"
- ),
- QMessageBox::Warning,
- QMessageBox::Yes | QMessageBox::No,
- QMessageBox::NoButton
- )->exec();
- if(button == QMessageBox::No)
- {
- return false;
- }
- }
- break;
- case JavaStatus::Pending:
- {
- return false;
- }
- case JavaStatus::Good:
- {
- settings->set("JavaPath", path);
- }
- }
-
- // Memory
- auto s = MMC->settings();
- s->set("MinMemAlloc", m_minMemSpinBox->value());
- s->set("MaxMemAlloc", m_maxMemSpinBox->value());
- if (m_permGenSpinBox->isVisible())
- {
- s->set("PermGen", m_permGenSpinBox->value());
- }
- else
- {
- s->reset("PermGen");
- }
- return true;
+ m_java_widget->initialize();
}
bool JavaWizardPage::wantsRefreshButton()
@@ -202,221 +53,37 @@ bool JavaWizardPage::wantsRefreshButton()
return true;
}
-void JavaWizardPage::memoryValueChanged(int)
+bool JavaWizardPage::validatePage()
{
- bool actuallyChanged = false;
- int min = m_minMemSpinBox->value();
- int max = m_maxMemSpinBox->value();
- int permgen = m_permGenSpinBox->value();
- QObject *obj = sender();
- if (obj == m_minMemSpinBox && min != observedMinMemory)
+ auto settings = MMC->settings();
+ auto result = m_java_widget->validate();
+ switch(result)
{
- observedMinMemory = min;
- actuallyChanged = true;
- if (min > max)
+ default:
+ case JavaSettingsWidget::ValidationStatus::Bad:
{
- observedMaxMemory = min;
- m_maxMemSpinBox->setValue(min);
+ return false;
}
- }
- else if (obj == m_maxMemSpinBox && max != observedMaxMemory)
- {
- observedMaxMemory = max;
- actuallyChanged = true;
- if (min > max)
+ case JavaSettingsWidget::ValidationStatus::AllOK:
{
- observedMinMemory = max;
- m_minMemSpinBox->setValue(max);
+ settings->set("JavaPath", m_java_widget->javaPath());
}
- }
- else if (obj == m_permGenSpinBox && permgen != observedPermGenMemory)
- {
- observedPermGenMemory = permgen;
- actuallyChanged = true;
- }
- if(actuallyChanged)
- {
- checkJavaPathOnEdit(m_javaPathTextBox->text());
- }
-}
-
-void JavaWizardPage::javaVersionSelected(BaseVersionPtr version)
-{
- auto java = std::dynamic_pointer_cast<JavaInstall>(version);
- if(!java)
- {
- return;
- }
- auto visible = java->id.requiresPermGen();
- m_labelPermGen->setVisible(visible);
- m_permGenSpinBox->setVisible(visible);
- m_javaPathTextBox->setText(java->path);
- checkJavaPath(java->path);
-}
-
-void JavaWizardPage::on_javaBrowseBtn_clicked()
-{
- QString filter;
-#if defined Q_OS_WIN32
- filter = "Java (javaw.exe)";
-#else
- filter = "Java (java)";
-#endif
- QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"), QString(), filter);
- if(raw_path.isNull())
- {
- return;
- }
- QString cooked_path = FS::NormalizePath(raw_path);
- m_javaPathTextBox->setText(cooked_path);
- checkJavaPath(cooked_path);
-}
-
-void JavaWizardPage::on_javaStatusBtn_clicked()
-{
- QString text;
- bool failed = false;
- switch(javaStatus)
- {
- case JavaStatus::NotSet:
- checkJavaPath(m_javaPathTextBox->text());
- return;
- case JavaStatus::DoesNotExist:
- text += QObject::tr("The specified file either doesn't exist or is not a proper executable.");
- failed = true;
- break;
- case JavaStatus::DoesNotStart:
+ case JavaSettingsWidget::ValidationStatus::JavaBad:
{
- text += QObject::tr("The specified java binary didn't start properly.<br />");
- auto htmlError = m_result.errorLog;
- if(!htmlError.isEmpty())
+ // Memory
+ auto s = MMC->settings();
+ s->set("MinMemAlloc", m_java_widget->minHeapSize());
+ s->set("MaxMemAlloc", m_java_widget->maxHeapSize());
+ if (m_java_widget->permGenEnabled())
{
- htmlError.replace('\n', "<br />");
- text += QString("<font color=\"red\">%1</font>").arg(htmlError);
+ s->set("PermGen", m_java_widget->permGenSize());
}
- failed = true;
- break;
- }
- case JavaStatus::ReturnedInvalidData:
- {
- text += QObject::tr("The specified java binary returned unexpected results:<br />");
- auto htmlOut = m_result.outLog;
- if(!htmlOut.isEmpty())
+ else
{
- htmlOut.replace('\n', "<br />");
- text += QString("<font color=\"red\">%1</font>").arg(htmlOut);
+ s->reset("PermGen");
}
- failed = true;
- break;
- }
- case JavaStatus::Good:
- text += QObject::tr("Java test succeeded!<br />Platform reported: %1<br />Java version "
- "reported: %2<br />").arg(m_result.realPlatform, m_result.javaVersion.toString());
- break;
- case JavaStatus::Pending:
- // TODO: abort here?
- return;
- }
- CustomMessageBox::selectable(
- this,
- failed ? QObject::tr("Java test success") : QObject::tr("Java test failure"),
- text,
- failed ? QMessageBox::Critical : QMessageBox::Information
- )->show();
-}
-
-void JavaWizardPage::setJavaStatus(JavaWizardPage::JavaStatus status)
-{
- javaStatus = status;
- switch(javaStatus)
- {
- case JavaStatus::Good:
- m_javaStatusBtn->setIcon(goodIcon);
- break;
- case JavaStatus::NotSet:
- case JavaStatus::Pending:
- m_javaStatusBtn->setIcon(yellowIcon);
- break;
- default:
- m_javaStatusBtn->setIcon(badIcon);
- break;
- }
-}
-
-void JavaWizardPage::javaPathEdited(const QString& path)
-{
- checkJavaPathOnEdit(path);
-}
-
-void JavaWizardPage::checkJavaPathOnEdit(const QString& path)
-{
- auto realPath = FS::ResolveExecutable(path);
- QFileInfo pathInfo(realPath);
- if (pathInfo.baseName().toLower().contains("java"))
- {
- checkJavaPath(path);
- }
- else
- {
- if(!m_checker)
- {
- setJavaStatus(JavaStatus::NotSet);
- }
- }
-}
-
-void JavaWizardPage::checkJavaPath(const QString &path)
-{
- if(m_checker)
- {
- queuedCheck = path;
- return;
- }
- auto realPath = FS::ResolveExecutable(path);
- if(realPath.isNull())
- {
- setJavaStatus(JavaStatus::DoesNotExist);
- return;
- }
- setJavaStatus(JavaStatus::Pending);
- m_checker.reset(new JavaChecker());
- m_checker->m_path = path;
- m_checker->m_minMem = m_minMemSpinBox->value();
- m_checker->m_maxMem = m_maxMemSpinBox->value();
- if(m_permGenSpinBox->isVisible())
- {
- m_checker->m_permGen = m_permGenSpinBox->value();
- }
- connect(m_checker.get(), &JavaChecker::checkFinished, this, &JavaWizardPage::checkFinished);
- m_checker->performCheck();
-}
-
-void JavaWizardPage::checkFinished(JavaCheckResult result)
-{
- m_result = result;
- switch(result.validity)
- {
- case JavaCheckResult::Validity::Valid:
- {
- setJavaStatus(JavaStatus::Good);
- break;
+ return true;
}
- case JavaCheckResult::Validity::ReturnedInvalidData:
- {
- setJavaStatus(JavaStatus::ReturnedInvalidData);
- break;
- }
- case JavaCheckResult::Validity::Errored:
- {
- setJavaStatus(JavaStatus::DoesNotStart);
- break;
- }
- }
- m_checker.reset();
- if(!queuedCheck.isNull())
- {
- checkJavaPath(queuedCheck);
- queuedCheck.clear();
}
}
@@ -425,11 +92,5 @@ void JavaWizardPage::retranslate()
setTitle(tr("Java"));
setSubTitle(tr("You do not have a working Java set up yet or it went missing.\n"
"Please select one of the following or browse for a java executable."));
- m_memoryGroupBox->setTitle(tr("Memory"));
- m_maxMemSpinBox->setToolTip(tr("The maximum amount of memory Minecraft is allowed to use."));
- m_labelMinMem->setText(tr("Minimum memory allocation:"));
- m_labelMaxMem->setText(tr("Maximum memory allocation:"));
- m_minMemSpinBox->setToolTip(tr("The amount of memory Minecraft is started with."));
- m_permGenSpinBox->setToolTip(tr("The amount of memory available to store loaded Java classes."));
- m_javaBrowseBtn->setText(tr("Browse"));
+ m_java_widget->retranslate();
}
diff --git a/application/setupwizard/JavaWizardPage.h b/application/setupwizard/JavaWizardPage.h
index f240217e..4ea31d24 100644
--- a/application/setupwizard/JavaWizardPage.h
+++ b/application/setupwizard/JavaWizardPage.h
@@ -1,21 +1,8 @@
#pragma once
#include "BaseWizardPage.h"
-#include <BaseVersion.h>
-#include <QObjectPtr.h>
-#include <java/JavaChecker.h>
-#include <QIcon>
-class QLineEdit;
-class VersionSelectWidget;
-class QSpinBox;
-class QPushButton;
-class QVBoxLayout;
-class QHBoxLayout;
-class QGroupBox;
-class QGridLayout;
-class QLabel;
-class QToolButton;
+class JavaSettingsWidget;
class JavaWizardPage : public BaseWizardPage
{
@@ -32,58 +19,11 @@ public:
void initializePage() override;
bool validatePage() override;
- enum class JavaStatus
- {
- NotSet,
- Pending,
- Good,
- DoesNotExist,
- DoesNotStart,
- ReturnedInvalidData
- } javaStatus = JavaStatus::NotSet;
-
-protected slots:
- void memoryValueChanged(int);
- void javaPathEdited(const QString &path);
- void javaVersionSelected(BaseVersionPtr version);
- void on_javaBrowseBtn_clicked();
- void on_javaStatusBtn_clicked();
- void checkFinished(JavaCheckResult result);
-
protected: /* methods */
- void checkJavaPathOnEdit(const QString &path);
- void checkJavaPath(const QString &path);
- void setJavaStatus(JavaStatus status);
void setupUi();
void retranslate() override;
private: /* data */
- VersionSelectWidget *m_versionWidget = nullptr;
- QVBoxLayout *m_verticalLayout = nullptr;
-
- QLineEdit * m_javaPathTextBox = nullptr;
- QPushButton * m_javaBrowseBtn = nullptr;
- QToolButton * m_javaStatusBtn = nullptr;
- QHBoxLayout *m_horizontalLayout = nullptr;
-
- QGroupBox *m_memoryGroupBox = nullptr;
- QGridLayout *m_gridLayout_2 = nullptr;
- QSpinBox *m_maxMemSpinBox = nullptr;
- QLabel *m_labelMinMem = nullptr;
- QLabel *m_labelMaxMem = nullptr;
- QSpinBox *m_minMemSpinBox = nullptr;
- QLabel *m_labelPermGen = nullptr;
- QSpinBox *m_permGenSpinBox = nullptr;
- QIcon goodIcon;
- QIcon yellowIcon;
- QIcon badIcon;
-
- int observedMinMemory = 0;
- int observedMaxMemory = 0;
- int observedPermGenMemory = 0;
- QString queuedCheck;
- uint64_t m_availableMemory = 0ull;
- shared_qobject_ptr<JavaChecker> m_checker;
- JavaCheckResult m_result;
+ JavaSettingsWidget *m_java_widget = nullptr;
};
diff --git a/application/setupwizard/SetupWizard.h b/application/setupwizard/SetupWizard.h
index a336f575..e3292997 100644
--- a/application/setupwizard/SetupWizard.h
+++ b/application/setupwizard/SetupWizard.h
@@ -1,4 +1,4 @@
-/* Copyright 2017 MultiMC Contributors
+/* Copyright 2017-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/themes/SystemTheme.cpp b/application/themes/SystemTheme.cpp
index 069b0b1b..a9ee853a 100644
--- a/application/themes/SystemTheme.cpp
+++ b/application/themes/SystemTheme.cpp
@@ -9,7 +9,7 @@ SystemTheme::SystemTheme()
const auto & style = QApplication::style();
systemPalette = style->standardPalette();
QString lowerThemeName = style->objectName();
- qWarning() << systemTheme;
+ qDebug() << systemTheme;
QStringList styles = QStyleFactory::keys();
for(auto &st: styles)
{
@@ -21,7 +21,7 @@ SystemTheme::SystemTheme()
}
// fall back to fusion if we can't find the current theme.
systemTheme = "Fusion";
- qWarning() << "System theme not found, defaulted to Fusion";
+ qDebug() << "System theme not found, defaulted to Fusion";
}
void SystemTheme::apply(bool initial)
diff --git a/application/widgets/CustomCommands.cpp b/application/widgets/CustomCommands.cpp
new file mode 100644
index 00000000..9f11e344
--- /dev/null
+++ b/application/widgets/CustomCommands.cpp
@@ -0,0 +1,48 @@
+#include "CustomCommands.h"
+#include "ui_CustomCommands.h"
+
+CustomCommands::~CustomCommands()
+{
+}
+
+CustomCommands::CustomCommands(QWidget* parent):
+ QWidget(parent),
+ ui(new Ui::CustomCommands)
+{
+ ui->setupUi(this);
+}
+
+void CustomCommands::initialize(bool checkable, bool checked, const QString& prelaunch, const QString& wrapper, const QString& postexit)
+{
+ ui->customCommandsGroupBox->setCheckable(checkable);
+ if(checkable)
+ {
+ ui->customCommandsGroupBox->setChecked(checked);
+ }
+ ui->preLaunchCmdTextBox->setText(prelaunch);
+ ui->wrapperCmdTextBox->setText(wrapper);
+ ui->postExitCmdTextBox->setText(postexit);
+}
+
+
+bool CustomCommands::checked() const
+{
+ if(!ui->customCommandsGroupBox->isCheckable())
+ return true;
+ return ui->customCommandsGroupBox->isChecked();
+}
+
+QString CustomCommands::prelaunchCommand() const
+{
+ return ui->preLaunchCmdTextBox->text();
+}
+
+QString CustomCommands::wrapperCommand() const
+{
+ return ui->wrapperCmdTextBox->text();
+}
+
+QString CustomCommands::postexitCommand() const
+{
+ return ui->postExitCmdTextBox->text();
+}
diff --git a/application/widgets/CustomCommands.h b/application/widgets/CustomCommands.h
new file mode 100644
index 00000000..2bc7cb1a
--- /dev/null
+++ b/application/widgets/CustomCommands.h
@@ -0,0 +1,43 @@
+/* Copyright 2018-2018 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <QWidget>
+
+namespace Ui
+{
+class CustomCommands;
+}
+
+class CustomCommands : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit CustomCommands(QWidget *parent = 0);
+ ~CustomCommands();
+ void initialize(bool checkable, bool checked, const QString & prelaunch, const QString & wrapper, const QString & postexit);
+
+ bool checked() const;
+ QString prelaunchCommand() const;
+ QString wrapperCommand() const;
+ QString postexitCommand() const;
+
+private:
+ Ui::CustomCommands *ui;
+};
+
+
diff --git a/application/widgets/CustomCommands.ui b/application/widgets/CustomCommands.ui
new file mode 100644
index 00000000..44104460
--- /dev/null
+++ b/application/widgets/CustomCommands.ui
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CustomCommands</class>
+ <widget class="QWidget" name="CustomCommands">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>518</width>
+ <height>646</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="customCommandsGroupBox">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="title">
+ <string>Cus&amp;tom Commands</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="2" column="0">
+ <widget class="QLabel" name="labelPostExitCmd">
+ <property name="text">
+ <string>Post-exit command:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="preLaunchCmdTextBox"/>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="labelPreLaunchCmd">
+ <property name="text">
+ <string>Pre-launch command:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="postExitCmdTextBox"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="labelWrapperCmd">
+ <property name="text">
+ <string>Wrapper command:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="wrapperCmdTextBox"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelCustomCmdsDescription">
+ <property name="text">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Pre-launch command runs before the instance launches and post-exit command runs after it exits.&lt;/p&gt;&lt;p&gt;Both will be run in MultiMC's working folder with extra environment variables:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;INST_NAME - Name of the instance&lt;/li&gt;&lt;li&gt;INST_ID - ID of the instance&lt;/li&gt;&lt;li&gt;INST_DIR - absolute path of the instance&lt;/li&gt;&lt;li&gt;INST_MC_DIR - absolute path of minecraft&lt;/li&gt;&lt;li&gt;INST_JAVA - java binary used for launch&lt;/li&gt;&lt;li&gt;INST_JAVA_ARGS - command-line parameters used for launch&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Wrapper command allows launching using an extra wrapper program (like 'optirun' on Linux)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
+ </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>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/application/widgets/FtbModpackListItem.cpp b/application/widgets/FtbModpackListItem.cpp
new file mode 100644
index 00000000..874e0eac
--- /dev/null
+++ b/application/widgets/FtbModpackListItem.cpp
@@ -0,0 +1,8 @@
+#include "FtbModpackListItem.h"
+
+FtbModpackListItem::FtbModpackListItem(QListWidget *list, FtbModpack modpack) : QListWidgetItem(list), modpack(modpack) {
+}
+
+FtbModpack FtbModpackListItem::getModpack(){
+ return modpack;
+}
diff --git a/application/widgets/FtbModpackListItem.h b/application/widgets/FtbModpackListItem.h
new file mode 100644
index 00000000..977cad2d
--- /dev/null
+++ b/application/widgets/FtbModpackListItem.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "QListWidget"
+#include <modplatform/PackHelpers.h>
+
+class FtbModpackListItem : public QListWidgetItem {
+
+private:
+ FtbModpack modpack;
+
+public:
+ FtbModpackListItem(QListWidget *list, FtbModpack modpack);
+ FtbModpack getModpack();
+
+};
diff --git a/application/widgets/JavaSettingsWidget.cpp b/application/widgets/JavaSettingsWidget.cpp
new file mode 100644
index 00000000..13cd27e7
--- /dev/null
+++ b/application/widgets/JavaSettingsWidget.cpp
@@ -0,0 +1,428 @@
+#include "JavaSettingsWidget.h"
+#include <MultiMC.h>
+
+#include <java/JavaInstall.h>
+#include <dialogs/CustomMessageBox.h>
+#include <java/JavaUtils.h>
+#include <sys.h>
+
+#include <QVBoxLayout>
+#include <QGroupBox>
+#include <QSpinBox>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QToolButton>
+#include <widgets/VersionSelectWidget.h>
+#include <FileSystem.h>
+#include <QFileDialog>
+
+JavaSettingsWidget::JavaSettingsWidget(QWidget* parent) : QWidget(parent)
+{
+ m_availableMemory = Sys::getSystemRam() / Sys::megabyte;
+
+ goodIcon = MMC->getThemedIcon("status-good");
+ yellowIcon = MMC->getThemedIcon("status-yellow");
+ badIcon = MMC->getThemedIcon("status-bad");
+ setupUi();
+
+ connect(m_minMemSpinBox, SIGNAL(valueChanged(int)), this, SLOT(memoryValueChanged(int)));
+ connect(m_maxMemSpinBox, SIGNAL(valueChanged(int)), this, SLOT(memoryValueChanged(int)));
+ connect(m_permGenSpinBox, SIGNAL(valueChanged(int)), this, SLOT(memoryValueChanged(int)));
+ connect(m_versionWidget, &VersionSelectWidget::selectedVersionChanged, this, &JavaSettingsWidget::javaVersionSelected);
+ connect(m_javaBrowseBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_javaBrowseBtn_clicked);
+ connect(m_javaPathTextBox, &QLineEdit::textEdited, this, &JavaSettingsWidget::javaPathEdited);
+ connect(m_javaStatusBtn, &QToolButton::clicked, this, &JavaSettingsWidget::on_javaStatusBtn_clicked);
+}
+
+void JavaSettingsWidget::setupUi()
+{
+ setObjectName(QStringLiteral("javaSettingsWidget"));
+ m_verticalLayout = new QVBoxLayout(this);
+ m_verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+
+ m_versionWidget = new VersionSelectWidget(MMC->javalist().get(), this);
+ m_versionWidget->setResizeOn(2);
+ m_verticalLayout->addWidget(m_versionWidget);
+
+ m_horizontalLayout = new QHBoxLayout();
+ m_horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ m_javaPathTextBox = new QLineEdit(this);
+ m_javaPathTextBox->setObjectName(QStringLiteral("javaPathTextBox"));
+
+ m_horizontalLayout->addWidget(m_javaPathTextBox);
+
+ m_javaBrowseBtn = new QPushButton(this);
+ m_javaBrowseBtn->setObjectName(QStringLiteral("javaBrowseBtn"));
+
+ m_horizontalLayout->addWidget(m_javaBrowseBtn);
+
+ m_javaStatusBtn = new QToolButton(this);
+ m_javaStatusBtn->setIcon(yellowIcon);
+ m_horizontalLayout->addWidget(m_javaStatusBtn);
+
+ m_verticalLayout->addLayout(m_horizontalLayout);
+
+ m_memoryGroupBox = new QGroupBox(this);
+ m_memoryGroupBox->setObjectName(QStringLiteral("memoryGroupBox"));
+ m_gridLayout_2 = new QGridLayout(m_memoryGroupBox);
+ m_gridLayout_2->setObjectName(QStringLiteral("gridLayout_2"));
+
+ m_labelMinMem = new QLabel(m_memoryGroupBox);
+ m_labelMinMem->setObjectName(QStringLiteral("labelMinMem"));
+ m_gridLayout_2->addWidget(m_labelMinMem, 0, 0, 1, 1);
+
+ m_minMemSpinBox = new QSpinBox(m_memoryGroupBox);
+ m_minMemSpinBox->setObjectName(QStringLiteral("minMemSpinBox"));
+ m_minMemSpinBox->setSuffix(QStringLiteral(" MB"));
+ m_minMemSpinBox->setMinimum(128);
+ m_minMemSpinBox->setMaximum(m_availableMemory);
+ m_minMemSpinBox->setSingleStep(128);
+ m_labelMinMem->setBuddy(m_minMemSpinBox);
+ m_gridLayout_2->addWidget(m_minMemSpinBox, 0, 1, 1, 1);
+
+ m_labelMaxMem = new QLabel(m_memoryGroupBox);
+ m_labelMaxMem->setObjectName(QStringLiteral("labelMaxMem"));
+ m_gridLayout_2->addWidget(m_labelMaxMem, 1, 0, 1, 1);
+
+ m_maxMemSpinBox = new QSpinBox(m_memoryGroupBox);
+ m_maxMemSpinBox->setObjectName(QStringLiteral("maxMemSpinBox"));
+ m_maxMemSpinBox->setSuffix(QStringLiteral(" MB"));
+ m_maxMemSpinBox->setMinimum(128);
+ m_maxMemSpinBox->setMaximum(m_availableMemory);
+ m_maxMemSpinBox->setSingleStep(128);
+ m_labelMaxMem->setBuddy(m_maxMemSpinBox);
+ m_gridLayout_2->addWidget(m_maxMemSpinBox, 1, 1, 1, 1);
+
+ m_labelPermGen = new QLabel(m_memoryGroupBox);
+ m_labelPermGen->setObjectName(QStringLiteral("labelPermGen"));
+ m_labelPermGen->setText(QStringLiteral("PermGen:"));
+ m_gridLayout_2->addWidget(m_labelPermGen, 2, 0, 1, 1);
+ m_labelPermGen->setVisible(false);
+
+ m_permGenSpinBox = new QSpinBox(m_memoryGroupBox);
+ m_permGenSpinBox->setObjectName(QStringLiteral("permGenSpinBox"));
+ m_permGenSpinBox->setSuffix(QStringLiteral(" MB"));
+ m_permGenSpinBox->setMinimum(64);
+ m_permGenSpinBox->setMaximum(m_availableMemory);
+ m_permGenSpinBox->setSingleStep(8);
+ m_gridLayout_2->addWidget(m_permGenSpinBox, 2, 1, 1, 1);
+ m_permGenSpinBox->setVisible(false);
+
+ m_verticalLayout->addWidget(m_memoryGroupBox);
+
+ retranslate();
+}
+
+void JavaSettingsWidget::initialize()
+{
+ m_versionWidget->initialize();
+ auto s = MMC->settings();
+ // Memory
+ observedMinMemory = s->get("MinMemAlloc").toInt();
+ observedMaxMemory = s->get("MaxMemAlloc").toInt();
+ observedPermGenMemory = s->get("PermGen").toInt();
+ m_minMemSpinBox->setValue(observedMinMemory);
+ m_maxMemSpinBox->setValue(observedMaxMemory);
+ m_permGenSpinBox->setValue(observedPermGenMemory);
+}
+
+void JavaSettingsWidget::refresh()
+{
+ m_versionWidget->loadList();
+}
+
+JavaSettingsWidget::ValidationStatus JavaSettingsWidget::validate()
+{
+ switch(javaStatus)
+ {
+ default:
+ case JavaStatus::NotSet:
+ case JavaStatus::DoesNotExist:
+ case JavaStatus::DoesNotStart:
+ case JavaStatus::ReturnedInvalidData:
+ {
+ int button = CustomMessageBox::selectable(
+ this,
+ tr("No Java version selected"),
+ tr("You didn't select a Java version or selected something that doesn't work.\n"
+ "MultiMC will not be able to start Minecraft.\n"
+ "Do you wish to proceed without any Java?"
+ "\n\n"
+ "You can change the Java version in the settings later.\n"
+ ),
+ QMessageBox::Warning,
+ QMessageBox::Yes | QMessageBox::No,
+ QMessageBox::NoButton
+ )->exec();
+ if(button == QMessageBox::No)
+ {
+ return ValidationStatus::Bad;
+ }
+ return ValidationStatus::JavaBad;
+ }
+ break;
+ case JavaStatus::Pending:
+ {
+ return ValidationStatus::Bad;
+ }
+ case JavaStatus::Good:
+ {
+ return ValidationStatus::AllOK;
+ }
+ }
+}
+
+QString JavaSettingsWidget::javaPath() const
+{
+ return m_javaPathTextBox->text();
+}
+
+int JavaSettingsWidget::maxHeapSize() const
+{
+ return m_maxMemSpinBox->value();
+}
+
+int JavaSettingsWidget::minHeapSize() const
+{
+ return m_minMemSpinBox->value();
+}
+
+bool JavaSettingsWidget::permGenEnabled() const
+{
+ return m_permGenSpinBox->isVisible();
+}
+
+int JavaSettingsWidget::permGenSize() const
+{
+ return m_permGenSpinBox->value();
+}
+
+void JavaSettingsWidget::memoryValueChanged(int)
+{
+ bool actuallyChanged = false;
+ int min = m_minMemSpinBox->value();
+ int max = m_maxMemSpinBox->value();
+ int permgen = m_permGenSpinBox->value();
+ QObject *obj = sender();
+ if (obj == m_minMemSpinBox && min != observedMinMemory)
+ {
+ observedMinMemory = min;
+ actuallyChanged = true;
+ if (min > max)
+ {
+ observedMaxMemory = min;
+ m_maxMemSpinBox->setValue(min);
+ }
+ }
+ else if (obj == m_maxMemSpinBox && max != observedMaxMemory)
+ {
+ observedMaxMemory = max;
+ actuallyChanged = true;
+ if (min > max)
+ {
+ observedMinMemory = max;
+ m_minMemSpinBox->setValue(max);
+ }
+ }
+ else if (obj == m_permGenSpinBox && permgen != observedPermGenMemory)
+ {
+ observedPermGenMemory = permgen;
+ actuallyChanged = true;
+ }
+ if(actuallyChanged)
+ {
+ checkJavaPathOnEdit(m_javaPathTextBox->text());
+ }
+}
+
+void JavaSettingsWidget::javaVersionSelected(BaseVersionPtr version)
+{
+ auto java = std::dynamic_pointer_cast<JavaInstall>(version);
+ if(!java)
+ {
+ return;
+ }
+ auto visible = java->id.requiresPermGen();
+ m_labelPermGen->setVisible(visible);
+ m_permGenSpinBox->setVisible(visible);
+ m_javaPathTextBox->setText(java->path);
+ checkJavaPath(java->path);
+}
+
+void JavaSettingsWidget::on_javaBrowseBtn_clicked()
+{
+ QString filter;
+#if defined Q_OS_WIN32
+ filter = "Java (javaw.exe)";
+#else
+ filter = "Java (java)";
+#endif
+ QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"), QString(), filter);
+ if(raw_path.isEmpty())
+ {
+ return;
+ }
+ QString cooked_path = FS::NormalizePath(raw_path);
+ m_javaPathTextBox->setText(cooked_path);
+ checkJavaPath(cooked_path);
+}
+
+void JavaSettingsWidget::on_javaStatusBtn_clicked()
+{
+ QString text;
+ bool failed = false;
+ switch(javaStatus)
+ {
+ case JavaStatus::NotSet:
+ checkJavaPath(m_javaPathTextBox->text());
+ return;
+ case JavaStatus::DoesNotExist:
+ text += QObject::tr("The specified file either doesn't exist or is not a proper executable.");
+ failed = true;
+ break;
+ case JavaStatus::DoesNotStart:
+ {
+ text += QObject::tr("The specified java binary didn't start properly.<br />");
+ auto htmlError = m_result.errorLog;
+ if(!htmlError.isEmpty())
+ {
+ htmlError.replace('\n', "<br />");
+ text += QString("<font color=\"red\">%1</font>").arg(htmlError);
+ }
+ failed = true;
+ break;
+ }
+ case JavaStatus::ReturnedInvalidData:
+ {
+ text += QObject::tr("The specified java binary returned unexpected results:<br />");
+ auto htmlOut = m_result.outLog;
+ if(!htmlOut.isEmpty())
+ {
+ htmlOut.replace('\n', "<br />");
+ text += QString("<font color=\"red\">%1</font>").arg(htmlOut);
+ }
+ failed = true;
+ break;
+ }
+ case JavaStatus::Good:
+ text += QObject::tr("Java test succeeded!<br />Platform reported: %1<br />Java version "
+ "reported: %2<br />").arg(m_result.realPlatform, m_result.javaVersion.toString());
+ break;
+ case JavaStatus::Pending:
+ // TODO: abort here?
+ return;
+ }
+ CustomMessageBox::selectable(
+ this,
+ failed ? QObject::tr("Java test success") : QObject::tr("Java test failure"),
+ text,
+ failed ? QMessageBox::Critical : QMessageBox::Information
+ )->show();
+}
+
+void JavaSettingsWidget::setJavaStatus(JavaSettingsWidget::JavaStatus status)
+{
+ javaStatus = status;
+ switch(javaStatus)
+ {
+ case JavaStatus::Good:
+ m_javaStatusBtn->setIcon(goodIcon);
+ break;
+ case JavaStatus::NotSet:
+ case JavaStatus::Pending:
+ m_javaStatusBtn->setIcon(yellowIcon);
+ break;
+ default:
+ m_javaStatusBtn->setIcon(badIcon);
+ break;
+ }
+}
+
+void JavaSettingsWidget::javaPathEdited(const QString& path)
+{
+ checkJavaPathOnEdit(path);
+}
+
+void JavaSettingsWidget::checkJavaPathOnEdit(const QString& path)
+{
+ auto realPath = FS::ResolveExecutable(path);
+ QFileInfo pathInfo(realPath);
+ if (pathInfo.baseName().toLower().contains("java"))
+ {
+ checkJavaPath(path);
+ }
+ else
+ {
+ if(!m_checker)
+ {
+ setJavaStatus(JavaStatus::NotSet);
+ }
+ }
+}
+
+void JavaSettingsWidget::checkJavaPath(const QString &path)
+{
+ if(m_checker)
+ {
+ queuedCheck = path;
+ return;
+ }
+ auto realPath = FS::ResolveExecutable(path);
+ if(realPath.isNull())
+ {
+ setJavaStatus(JavaStatus::DoesNotExist);
+ return;
+ }
+ setJavaStatus(JavaStatus::Pending);
+ m_checker.reset(new JavaChecker());
+ m_checker->m_path = path;
+ m_checker->m_minMem = m_minMemSpinBox->value();
+ m_checker->m_maxMem = m_maxMemSpinBox->value();
+ if(m_permGenSpinBox->isVisible())
+ {
+ m_checker->m_permGen = m_permGenSpinBox->value();
+ }
+ connect(m_checker.get(), &JavaChecker::checkFinished, this, &JavaSettingsWidget::checkFinished);
+ m_checker->performCheck();
+}
+
+void JavaSettingsWidget::checkFinished(JavaCheckResult result)
+{
+ m_result = result;
+ switch(result.validity)
+ {
+ case JavaCheckResult::Validity::Valid:
+ {
+ setJavaStatus(JavaStatus::Good);
+ break;
+ }
+ case JavaCheckResult::Validity::ReturnedInvalidData:
+ {
+ setJavaStatus(JavaStatus::ReturnedInvalidData);
+ break;
+ }
+ case JavaCheckResult::Validity::Errored:
+ {
+ setJavaStatus(JavaStatus::DoesNotStart);
+ break;
+ }
+ }
+ m_checker.reset();
+ if(!queuedCheck.isNull())
+ {
+ checkJavaPath(queuedCheck);
+ queuedCheck.clear();
+ }
+}
+
+void JavaSettingsWidget::retranslate()
+{
+ m_memoryGroupBox->setTitle(tr("Memory"));
+ m_maxMemSpinBox->setToolTip(tr("The maximum amount of memory Minecraft is allowed to use."));
+ m_labelMinMem->setText(tr("Minimum memory allocation:"));
+ m_labelMaxMem->setText(tr("Maximum memory allocation:"));
+ m_minMemSpinBox->setToolTip(tr("The amount of memory Minecraft is started with."));
+ m_permGenSpinBox->setToolTip(tr("The amount of memory available to store loaded Java classes."));
+ m_javaBrowseBtn->setText(tr("Browse"));
+}
diff --git a/application/widgets/JavaSettingsWidget.h b/application/widgets/JavaSettingsWidget.h
new file mode 100644
index 00000000..3a94f851
--- /dev/null
+++ b/application/widgets/JavaSettingsWidget.h
@@ -0,0 +1,102 @@
+#pragma once
+#include <QWidget>
+
+#include <java/JavaChecker.h>
+#include <BaseVersion.h>
+#include <QObjectPtr.h>
+#include <QIcon>
+
+class QLineEdit;
+class VersionSelectWidget;
+class QSpinBox;
+class QPushButton;
+class QVBoxLayout;
+class QHBoxLayout;
+class QGroupBox;
+class QGridLayout;
+class QLabel;
+class QToolButton;
+
+/**
+ * This is a widget for all the Java settings dialogs and pages.
+ */
+class JavaSettingsWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit JavaSettingsWidget(QWidget *parent);
+ virtual ~JavaSettingsWidget() {};
+
+ enum class JavaStatus
+ {
+ NotSet,
+ Pending,
+ Good,
+ DoesNotExist,
+ DoesNotStart,
+ ReturnedInvalidData
+ } javaStatus = JavaStatus::NotSet;
+
+ enum class ValidationStatus
+ {
+ Bad,
+ JavaBad,
+ AllOK
+ };
+
+ void refresh();
+ void initialize();
+ ValidationStatus validate();
+ void retranslate();
+
+ bool permGenEnabled() const;
+ int permGenSize() const;
+ int minHeapSize() const;
+ int maxHeapSize() const;
+ QString javaPath() const;
+
+
+protected slots:
+ void memoryValueChanged(int);
+ void javaPathEdited(const QString &path);
+ void javaVersionSelected(BaseVersionPtr version);
+ void on_javaBrowseBtn_clicked();
+ void on_javaStatusBtn_clicked();
+ void checkFinished(JavaCheckResult result);
+
+protected: /* methods */
+ void checkJavaPathOnEdit(const QString &path);
+ void checkJavaPath(const QString &path);
+ void setJavaStatus(JavaStatus status);
+ void setupUi();
+
+private: /* data */
+ VersionSelectWidget *m_versionWidget = nullptr;
+ QVBoxLayout *m_verticalLayout = nullptr;
+
+ QLineEdit * m_javaPathTextBox = nullptr;
+ QPushButton * m_javaBrowseBtn = nullptr;
+ QToolButton * m_javaStatusBtn = nullptr;
+ QHBoxLayout *m_horizontalLayout = nullptr;
+
+ QGroupBox *m_memoryGroupBox = nullptr;
+ QGridLayout *m_gridLayout_2 = nullptr;
+ QSpinBox *m_maxMemSpinBox = nullptr;
+ QLabel *m_labelMinMem = nullptr;
+ QLabel *m_labelMaxMem = nullptr;
+ QSpinBox *m_minMemSpinBox = nullptr;
+ QLabel *m_labelPermGen = nullptr;
+ QSpinBox *m_permGenSpinBox = nullptr;
+ QIcon goodIcon;
+ QIcon yellowIcon;
+ QIcon badIcon;
+
+ int observedMinMemory = 0;
+ int observedMaxMemory = 0;
+ int observedPermGenMemory = 0;
+ QString queuedCheck;
+ uint64_t m_availableMemory = 0ull;
+ shared_qobject_ptr<JavaChecker> m_checker;
+ JavaCheckResult m_result;
+};
diff --git a/application/widgets/LabeledToolButton.cpp b/application/widgets/LabeledToolButton.cpp
index 827fdf2d..744d2e00 100644
--- a/application/widgets/LabeledToolButton.cpp
+++ b/application/widgets/LabeledToolButton.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
#include <QStyleOption>
#include "LabeledToolButton.h"
#include <QApplication>
+#include <QDebug>
/*
*
@@ -36,7 +37,7 @@ LabeledToolButton::LabeledToolButton(QWidget * parent)
m_label->setAlignment(Qt::AlignCenter);
m_label->setTextInteractionFlags(Qt::NoTextInteraction);
// somehow, this makes word wrap work in the QLabel. yay.
- m_label->setMinimumWidth(100);
+ //m_label->setMinimumWidth(100);
}
QString LabeledToolButton::text() const
@@ -49,6 +50,13 @@ void LabeledToolButton::setText(const QString & text)
m_label->setText(text);
}
+void LabeledToolButton::setIcon(QIcon icon)
+{
+ m_icon = icon;
+ resetIcon();
+}
+
+
/*!
\reimp
*/
@@ -82,5 +90,26 @@ QSize LabeledToolButton::sizeHint() const
void LabeledToolButton::resizeEvent(QResizeEvent * event)
{
m_label->setGeometry(QRect(4, 4, width()-8, height()-8));
+ if(!m_icon.isNull())
+ {
+ resetIcon();
+ }
QWidget::resizeEvent(event);
}
+
+void LabeledToolButton::resetIcon()
+{
+ auto iconSz = m_icon.actualSize(QSize(160, 80));
+ float w = iconSz.width();
+ float h = iconSz.height();
+ float ar = w/h;
+ // FIXME: hardcoded max size of 160x80
+ int newW = 80 * ar;
+ if(newW > 160)
+ newW = 160;
+ QSize newSz (newW, 80);
+ auto pixmap = m_icon.pixmap(newSz);
+ m_label->setPixmap(pixmap);
+ m_label->setMinimumHeight(80);
+ m_label->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred );
+}
diff --git a/application/widgets/LabeledToolButton.h b/application/widgets/LabeledToolButton.h
index 999650fc..151a5c2c 100644
--- a/application/widgets/LabeledToolButton.h
+++ b/application/widgets/LabeledToolButton.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,13 +25,16 @@ class LabeledToolButton : public QToolButton
Q_OBJECT
QLabel * m_label;
+ QIcon m_icon;
public:
LabeledToolButton(QWidget * parent = 0);
QString text() const;
void setText(const QString & text);
+ void setIcon(QIcon icon);
virtual QSize sizeHint() const;
protected:
void resizeEvent(QResizeEvent * event);
+ void resetIcon();
};
diff --git a/application/widgets/MCModInfoFrame.cpp b/application/widgets/MCModInfoFrame.cpp
index 9214ef8b..629c17e7 100644
--- a/application/widgets/MCModInfoFrame.cpp
+++ b/application/widgets/MCModInfoFrame.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/widgets/MCModInfoFrame.h b/application/widgets/MCModInfoFrame.h
index da8f6183..6bcd345c 100644
--- a/application/widgets/MCModInfoFrame.h
+++ b/application/widgets/MCModInfoFrame.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/widgets/ModListView.cpp b/application/widgets/ModListView.cpp
index 05b85c60..96e8d91b 100644
--- a/application/widgets/ModListView.cpp
+++ b/application/widgets/ModListView.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/widgets/ModListView.h b/application/widgets/ModListView.h
index 7f3a4a71..baca23f4 100644
--- a/application/widgets/ModListView.h
+++ b/application/widgets/ModListView.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/widgets/PageContainer.cpp b/application/widgets/PageContainer.cpp
index dacd6acd..0f78329a 100644
--- a/application/widgets/PageContainer.cpp
+++ b/application/widgets/PageContainer.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/widgets/PageContainer.h b/application/widgets/PageContainer.h
index c3d77486..96eac80a 100644
--- a/application/widgets/PageContainer.h
+++ b/application/widgets/PageContainer.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,9 +47,23 @@ public:
*/
bool prepareToClose();
+ /* request close - used by individual pages */
+ bool requestClose() override
+ {
+ if(m_container)
+ {
+ return m_container->requestClose();
+ }
+ return false;
+ }
+
virtual bool selectPage(QString pageId) override;
void refreshContainer() override;
+ virtual void setParentContainer(BasePageContainer * container)
+ {
+ m_container = container;
+ };
private:
void createUI();
@@ -60,6 +74,7 @@ slots:
void help();
private:
+ BasePageContainer * m_container = nullptr;
BasePage * m_currentPage = 0;
QSortFilterProxyModel *m_proxyModel;
PageModel *m_model;
diff --git a/application/widgets/PageContainer_p.h b/application/widgets/PageContainer_p.h
index 7e49294f..ed8171f1 100644
--- a/application/widgets/PageContainer_p.h
+++ b/application/widgets/PageContainer_p.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/widgets/ProgressWidget.cpp b/application/widgets/ProgressWidget.cpp
index bd5967a3..fab099a9 100644
--- a/application/widgets/ProgressWidget.cpp
+++ b/application/widgets/ProgressWidget.cpp
@@ -48,12 +48,12 @@ bool ProgressWidget::exec(std::shared_ptr<Task> task)
{
loop.exec();
}
- return task->successful();
+ return task->wasSuccessful();
}
void ProgressWidget::handleTaskFinish()
{
- if (!m_task->successful())
+ if (!m_task->wasSuccessful())
{
m_label->setText(m_task->failReason());
}
diff --git a/application/widgets/ServerStatus.cpp b/application/widgets/ServerStatus.cpp
index 4602dde5..f1963b68 100644
--- a/application/widgets/ServerStatus.cpp
+++ b/application/widgets/ServerStatus.cpp
@@ -63,15 +63,13 @@ ServerStatus::ServerStatus(QWidget *parent, Qt::WindowFlags f) : QWidget(parent,
yellowIcon = MMC->getThemedIcon("status-yellow");
badIcon = MMC->getThemedIcon("status-bad");
- addStatus("minecraft.net", tr("Web"));
- addLine();
- addStatus("account.mojang.com", tr("Account"));
- addLine();
- addStatus("skins.minecraft.net", tr("Skins"));
- addLine();
addStatus("authserver.mojang.com", tr("Auth"));
addLine();
addStatus("sessionserver.mojang.com", tr("Session"));
+ addLine();
+ addStatus("textures.minecraft.net", tr("Skins"));
+ addLine();
+ addStatus("api.mojang.com", tr("API"));
m_statusRefresh = new QToolButton(this);
m_statusRefresh->setCheckable(true);
diff --git a/application/widgets/VersionListView.cpp b/application/widgets/VersionListView.cpp
index 4b60c5e6..8c80ecf3 100644
--- a/application/widgets/VersionListView.cpp
+++ b/application/widgets/VersionListView.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/widgets/VersionListView.h b/application/widgets/VersionListView.h
index 83a20c1f..b7a881e9 100644
--- a/application/widgets/VersionListView.h
+++ b/application/widgets/VersionListView.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/application/widgets/VersionSelectWidget.cpp b/application/widgets/VersionSelectWidget.cpp
index 1696d9d1..2a7cbfb7 100644
--- a/application/widgets/VersionSelectWidget.cpp
+++ b/application/widgets/VersionSelectWidget.cpp
@@ -41,6 +41,11 @@ VersionSelectWidget::VersionSelectWidget(BaseVersionList* vlist, QWidget* parent
QMetaObject::connectSlotsByName(this);
}
+void VersionSelectWidget::setCurrentVersion(const QString& version)
+{
+ m_currentVersion = version;
+}
+
void VersionSelectWidget::setEmptyString(QString emptyString)
{
listView->setEmptyString(emptyString);
@@ -134,15 +139,33 @@ void VersionSelectWidget::preselect()
{
if(preselectedAlready)
return;
- preselectedAlready = true;
+ selectCurrent();
+ if(preselectedAlready)
+ return;
selectRecommended();
}
+void VersionSelectWidget::selectCurrent()
+{
+ if(m_currentVersion.isEmpty())
+ {
+ return;
+ }
+ auto idx = m_proxyModel->getVersion(m_currentVersion);
+ if(idx.isValid())
+ {
+ preselectedAlready = true;
+ listView->selectionModel()->setCurrentIndex(idx,QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
+ listView->scrollTo(idx, QAbstractItemView::PositionAtCenter);
+ }
+}
+
void VersionSelectWidget::selectRecommended()
{
auto idx = m_proxyModel->getRecommended();
if(idx.isValid())
{
+ preselectedAlready = true;
listView->selectionModel()->setCurrentIndex(idx,QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
listView->scrollTo(idx, QAbstractItemView::PositionAtCenter);
}
diff --git a/application/widgets/VersionSelectWidget.h b/application/widgets/VersionSelectWidget.h
index 66e512ac..3ea0b4f5 100644
--- a/application/widgets/VersionSelectWidget.h
+++ b/application/widgets/VersionSelectWidget.h
@@ -1,4 +1,4 @@
-/* Copyright 2013-2017 MultiMC Contributors
+/* Copyright 2013-2018 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,13 +40,14 @@ public:
bool hasVersions() const;
BaseVersionPtr selectedVersion() const;
void selectRecommended();
+ void selectCurrent();
+ void setCurrentVersion(const QString & version);
void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter);
void setExactFilter(BaseVersionList::ModelRoles role, QString filter);
void setEmptyString(QString emptyString);
void setEmptyErrorString(QString emptyErrorString);
void setResizeOn(int column);
- void setUseLatest(const bool useLatest);
signals:
void selectedVersionChanged(BaseVersionPtr version);
@@ -64,6 +65,7 @@ private:
void preselect();
private:
+ QString m_currentVersion;
BaseVersionList *m_vlist = nullptr;
VersionProxyModel *m_proxyModel = nullptr;
int resizeOnColumn = 0;