NOISSUE move everything.
This commit is contained in:
56
application/BuildConfig.cpp.in
Normal file
56
application/BuildConfig.cpp.in
Normal file
@ -0,0 +1,56 @@
|
||||
#include "BuildConfig.h"
|
||||
#include <QObject>
|
||||
|
||||
Config BuildConfig;
|
||||
|
||||
Config::Config()
|
||||
{
|
||||
// Version information
|
||||
VERSION_MAJOR = @MultiMC_VERSION_MAJOR@;
|
||||
VERSION_MINOR = @MultiMC_VERSION_MINOR@;
|
||||
VERSION_HOTFIX = @MultiMC_VERSION_HOTFIX@;
|
||||
VERSION_BUILD = @MultiMC_VERSION_BUILD@;
|
||||
|
||||
VERSION_CHANNEL = "@MultiMC_VERSION_CHANNEL@";
|
||||
BUILD_PLATFORM = "@MultiMC_BUILD_PLATFORM@";
|
||||
CHANLIST_URL = "@MultiMC_CHANLIST_URL@";
|
||||
NOTIFICATION_URL = "@MultiMC_NOTIFICATION_URL@";
|
||||
FULL_VERSION_STR = "@MultiMC_VERSION_MAJOR@.@MultiMC_VERSION_MINOR@.@MultiMC_VERSION_BUILD@";
|
||||
|
||||
UPDATER_DRY_RUN = @MultiMC_UPDATER_DRY_RUN_value@;
|
||||
UPDATER_FORCE_LOCAL = @MultiMC_UPDATER_FORCE_LOCAL_value@;
|
||||
|
||||
GIT_COMMIT = "@MultiMC_GIT_COMMIT@";
|
||||
VERSION_STR = "@MultiMC_VERSION_STRING@";
|
||||
NEWS_RSS_URL = "@MultiMC_NEWS_RSS_URL@";
|
||||
}
|
||||
|
||||
QString Config::printableVersionString() const
|
||||
{
|
||||
QString vstr = QString("%1.%2").arg(QString::number(VERSION_MAJOR), QString::number(VERSION_MINOR));
|
||||
|
||||
if (VERSION_HOTFIX > 0) vstr += "." + QString::number(VERSION_HOTFIX);
|
||||
|
||||
// If the build is a development build or release candidate, add that info to the end.
|
||||
if(VERSION_CHANNEL == "stable")
|
||||
{
|
||||
return vstr;
|
||||
}
|
||||
else if(VERSION_CHANNEL == "develop")
|
||||
{
|
||||
vstr += "-dev-" + QString::number(VERSION_BUILD);
|
||||
}
|
||||
else if(VERSION_CHANNEL == "unstable")
|
||||
{
|
||||
vstr += "-nuke-" + QString::number(VERSION_BUILD);
|
||||
}
|
||||
else if(VERSION_CHANNEL == "custom")
|
||||
{
|
||||
vstr += "-local";
|
||||
}
|
||||
else
|
||||
{
|
||||
vstr += "-" + VERSION_CHANNEL + "-" + QString::number(VERSION_BUILD);
|
||||
}
|
||||
return vstr;
|
||||
}
|
63
application/BuildConfig.h
Normal file
63
application/BuildConfig.h
Normal file
@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
#include <QString>
|
||||
|
||||
/**
|
||||
* \brief The Config class holds all the build-time information passed from the build system.
|
||||
*/
|
||||
class Config
|
||||
{
|
||||
public:
|
||||
Config();
|
||||
/// The major version number.
|
||||
int VERSION_MAJOR;
|
||||
/// The minor version number.
|
||||
int VERSION_MINOR;
|
||||
/// The hotfix number.
|
||||
int VERSION_HOTFIX;
|
||||
/// The build number.
|
||||
int VERSION_BUILD;
|
||||
|
||||
/**
|
||||
* The version channel
|
||||
* This is used by the updater to determine what channel the current version came from.
|
||||
*/
|
||||
QString VERSION_CHANNEL;
|
||||
|
||||
/// A short string identifying this build's platform. For example, "lin64" or "win32".
|
||||
QString BUILD_PLATFORM;
|
||||
|
||||
/// URL for the updater's channel
|
||||
QString CHANLIST_URL;
|
||||
|
||||
/// URL for notifications
|
||||
QString NOTIFICATION_URL;
|
||||
|
||||
/// Used for matching notifications
|
||||
QString FULL_VERSION_STR;
|
||||
|
||||
/// enabled for updater dry run
|
||||
bool UPDATER_DRY_RUN;
|
||||
|
||||
/// enabled for updater dry run
|
||||
bool UPDATER_FORCE_LOCAL;
|
||||
|
||||
/// The commit hash of this build
|
||||
QString GIT_COMMIT;
|
||||
|
||||
/// This is printed on start to standard output
|
||||
QString VERSION_STR;
|
||||
|
||||
/**
|
||||
* This is used to fetch the news RSS feed.
|
||||
* It defaults in CMakeLists.txt to "http://multimc.org/rss.xml"
|
||||
*/
|
||||
QString NEWS_RSS_URL;
|
||||
|
||||
/**
|
||||
* \brief Converts the Version to a string.
|
||||
* \return The version number in string format (major.minor.revision.build).
|
||||
*/
|
||||
QString printableVersionString() const;
|
||||
};
|
||||
|
||||
extern Config BuildConfig;
|
473
application/CMakeLists.txt
Normal file
473
application/CMakeLists.txt
Normal file
@ -0,0 +1,473 @@
|
||||
project(MultiMC-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 4)
|
||||
set(MultiMC_VERSION_HOTFIX 5)
|
||||
|
||||
# Build number
|
||||
set(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
|
||||
|
||||
# Version type
|
||||
set(MultiMC_VERSION_TYPE "Custom" CACHE STRING "MultiMC's version type. This should be one of 'Custom', 'Release', 'ReleaseCandidate', or 'Development', depending on what type of version this is.")
|
||||
|
||||
# Build platform.
|
||||
set(MultiMC_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used by the notification system and to display in the about dialog.")
|
||||
|
||||
# Version channel
|
||||
set(MultiMC_VERSION_CHANNEL "" CACHE STRING "The current build's channel. Included in the version string.")
|
||||
|
||||
# Channel list URL
|
||||
set(MultiMC_CHANLIST_URL "" CACHE STRING "URL for the channel list.")
|
||||
|
||||
# Updater enabled?
|
||||
set(MultiMC_UPDATER false CACHE BOOL "Whether or not the update system is enabled. If this is enabled, you must also set MultiMC_CHANLIST_URL and MultiMC_VERSION_CHANNEL in order for it to work properly.")
|
||||
|
||||
# Notification URL
|
||||
set(MultiMC_NOTIFICATION_URL "" CACHE STRING "URL for checking for notifications.")
|
||||
|
||||
set(MultiMC_RELEASE_VERSION_NAME "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}")
|
||||
if(MultiMC_VERSION_HOTFIX GREATER 0)
|
||||
set(MultiMC_RELEASE_VERSION_NAME "${MultiMC_RELEASE_VERSION_NAME}.${MultiMC_VERSION_HOTFIX}")
|
||||
endif()
|
||||
|
||||
# Build a version string to display in the configure logs.
|
||||
if(MultiMC_VERSION_TYPE STREQUAL "Custom")
|
||||
message(STATUS "Version Type: Custom")
|
||||
set(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}")
|
||||
elseif(MultiMC_VERSION_TYPE STREQUAL "Release")
|
||||
message(STATUS "Version Type: Stable Release")
|
||||
set(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}")
|
||||
elseif(MultiMC_VERSION_TYPE STREQUAL "Development")
|
||||
message(STATUS "Version Type: Development")
|
||||
set(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}-dev${MultiMC_VERSION_BUILD}")
|
||||
else()
|
||||
message(ERROR "Invalid build type.")
|
||||
endif()
|
||||
|
||||
message(STATUS "MultiMC 5 Version: ${MultiMC_VERSION_STRING}")
|
||||
|
||||
# If the update system is enabled, make sure MultiMC_CHANLIST_URL and MultiMC_VERSION_CHANNEL are set.
|
||||
if(MultiMC_UPDATER)
|
||||
if(MultiMC_VERSION_CHANNEL STREQUAL "")
|
||||
message(FATAL_ERROR "Update system is enabled, but MultiMC_VERSION_CHANNEL is not set.\n"
|
||||
"Please ensure the CMake variables MultiMC_VERSION_CHANNEL, MultiMC_CHANLIST_URL, and MultiMC_VERSION_BUILD are set.")
|
||||
endif()
|
||||
if(MultiMC_CHANLIST_URL STREQUAL "")
|
||||
message(FATAL_ERROR "Update system is enabled, but MultiMC_CHANLIST_URL is not set.\n"
|
||||
"Please ensure the CMake variables MultiMC_VERSION_CHANNEL, MultiMC_CHANLIST_URL, and MultiMC_VERSION_BUILD are set.")
|
||||
endif()
|
||||
if(MultiMC_VERSION_BUILD LESS 0)
|
||||
message(FATAL_ERROR "Update system is enabled, but MultiMC_VERSION_BUILD is not set.\n"
|
||||
"Please ensure the CMake variables MultiMC_VERSION_CHANNEL, MultiMC_CHANLIST_URL, and MultiMC_VERSION_BUILD are set.")
|
||||
endif()
|
||||
message(STATUS "Updater is enabled. Channel list URL: ${MultiMC_CHANLIST_URL}")
|
||||
endif()
|
||||
|
||||
#### Updater-related build config options ####
|
||||
option(MultiMC_UPDATER_DRY_RUN "Enable updater dry-run mode -- for updater development." OFF)
|
||||
option(MultiMC_UPDATER_FORCE_LOCAL "Do not download updated updater -- for updater development." OFF)
|
||||
|
||||
if(MultiMC_UPDATER_DRY_RUN)
|
||||
set(MultiMC_UPDATER_DRY_RUN_value "true")
|
||||
else()
|
||||
set(MultiMC_UPDATER_DRY_RUN_value "false")
|
||||
endif()
|
||||
|
||||
if(MultiMC_UPDATER_FORCE_LOCAL)
|
||||
set(MultiMC_UPDATER_FORCE_LOCAL_value "true")
|
||||
else()
|
||||
set(MultiMC_UPDATER_FORCE_LOCAL_value "false")
|
||||
endif()
|
||||
|
||||
######## Configure header ########
|
||||
configure_file("${PROJECT_SOURCE_DIR}/BuildConfig.cpp.in" "${PROJECT_BINARY_DIR}/BuildConfig.cpp")
|
||||
|
||||
######## Packaging/install paths setup ########
|
||||
|
||||
if(UNIX AND APPLE)
|
||||
set(BINARY_DEST_DIR MultiMC.app/Contents/MacOS)
|
||||
set(PLUGIN_DEST_DIR MultiMC.app/Contents/MacOS)
|
||||
set(QTCONF_DEST_DIR MultiMC.app/Contents/Resources)
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app")
|
||||
|
||||
set(MACOSX_BUNDLE_BUNDLE_NAME "MultiMC")
|
||||
set(MACOSX_BUNDLE_INFO_STRING "MultiMC Minecraft launcher and management utility.")
|
||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.multimc.MultiMC5")
|
||||
set(MACOSX_BUNDLE_BUNDLE_VERSION "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_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 2014 MultiMC Contributors")
|
||||
elseif(UNIX)
|
||||
set(BINARY_DEST_DIR bin)
|
||||
set(PLUGIN_DEST_DIR plugins)
|
||||
set(QTCONF_DEST_DIR .)
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC")
|
||||
elseif(WIN32)
|
||||
set(BINARY_DEST_DIR .)
|
||||
set(PLUGIN_DEST_DIR .)
|
||||
set(QTCONF_DEST_DIR .)
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.exe")
|
||||
endif()
|
||||
|
||||
# directories to look for dependencies
|
||||
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR})
|
||||
|
||||
################################ FILES ################################
|
||||
|
||||
######## Sources and headers ########
|
||||
SET(MULTIMC_SOURCES
|
||||
# Application base
|
||||
main.cpp
|
||||
MultiMC.h
|
||||
MultiMC.cpp
|
||||
BuildConfig.h
|
||||
${PROJECT_BINARY_DIR}/BuildConfig.cpp
|
||||
|
||||
# GUI - general utilities
|
||||
GuiUtil.h
|
||||
GuiUtil.cpp
|
||||
ColumnResizer.h
|
||||
ColumnResizer.cpp
|
||||
InstanceProxyModel.h
|
||||
InstanceProxyModel.cpp
|
||||
|
||||
# GUI - windows
|
||||
MainWindow.h
|
||||
MainWindow.cpp
|
||||
ConsoleWindow.h
|
||||
ConsoleWindow.cpp
|
||||
|
||||
# page provider for instances
|
||||
InstancePageProvider.h
|
||||
InstancePageProvider.cpp
|
||||
|
||||
# Annoying nag screen logic
|
||||
NagUtils.h
|
||||
NagUtils.cpp
|
||||
|
||||
|
||||
# GUI - page dialog pages
|
||||
pages/BasePage.h
|
||||
pages/VersionPage.cpp
|
||||
pages/VersionPage.h
|
||||
pages/TexturePackPage.h
|
||||
pages/ResourcePackPage.h
|
||||
pages/ModFolderPage.cpp
|
||||
pages/ModFolderPage.h
|
||||
pages/NotesPage.cpp
|
||||
pages/NotesPage.h
|
||||
pages/LogPage.cpp
|
||||
pages/LogPage.h
|
||||
pages/InstanceSettingsPage.cpp
|
||||
pages/InstanceSettingsPage.h
|
||||
pages/ScreenshotsPage.cpp
|
||||
pages/ScreenshotsPage.h
|
||||
pages/OtherLogsPage.cpp
|
||||
pages/OtherLogsPage.h
|
||||
|
||||
# GUI - global settings pages
|
||||
pages/global/AccountListPage.cpp
|
||||
pages/global/AccountListPage.h
|
||||
pages/global/ExternalToolsPage.cpp
|
||||
pages/global/ExternalToolsPage.h
|
||||
pages/global/JavaPage.cpp
|
||||
pages/global/JavaPage.h
|
||||
pages/global/MinecraftPage.cpp
|
||||
pages/global/MinecraftPage.h
|
||||
pages/global/MultiMCPage.cpp
|
||||
pages/global/MultiMCPage.h
|
||||
pages/global/ProxyPage.cpp
|
||||
pages/global/ProxyPage.h
|
||||
|
||||
# GUI - dialogs
|
||||
dialogs/AboutDialog.cpp
|
||||
dialogs/AboutDialog.h
|
||||
dialogs/AccountSelectDialog.cpp
|
||||
dialogs/AccountSelectDialog.h
|
||||
dialogs/CopyInstanceDialog.cpp
|
||||
dialogs/CopyInstanceDialog.h
|
||||
dialogs/CustomMessageBox.cpp
|
||||
dialogs/CustomMessageBox.h
|
||||
dialogs/EditAccountDialog.cpp
|
||||
dialogs/EditAccountDialog.h
|
||||
dialogs/IconPickerDialog.cpp
|
||||
dialogs/IconPickerDialog.h
|
||||
dialogs/LoginDialog.cpp
|
||||
dialogs/LoginDialog.h
|
||||
dialogs/ModEditDialogCommon.cpp
|
||||
dialogs/ModEditDialogCommon.h
|
||||
dialogs/NewInstanceDialog.cpp
|
||||
dialogs/NewInstanceDialog.h
|
||||
dialogs/NotificationDialog.cpp
|
||||
dialogs/NotificationDialog.h
|
||||
pagedialog/PageDialog.cpp
|
||||
pagedialog/PageDialog.h
|
||||
dialogs/ProgressDialog.cpp
|
||||
dialogs/ProgressDialog.h
|
||||
dialogs/UpdateDialog.cpp
|
||||
dialogs/UpdateDialog.h
|
||||
dialogs/VersionSelectDialog.cpp
|
||||
dialogs/VersionSelectDialog.h
|
||||
|
||||
|
||||
# GUI - widgets
|
||||
widgets/Common.cpp
|
||||
widgets/Common.h
|
||||
widgets/IconLabel.cpp
|
||||
widgets/IconLabel.h
|
||||
widgets/LabeledToolButton.cpp
|
||||
widgets/LabeledToolButton.h
|
||||
widgets/LineSeparator.cpp
|
||||
widgets/LineSeparator.h
|
||||
widgets/MCModInfoFrame.cpp
|
||||
widgets/MCModInfoFrame.h
|
||||
widgets/ModListView.cpp
|
||||
widgets/ModListView.h
|
||||
widgets/PageContainer.cpp
|
||||
widgets/PageContainer.h
|
||||
widgets/PageContainer_p.h
|
||||
widgets/ServerStatus.cpp
|
||||
widgets/ServerStatus.h
|
||||
widgets/VersionListView.cpp
|
||||
widgets/VersionListView.h
|
||||
|
||||
|
||||
# GUI - instance group view
|
||||
groupview/GroupedProxyModel.cpp
|
||||
groupview/GroupedProxyModel.h
|
||||
groupview/GroupView.cpp
|
||||
groupview/GroupView.h
|
||||
groupview/InstanceDelegate.cpp
|
||||
groupview/InstanceDelegate.h
|
||||
groupview/VisualGroup.cpp
|
||||
groupview/VisualGroup.h
|
||||
)
|
||||
|
||||
######## UIs ########
|
||||
SET(MULTIMC_UIS
|
||||
# Option pages
|
||||
pages/VersionPage.ui
|
||||
pages/ModFolderPage.ui
|
||||
pages/LogPage.ui
|
||||
pages/InstanceSettingsPage.ui
|
||||
pages/NotesPage.ui
|
||||
pages/ScreenshotsPage.ui
|
||||
pages/OtherLogsPage.ui
|
||||
|
||||
# Global settings pages
|
||||
pages/global/AccountListPage.ui
|
||||
pages/global/ExternalToolsPage.ui
|
||||
pages/global/JavaPage.ui
|
||||
pages/global/MinecraftPage.ui
|
||||
pages/global/MultiMCPage.ui
|
||||
pages/global/ProxyPage.ui
|
||||
|
||||
# Dialogs
|
||||
dialogs/CopyInstanceDialog.ui
|
||||
dialogs/NewInstanceDialog.ui
|
||||
dialogs/AboutDialog.ui
|
||||
dialogs/VersionSelectDialog.ui
|
||||
dialogs/ProgressDialog.ui
|
||||
dialogs/IconPickerDialog.ui
|
||||
dialogs/AccountSelectDialog.ui
|
||||
dialogs/EditAccountDialog.ui
|
||||
dialogs/LoginDialog.ui
|
||||
dialogs/UpdateDialog.ui
|
||||
dialogs/NotificationDialog.ui
|
||||
|
||||
# Widgets/other
|
||||
widgets/MCModInfoFrame.ui
|
||||
)
|
||||
|
||||
set(MULTIMC_QRCS
|
||||
resources/backgrounds/backgrounds.qrc
|
||||
resources/multimc/multimc.qrc
|
||||
resources/pe_dark/pe_dark.qrc
|
||||
resources/pe_light/pe_light.qrc
|
||||
resources/pe_colored/pe_colored.qrc
|
||||
resources/pe_blue/pe_blue.qrc
|
||||
resources/OSX/OSX.qrc
|
||||
resources/iOS/iOS.qrc
|
||||
resources/instances/instances.qrc
|
||||
resources/versions/versions.qrc
|
||||
)
|
||||
|
||||
######## Windows resource files ########
|
||||
if(WIN32)
|
||||
set(MULTIMC_RCS resources/multimc.rc)
|
||||
endif()
|
||||
|
||||
####### X11 Stuff #######
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(Qt5X11Extras REQUIRED)
|
||||
set(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS} xcb Qt5::X11Extras)
|
||||
list(APPEND MULTIMC_SOURCES Platform_X11.cpp)
|
||||
else()
|
||||
list(APPEND MULTIMC_SOURCES Platform_Other.cpp)
|
||||
endif()
|
||||
|
||||
|
||||
# Link additional libraries
|
||||
if(WIN32)
|
||||
set(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS} Qt5::WinMain)
|
||||
endif(WIN32)
|
||||
|
||||
include_directories(../logic)
|
||||
|
||||
# Qt 5 stuff
|
||||
qt5_wrap_ui(MULTIMC_UI ${MULTIMC_UIS})
|
||||
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_logic xz-embedded unpack200 iconfix libUtil LogicalGui
|
||||
${QUAZIP_LIBRARIES} Qt5::Core Qt5::Xml Qt5::Widgets Qt5::Network Qt5::Concurrent Qt5::WebKitWidgets
|
||||
${MultiMC_LINK_ADDITIONAL_LIBS})
|
||||
|
||||
################################ INSTALLATION AND PACKAGING ################################
|
||||
|
||||
######## Install ########
|
||||
|
||||
#### Executable ####
|
||||
if(APPLE AND UNIX) ## OSX
|
||||
install(TARGETS MultiMC
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION MultiMC.app/Contents/MacOS COMPONENT Runtime
|
||||
)
|
||||
|
||||
elseif(UNIX) ## LINUX and similar
|
||||
install(TARGETS MultiMC
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION bin COMPONENT Runtime
|
||||
)
|
||||
install(PROGRAMS package/linux/MultiMC DESTINATION .)
|
||||
|
||||
elseif(WIN32) ## WINDOWS
|
||||
install(TARGETS MultiMC
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
LIBRARY DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION . COMPONENT Runtime
|
||||
)
|
||||
endif()
|
||||
|
||||
#### Java bits ####
|
||||
install_jar(JavaCheck "${BINARY_DEST_DIR}/jars")
|
||||
install_jar(NewLaunch "${BINARY_DEST_DIR}/jars")
|
||||
|
||||
#### Dist package logic ####
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
# Image formats
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "tga|tiff|mng" EXCLUDE
|
||||
)
|
||||
# Icon engines
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "fontawesome" EXCLUDE
|
||||
)
|
||||
# Platform plugins
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "minimal|linuxfb|offscreen" EXCLUDE
|
||||
)
|
||||
else()
|
||||
# Image formats
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "tga|tiff|mng" EXCLUDE
|
||||
REGEX "d\\." EXCLUDE
|
||||
REGEX "_debug\\." EXCLUDE
|
||||
)
|
||||
# Icon engines
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "fontawesome" EXCLUDE
|
||||
REGEX "d\\." EXCLUDE
|
||||
REGEX "_debug\\." EXCLUDE
|
||||
)
|
||||
# Platform plugins
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "minimal|linuxfb|offscreen" EXCLUDE
|
||||
REGEX "d\\." EXCLUDE
|
||||
REGEX "_debug\\." EXCLUDE
|
||||
)
|
||||
if(APPLE)
|
||||
# Accessible plugin to make buttons look decent on osx
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/accessible"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "quick" EXCLUDE
|
||||
REGEX "d\\." EXCLUDE
|
||||
REGEX "_debug\\." EXCLUDE
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# qtconf
|
||||
install(
|
||||
CODE "
|
||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${QTCONF_DEST_DIR}/qt.conf\" \"\")
|
||||
"
|
||||
COMPONENT Runtime
|
||||
)
|
||||
|
||||
# ICNS file for OS X
|
||||
if(APPLE)
|
||||
install(FILES resources/MultiMC.icns DESTINATION MultiMC.app/Contents/Resources)
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/install_prereqs.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/install_prereqs.cmake"
|
||||
@ONLY
|
||||
)
|
||||
install(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/install_prereqs.cmake" COMPONENT Runtime)
|
||||
|
||||
|
||||
|
||||
######## Package ########
|
||||
|
||||
# Package with CPack
|
||||
if(UNIX)
|
||||
if(APPLE)
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
else()
|
||||
set(CPACK_GENERATOR "TGZ")
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
endif()
|
||||
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0)
|
||||
|
||||
set(CPACK_PACKAGE_NAME "MultiMC 5")
|
||||
set(CPACK_PACKAGE_VENDOR "")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MultiMC - Minecraft launcher and management tool.")
|
||||
set(CPACK_PACKAGE_VERSION "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${MultiMC_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${MultiMC_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${MultiMC_VERSION_REV})
|
||||
|
||||
set(CPACK_PACKAGE_FILE_NAME "MultiMC")
|
||||
|
||||
include(CPack)
|
202
application/ColumnResizer.cpp
Normal file
202
application/ColumnResizer.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright 2011 Aurélien Gâteau <agateau@kde.org>
|
||||
* License: LGPL v2.1 or later (see COPYING)
|
||||
*/
|
||||
#include "ColumnResizer.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QEvent>
|
||||
#include <QFormLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
class FormLayoutWidgetItem : public QWidgetItem
|
||||
{
|
||||
public:
|
||||
FormLayoutWidgetItem(QWidget* widget, QFormLayout* formLayout, QFormLayout::ItemRole itemRole)
|
||||
: QWidgetItem(widget)
|
||||
, m_width(-1)
|
||||
, m_formLayout(formLayout)
|
||||
, m_itemRole(itemRole)
|
||||
{}
|
||||
|
||||
QSize sizeHint() const
|
||||
{
|
||||
QSize size = QWidgetItem::sizeHint();
|
||||
if (m_width != -1) {
|
||||
size.setWidth(m_width);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
QSize minimumSize() const
|
||||
{
|
||||
QSize size = QWidgetItem::minimumSize();
|
||||
if (m_width != -1) {
|
||||
size.setWidth(m_width);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
QSize maximumSize() const
|
||||
{
|
||||
QSize size = QWidgetItem::maximumSize();
|
||||
if (m_width != -1) {
|
||||
size.setWidth(m_width);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void setWidth(int width)
|
||||
{
|
||||
if (width != m_width) {
|
||||
m_width = width;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void setGeometry(const QRect& _rect)
|
||||
{
|
||||
QRect rect = _rect;
|
||||
int width = widget()->sizeHint().width();
|
||||
if (m_itemRole == QFormLayout::LabelRole && m_formLayout->labelAlignment() & Qt::AlignRight) {
|
||||
rect.setLeft(rect.right() - width);
|
||||
}
|
||||
QWidgetItem::setGeometry(rect);
|
||||
}
|
||||
|
||||
QFormLayout* formLayout() const
|
||||
{
|
||||
return m_formLayout;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_width;
|
||||
QFormLayout* m_formLayout;
|
||||
QFormLayout::ItemRole m_itemRole;
|
||||
};
|
||||
|
||||
typedef QPair<QGridLayout*, int> GridColumnInfo;
|
||||
|
||||
class ColumnResizerPrivate
|
||||
{
|
||||
public:
|
||||
ColumnResizerPrivate(ColumnResizer* q_ptr)
|
||||
: q(q_ptr)
|
||||
, m_updateTimer(new QTimer(q))
|
||||
{
|
||||
m_updateTimer->setSingleShot(true);
|
||||
m_updateTimer->setInterval(0);
|
||||
QObject::connect(m_updateTimer, SIGNAL(timeout()), q, SLOT(updateWidth()));
|
||||
}
|
||||
|
||||
void scheduleWidthUpdate()
|
||||
{
|
||||
m_updateTimer->start();
|
||||
}
|
||||
|
||||
ColumnResizer* q;
|
||||
QTimer* m_updateTimer;
|
||||
QList<QWidget*> m_widgets;
|
||||
QList<FormLayoutWidgetItem*> m_wrWidgetItemList;
|
||||
QList<GridColumnInfo> m_gridColumnInfoList;
|
||||
};
|
||||
|
||||
ColumnResizer::ColumnResizer(QObject* parent)
|
||||
: QObject(parent)
|
||||
, d(new ColumnResizerPrivate(this))
|
||||
{}
|
||||
|
||||
ColumnResizer::~ColumnResizer()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void ColumnResizer::addWidget(QWidget* widget)
|
||||
{
|
||||
d->m_widgets.append(widget);
|
||||
widget->installEventFilter(this);
|
||||
d->scheduleWidthUpdate();
|
||||
}
|
||||
|
||||
void ColumnResizer::updateWidth()
|
||||
{
|
||||
int width = 0;
|
||||
Q_FOREACH(QWidget* widget, d->m_widgets) {
|
||||
width = qMax(widget->sizeHint().width(), width);
|
||||
}
|
||||
Q_FOREACH(FormLayoutWidgetItem* item, d->m_wrWidgetItemList) {
|
||||
item->setWidth(width);
|
||||
item->formLayout()->update();
|
||||
}
|
||||
Q_FOREACH(GridColumnInfo info, d->m_gridColumnInfoList) {
|
||||
info.first->setColumnMinimumWidth(info.second, width);
|
||||
}
|
||||
}
|
||||
|
||||
bool ColumnResizer::eventFilter(QObject*, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::Resize) {
|
||||
d->scheduleWidthUpdate();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ColumnResizer::addWidgetsFromLayout(QLayout* layout, int column)
|
||||
{
|
||||
Q_ASSERT(column >= 0);
|
||||
QGridLayout* gridLayout = qobject_cast<QGridLayout*>(layout);
|
||||
QFormLayout* formLayout = qobject_cast<QFormLayout*>(layout);
|
||||
if (gridLayout) {
|
||||
addWidgetsFromGridLayout(gridLayout, column);
|
||||
} else if (formLayout) {
|
||||
if (column > QFormLayout::SpanningRole) {
|
||||
qCritical() << "column should not be more than" << QFormLayout::SpanningRole << "for QFormLayout";
|
||||
return;
|
||||
}
|
||||
QFormLayout::ItemRole role = static_cast<QFormLayout::ItemRole>(column);
|
||||
addWidgetsFromFormLayout(formLayout, role);
|
||||
} else {
|
||||
qCritical() << "Don't know how to handle layout" << layout;
|
||||
}
|
||||
}
|
||||
|
||||
void ColumnResizer::addWidgetsFromGridLayout(QGridLayout* layout, int column)
|
||||
{
|
||||
for (int row = 0; row < layout->rowCount(); ++row) {
|
||||
QLayoutItem* item = layout->itemAtPosition(row, column);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
QWidget* widget = item->widget();
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
addWidget(widget);
|
||||
}
|
||||
d->m_gridColumnInfoList << GridColumnInfo(layout, column);
|
||||
}
|
||||
|
||||
void ColumnResizer::addWidgetsFromFormLayout(QFormLayout* layout, QFormLayout::ItemRole role)
|
||||
{
|
||||
for (int row = 0; row < layout->rowCount(); ++row) {
|
||||
QLayoutItem* item = layout->itemAt(row, role);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
QWidget* widget = item->widget();
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
layout->removeItem(item);
|
||||
delete item;
|
||||
FormLayoutWidgetItem* newItem = new FormLayoutWidgetItem(widget, layout, role);
|
||||
layout->setItem(row, role, newItem);
|
||||
addWidget(widget);
|
||||
d->m_wrWidgetItemList << newItem;
|
||||
}
|
||||
}
|
||||
|
||||
#include <ColumnResizer.moc>
|
||||
// vi: ts=4 sw=4 et
|
38
application/ColumnResizer.h
Normal file
38
application/ColumnResizer.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2011 Aurélien Gâteau <agateau@kde.org>
|
||||
* License: LGPL v2.1 or later (see COPYING)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QFormLayout>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QList>
|
||||
|
||||
class QEvent;
|
||||
class QGridLayout;
|
||||
class QLayout;
|
||||
class QWidget;
|
||||
|
||||
class ColumnResizerPrivate;
|
||||
class ColumnResizer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColumnResizer(QObject* parent = 0);
|
||||
~ColumnResizer();
|
||||
|
||||
void addWidget(QWidget* widget);
|
||||
void addWidgetsFromLayout(QLayout*, int column);
|
||||
void addWidgetsFromGridLayout(QGridLayout*, int column);
|
||||
void addWidgetsFromFormLayout(QFormLayout*, QFormLayout::ItemRole role);
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateWidth();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject*, QEvent* event);
|
||||
|
||||
private:
|
||||
ColumnResizerPrivate* const d;
|
||||
};
|
260
application/ConsoleWindow.cpp
Normal file
260
application/ConsoleWindow.cpp
Normal file
@ -0,0 +1,260 @@
|
||||
/* Copyright 2013-2015 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 "ConsoleWindow.h"
|
||||
#include "MultiMC.h"
|
||||
|
||||
#include <QScrollBar>
|
||||
#include <QMessageBox>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <qlayoutitem.h>
|
||||
#include <QCloseEvent>
|
||||
|
||||
#include <Platform.h>
|
||||
#include <dialogs/CustomMessageBox.h>
|
||||
#include <dialogs/ProgressDialog.h>
|
||||
#include "widgets/PageContainer.h"
|
||||
#include "pages/LogPage.h"
|
||||
#include "InstancePageProvider.h"
|
||||
|
||||
#include "icons/IconList.h"
|
||||
|
||||
class LogPageProvider : public BasePageProvider
|
||||
{
|
||||
public:
|
||||
LogPageProvider(BasePageProviderPtr parent, BasePage * log_page)
|
||||
{
|
||||
m_parent = parent;
|
||||
m_log_page = log_page;
|
||||
}
|
||||
virtual QString dialogTitle() {return "Fake";};
|
||||
virtual QList<BasePage *> getPages()
|
||||
{
|
||||
auto pages = m_parent->getPages();
|
||||
pages.prepend(m_log_page);
|
||||
return pages;
|
||||
}
|
||||
private:
|
||||
BasePageProviderPtr m_parent;
|
||||
BasePage * m_log_page;
|
||||
};
|
||||
|
||||
ConsoleWindow::ConsoleWindow(BaseProcess *process, QWidget *parent)
|
||||
: QMainWindow(parent), m_proc(process)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
auto instance = m_proc->instance();
|
||||
auto icon = ENV.icons()->getIcon(instance->iconKey());
|
||||
QString windowTitle = tr("Console window for ") + instance->name();
|
||||
|
||||
// Set window properties
|
||||
{
|
||||
setWindowIcon(icon);
|
||||
setWindowTitle(windowTitle);
|
||||
}
|
||||
|
||||
// Add page container
|
||||
{
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
auto provider = std::make_shared<InstancePageProvider>(m_proc->instance());
|
||||
auto baseprovider = std::dynamic_pointer_cast<BasePageProvider>(provider);
|
||||
auto proxy_provider = std::make_shared<LogPageProvider>(baseprovider, new LogPage(m_proc));
|
||||
m_container = new PageContainer(proxy_provider, "console", this);
|
||||
mainLayout->addWidget(m_container);
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->setContentsMargins(0,0,0,0);
|
||||
setLayout(mainLayout);
|
||||
setCentralWidget(m_container);
|
||||
}
|
||||
|
||||
// Add custom buttons to the page container layout.
|
||||
{
|
||||
auto horizontalLayout = new QHBoxLayout();
|
||||
horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
|
||||
horizontalLayout->setContentsMargins(6, -1, 6, -1);
|
||||
|
||||
auto btnHelp = new QPushButton();
|
||||
btnHelp->setText(tr("Help"));
|
||||
horizontalLayout->addWidget(btnHelp);
|
||||
connect(btnHelp, SIGNAL(clicked(bool)), m_container, SLOT(help()));
|
||||
|
||||
auto spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
horizontalLayout->addSpacerItem(spacer);
|
||||
|
||||
m_killButton = new QPushButton();
|
||||
m_killButton->setText(tr("Kill Minecraft"));
|
||||
horizontalLayout->addWidget(m_killButton);
|
||||
connect(m_killButton, SIGNAL(clicked(bool)), SLOT(on_btnKillMinecraft_clicked()));
|
||||
|
||||
m_closeButton = new QPushButton();
|
||||
m_closeButton->setText(tr("Close"));
|
||||
horizontalLayout->addWidget(m_closeButton);
|
||||
connect(m_closeButton, SIGNAL(clicked(bool)), SLOT(on_closeButton_clicked()));
|
||||
|
||||
m_container->addButtons(horizontalLayout);
|
||||
}
|
||||
|
||||
// restore window state
|
||||
{
|
||||
auto base64State = MMC->settings()->get("ConsoleWindowState").toByteArray();
|
||||
restoreState(QByteArray::fromBase64(base64State));
|
||||
auto base64Geometry = MMC->settings()->get("ConsoleWindowGeometry").toByteArray();
|
||||
restoreGeometry(QByteArray::fromBase64(base64Geometry));
|
||||
}
|
||||
|
||||
// Set up tray icon
|
||||
{
|
||||
m_trayIcon = new QSystemTrayIcon(icon, this);
|
||||
m_trayIcon->setToolTip(windowTitle);
|
||||
|
||||
connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
|
||||
SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
|
||||
m_trayIcon->show();
|
||||
}
|
||||
|
||||
// Set up signal connections
|
||||
connect(m_proc, SIGNAL(ended(InstancePtr, int, QProcess::ExitStatus)), this,
|
||||
SLOT(onEnded(InstancePtr, int, QProcess::ExitStatus)));
|
||||
connect(m_proc, SIGNAL(prelaunch_failed(InstancePtr, int, QProcess::ExitStatus)), this,
|
||||
SLOT(onEnded(InstancePtr, int, QProcess::ExitStatus)));
|
||||
connect(m_proc, SIGNAL(launch_failed(InstancePtr)), this,
|
||||
SLOT(onLaunchFailed(InstancePtr)));
|
||||
|
||||
setMayClose(false);
|
||||
|
||||
if (m_proc->instance()->settings().get("ShowConsole").toBool())
|
||||
{
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
|
||||
{
|
||||
switch (reason)
|
||||
{
|
||||
case QSystemTrayIcon::Trigger:
|
||||
{
|
||||
toggleConsole();
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::on_closeButton_clicked()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void ConsoleWindow::setMayClose(bool mayclose)
|
||||
{
|
||||
if(mayclose)
|
||||
m_closeButton->setText(tr("Close"));
|
||||
else
|
||||
m_closeButton->setText(tr("Hide"));
|
||||
m_mayclose = mayclose;
|
||||
}
|
||||
|
||||
void ConsoleWindow::toggleConsole()
|
||||
{
|
||||
if (isVisible())
|
||||
{
|
||||
if(!isActiveWindow())
|
||||
{
|
||||
activateWindow();
|
||||
return;
|
||||
}
|
||||
hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if (!m_mayclose)
|
||||
{
|
||||
toggleConsole();
|
||||
event->ignore();
|
||||
}
|
||||
else if(m_container->requestClose(event))
|
||||
{
|
||||
MMC->settings()->set("ConsoleWindowState", saveState().toBase64());
|
||||
MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
|
||||
|
||||
emit isClosing();
|
||||
m_trayIcon->hide();
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::on_btnKillMinecraft_clicked()
|
||||
{
|
||||
m_killButton->setEnabled(false);
|
||||
auto response = CustomMessageBox::selectable(
|
||||
this, tr("Kill Minecraft?"),
|
||||
tr("This can cause the instance to get corrupted and should only be used if Minecraft "
|
||||
"is frozen for some reason"),
|
||||
QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec();
|
||||
if (response == QMessageBox::Yes)
|
||||
m_proc->killProcess();
|
||||
else
|
||||
m_killButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void ConsoleWindow::onEnded(InstancePtr instance, int code, QProcess::ExitStatus status)
|
||||
{
|
||||
bool peacefulExit = code == 0 && status != QProcess::CrashExit;
|
||||
m_killButton->setEnabled(false);
|
||||
setMayClose(true);
|
||||
if (instance->settings().get("AutoCloseConsole").toBool())
|
||||
{
|
||||
if (peacefulExit)
|
||||
{
|
||||
this->close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!isVisible())
|
||||
{
|
||||
show();
|
||||
}
|
||||
// Raise Window
|
||||
if (MMC->settings()->get("RaiseConsole").toBool())
|
||||
{
|
||||
raise();
|
||||
activateWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::onLaunchFailed(InstancePtr instance)
|
||||
{
|
||||
m_killButton->setEnabled(false);
|
||||
|
||||
setMayClose(true);
|
||||
|
||||
if (!isVisible())
|
||||
show();
|
||||
}
|
||||
ConsoleWindow::~ConsoleWindow()
|
||||
{
|
||||
|
||||
}
|
65
application/ConsoleWindow.h
Normal file
65
application/ConsoleWindow.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* Copyright 2013-2015 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 <QMainWindow>
|
||||
#include <QSystemTrayIcon>
|
||||
#include "BaseProcess.h"
|
||||
|
||||
class QPushButton;
|
||||
class PageContainer;
|
||||
class ConsoleWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConsoleWindow(BaseProcess *proc, QWidget *parent = 0);
|
||||
virtual ~ConsoleWindow();
|
||||
|
||||
/**
|
||||
* @brief specify if the window is allowed to close
|
||||
* @param mayclose
|
||||
* used to keep it alive while MC runs
|
||||
*/
|
||||
void setMayClose(bool mayclose);
|
||||
|
||||
signals:
|
||||
void isClosing();
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_closeButton_clicked();
|
||||
void on_btnKillMinecraft_clicked();
|
||||
|
||||
void onEnded(InstancePtr instance, int code, QProcess::ExitStatus status);
|
||||
void onLaunchFailed(InstancePtr instance);
|
||||
|
||||
// FIXME: add handlers for the other MinecraftProcess signals (pre/post launch command
|
||||
// failures)
|
||||
|
||||
void iconActivated(QSystemTrayIcon::ActivationReason);
|
||||
void toggleConsole();
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *);
|
||||
|
||||
private:
|
||||
BaseProcess *m_proc = nullptr;
|
||||
bool m_mayclose = true;
|
||||
QSystemTrayIcon *m_trayIcon = nullptr;
|
||||
PageContainer *m_container = nullptr;
|
||||
QPushButton *m_closeButton = nullptr;
|
||||
QPushButton *m_killButton = nullptr;
|
||||
};
|
48
application/GuiUtil.cpp
Normal file
48
application/GuiUtil.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include "GuiUtil.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QDesktopServices>
|
||||
#include <QApplication>
|
||||
|
||||
#include "dialogs/ProgressDialog.h"
|
||||
#include "net/PasteUpload.h"
|
||||
#include "dialogs/CustomMessageBox.h"
|
||||
|
||||
void GuiUtil::uploadPaste(const QString &text, QWidget *parentWidget)
|
||||
{
|
||||
ProgressDialog dialog(parentWidget);
|
||||
std::unique_ptr<PasteUpload> paste(new PasteUpload(parentWidget, text));
|
||||
|
||||
if (!paste->validateText())
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
parentWidget, QObject::tr("Upload failed"),
|
||||
QObject::tr("The log file is too big. You'll have to upload it manually."),
|
||||
QMessageBox::Warning)->exec();
|
||||
return;
|
||||
}
|
||||
|
||||
dialog.exec(paste.get());
|
||||
if (!paste->successful())
|
||||
{
|
||||
CustomMessageBox::selectable(parentWidget, QObject::tr("Upload failed"),
|
||||
paste->failReason(), QMessageBox::Critical)->exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
const QString link = paste->pasteLink();
|
||||
setClipboardText(link);
|
||||
QDesktopServices::openUrl(link);
|
||||
CustomMessageBox::selectable(
|
||||
parentWidget, QObject::tr("Upload finished"),
|
||||
QObject::tr("The <a href=\"%1\">link to the uploaded log</a> has been opened in "
|
||||
"the default "
|
||||
"browser and placed in your clipboard.").arg(link),
|
||||
QMessageBox::Information)->exec();
|
||||
}
|
||||
}
|
||||
|
||||
void GuiUtil::setClipboardText(const QString &text)
|
||||
{
|
||||
QApplication::clipboard()->setText(text);
|
||||
}
|
9
application/GuiUtil.h
Normal file
9
application/GuiUtil.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace GuiUtil
|
||||
{
|
||||
void uploadPaste(const QString &text, QWidget *parentWidget);
|
||||
void setClipboardText(const QString &text);
|
||||
}
|
0
application/InstancePageProvider.cpp
Normal file
0
application/InstancePageProvider.cpp
Normal file
52
application/InstancePageProvider.h
Normal file
52
application/InstancePageProvider.h
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
#include "minecraft/OneSixInstance.h"
|
||||
#include "pages/BasePage.h"
|
||||
#include "pages/VersionPage.h"
|
||||
#include "pages/ModFolderPage.h"
|
||||
#include "pages/ResourcePackPage.h"
|
||||
#include "pages/TexturePackPage.h"
|
||||
#include "pages/NotesPage.h"
|
||||
#include "pages/ScreenshotsPage.h"
|
||||
#include "pages/InstanceSettingsPage.h"
|
||||
#include "pages/OtherLogsPage.h"
|
||||
#include "pages/BasePageProvider.h"
|
||||
#include <pathutils.h>
|
||||
|
||||
class InstancePageProvider : public QObject, public BasePageProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InstancePageProvider(InstancePtr parent)
|
||||
{
|
||||
inst = parent;
|
||||
}
|
||||
|
||||
virtual ~InstancePageProvider() {};
|
||||
virtual QList<BasePage *> getPages() override
|
||||
{
|
||||
QList<BasePage *> values;
|
||||
std::shared_ptr<OneSixInstance> onesix = std::dynamic_pointer_cast<OneSixInstance>(inst);
|
||||
if(onesix)
|
||||
{
|
||||
values.append(new VersionPage(onesix.get()));
|
||||
values.append(new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods",
|
||||
tr("Loader mods"), "Loader-mods"));
|
||||
values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList(), "coremods", "coremods",
|
||||
tr("Core mods"), "Core-mods"));
|
||||
values.append(new ResourcePackPage(onesix.get()));
|
||||
values.append(new TexturePackPage(onesix.get()));
|
||||
values.append(new NotesPage(onesix.get()));
|
||||
values.append(new ScreenshotsPage(PathCombine(onesix->minecraftRoot(), "screenshots")));
|
||||
values.append(new InstanceSettingsPage(onesix.get()));
|
||||
values.append(new OtherLogsPage(onesix->minecraftRoot()));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
virtual QString dialogTitle() override
|
||||
{
|
||||
return tr("Edit Instance (%1)").arg(inst->name());
|
||||
}
|
||||
protected:
|
||||
InstancePtr inst;
|
||||
};
|
23
application/InstanceProxyModel.cpp
Normal file
23
application/InstanceProxyModel.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "InstanceProxyModel.h"
|
||||
#include "MultiMC.h"
|
||||
#include <BaseInstance.h>
|
||||
|
||||
InstanceProxyModel::InstanceProxyModel(QObject *parent) : GroupedProxyModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool InstanceProxyModel::subSortLessThan(const QModelIndex &left,
|
||||
const QModelIndex &right) const
|
||||
{
|
||||
BaseInstance *pdataLeft = static_cast<BaseInstance *>(left.internalPointer());
|
||||
BaseInstance *pdataRight = static_cast<BaseInstance *>(right.internalPointer());
|
||||
QString sortMode = MMC->settings()->get("InstSortMode").toString();
|
||||
if (sortMode == "LastLaunch")
|
||||
{
|
||||
return pdataLeft->lastLaunch() > pdataRight->lastLaunch();
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString::localeAwareCompare(pdataLeft->name(), pdataRight->name()) < 0;
|
||||
}
|
||||
}
|
13
application/InstanceProxyModel.h
Normal file
13
application/InstanceProxyModel.h
Normal file
@ -0,0 +1,13 @@
|
||||
#include "groupview/GroupedProxyModel.h"
|
||||
|
||||
/**
|
||||
* A proxy model that is responsible for sorting instances into groups
|
||||
*/
|
||||
class InstanceProxyModel : public GroupedProxyModel
|
||||
{
|
||||
public:
|
||||
explicit InstanceProxyModel(QObject *parent = 0);
|
||||
|
||||
protected:
|
||||
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||
};
|
2069
application/MainWindow.cpp
Normal file
2069
application/MainWindow.cpp
Normal file
File diff suppressed because it is too large
Load Diff
218
application/MainWindow.h
Normal file
218
application/MainWindow.h
Normal file
@ -0,0 +1,218 @@
|
||||
/* Copyright 2013-2015 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 <QMainWindow>
|
||||
#include <QProcess>
|
||||
#include <QTimer>
|
||||
|
||||
#include "BaseInstance.h"
|
||||
#include "auth/MojangAccount.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "updater/GoUpdate.h"
|
||||
|
||||
class NewsChecker;
|
||||
class NotificationChecker;
|
||||
class QToolButton;
|
||||
class InstanceProxyModel;
|
||||
class LabeledToolButton;
|
||||
class QLabel;
|
||||
class MinecraftProcess;
|
||||
class ConsoleWindow;
|
||||
class BaseProfilerFactory;
|
||||
class GenericPageProvider;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
void closeEvent(QCloseEvent *event);
|
||||
|
||||
// Browser Dialog
|
||||
void openWebPage(QUrl url);
|
||||
|
||||
void checkSetDefaultJava();
|
||||
void checkInstancePathForProblems();
|
||||
|
||||
private
|
||||
slots:
|
||||
void onCatToggled(bool);
|
||||
|
||||
void on_actionAbout_triggered();
|
||||
|
||||
void on_actionAddInstance_triggered();
|
||||
|
||||
void on_actionCopyInstance_triggered();
|
||||
|
||||
void on_actionChangeInstGroup_triggered();
|
||||
|
||||
void on_actionChangeInstIcon_triggered();
|
||||
|
||||
void on_actionViewInstanceFolder_triggered();
|
||||
|
||||
void on_actionConfig_Folder_triggered();
|
||||
|
||||
void on_actionViewSelectedInstFolder_triggered();
|
||||
|
||||
void on_actionRefresh_triggered();
|
||||
|
||||
void on_actionViewCentralModsFolder_triggered();
|
||||
|
||||
void on_actionCheckUpdate_triggered();
|
||||
|
||||
void on_actionSettings_triggered();
|
||||
|
||||
void on_actionInstanceSettings_triggered();
|
||||
|
||||
void on_actionManageAccounts_triggered();
|
||||
|
||||
void on_actionReportBug_triggered();
|
||||
|
||||
void on_actionPatreon_triggered();
|
||||
|
||||
void on_actionMoreNews_triggered();
|
||||
|
||||
void newsButtonClicked();
|
||||
|
||||
void on_mainToolBar_visibilityChanged(bool);
|
||||
|
||||
// void on_instanceView_customContextMenuRequested(const QPoint &pos);
|
||||
|
||||
void on_actionLaunchInstance_triggered();
|
||||
|
||||
void on_actionLaunchInstanceOffline_triggered();
|
||||
|
||||
void on_actionDeleteInstance_triggered();
|
||||
|
||||
void on_actionExportInstance_triggered();
|
||||
|
||||
void on_actionRenameInstance_triggered();
|
||||
|
||||
void on_actionEditInstance_triggered();
|
||||
|
||||
void on_actionEditInstNotes_triggered();
|
||||
|
||||
void on_actionScreenshots_triggered();
|
||||
|
||||
/*!
|
||||
* Launches the currently selected instance with the default account.
|
||||
* If no default account is selected, prompts the user to pick an account.
|
||||
*/
|
||||
void doLaunch(bool online = true, BaseProfilerFactory *profiler = 0);
|
||||
|
||||
/*!
|
||||
* Launches the given instance with the given account.
|
||||
* This function assumes that the given account has a valid, usable access token.
|
||||
*/
|
||||
void launchInstance(InstancePtr instance, AuthSessionPtr session, BaseProfilerFactory *profiler = 0);
|
||||
|
||||
/*!
|
||||
* Prepares the given instance for launch with the given account.
|
||||
*/
|
||||
void updateInstance(InstancePtr instance, AuthSessionPtr account, BaseProfilerFactory *profiler = 0);
|
||||
|
||||
void onGameUpdateError(QString error);
|
||||
|
||||
void taskStart();
|
||||
void taskEnd();
|
||||
|
||||
void instanceEnded();
|
||||
|
||||
// called when an icon is changed in the icon model.
|
||||
void iconUpdated(QString);
|
||||
|
||||
void showInstanceContextMenu(const QPoint &);
|
||||
|
||||
void updateToolsMenu();
|
||||
|
||||
void skinJobFinished();
|
||||
public
|
||||
slots:
|
||||
void instanceActivated(QModelIndex);
|
||||
|
||||
void instanceChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
|
||||
void selectionBad();
|
||||
|
||||
void startTask(Task *task);
|
||||
|
||||
void updateAvailable(GoUpdate::Status status);
|
||||
|
||||
void updateNotAvailable();
|
||||
|
||||
void notificationsChanged();
|
||||
|
||||
void activeAccountChanged();
|
||||
|
||||
void changeActiveAccount();
|
||||
|
||||
void repopulateAccountsMenu();
|
||||
|
||||
void updateNewsLabel();
|
||||
|
||||
/*!
|
||||
* Runs the DownloadTask and installs updates.
|
||||
*/
|
||||
void downloadUpdates(GoUpdate::Status status, bool installOnExit = false);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *ev);
|
||||
void setCatBackground(bool enabled);
|
||||
void updateInstanceToolIcon(QString new_icon);
|
||||
|
||||
void setSelectedInstanceById(const QString &id);
|
||||
|
||||
void waitForMinecraftVersions();
|
||||
void instanceFromVersion(QString instName, QString instGroup, QString instIcon, BaseVersionPtr version);
|
||||
void instanceFromZipPack(QString instName, QString instGroup, QString instIcon, QUrl url);
|
||||
void finalizeInstance(InstancePtr inst);
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
class GroupView *view;
|
||||
InstanceProxyModel *proxymodel;
|
||||
NetJobPtr skin_download_job;
|
||||
MinecraftProcess *proc;
|
||||
ConsoleWindow *console;
|
||||
LabeledToolButton *renameButton;
|
||||
QToolButton *changeIconButton;
|
||||
QToolButton *newsLabel;
|
||||
|
||||
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
|
||||
std::shared_ptr<NewsChecker> m_newsChecker;
|
||||
std::shared_ptr<NotificationChecker> m_notificationChecker;
|
||||
|
||||
InstancePtr m_selectedInstance;
|
||||
QString m_currentInstIcon;
|
||||
|
||||
Task *m_versionLoadTask;
|
||||
|
||||
QLabel *m_statusLeft;
|
||||
class ServerStatus *m_statusRight;
|
||||
|
||||
QMenu *accountMenu;
|
||||
QToolButton *accountMenuButton;
|
||||
QAction *manageAccountsAction;
|
||||
};
|
632
application/MultiMC.cpp
Normal file
632
application/MultiMC.cpp
Normal file
@ -0,0 +1,632 @@
|
||||
#include "MultiMC.h"
|
||||
#include "BuildConfig.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QTranslator>
|
||||
#include <QLibraryInfo>
|
||||
#include <QMessageBox>
|
||||
#include <QStringList>
|
||||
#include <QDesktopServices>
|
||||
#include <QDebug>
|
||||
|
||||
#include "dialogs/VersionSelectDialog.h"
|
||||
#include "InstanceList.h"
|
||||
#include "auth/MojangAccountList.h"
|
||||
#include "icons/IconList.h"
|
||||
#include "minecraft/LwjglVersionList.h"
|
||||
#include "minecraft/MinecraftVersionList.h"
|
||||
#include "liteloader/LiteLoaderVersionList.h"
|
||||
|
||||
#include "forge/ForgeVersionList.h"
|
||||
|
||||
#include "net/HttpMetaCache.h"
|
||||
#include "net/URLConstants.h"
|
||||
#include "Env.h"
|
||||
|
||||
#include "java/JavaUtils.h"
|
||||
|
||||
#include "updater/UpdateChecker.h"
|
||||
|
||||
#include "tools/JProfiler.h"
|
||||
#include "tools/JVisualVM.h"
|
||||
#include "tools/MCEditTool.h"
|
||||
|
||||
#include "pathutils.h"
|
||||
#include "cmdutils.h"
|
||||
#include <xdgicon.h>
|
||||
#include "settings/INISettingsObject.h"
|
||||
#include "settings/Setting.h"
|
||||
|
||||
#include "trans/TranslationDownloader.h"
|
||||
|
||||
#include "ftb/FTBPlugin.h"
|
||||
|
||||
using namespace Util::Commandline;
|
||||
|
||||
MultiMC::MultiMC(int &argc, char **argv, bool test_mode) : QApplication(argc, argv)
|
||||
{
|
||||
setOrganizationName("MultiMC");
|
||||
setApplicationName("MultiMC5");
|
||||
|
||||
startTime = QDateTime::currentDateTime();
|
||||
|
||||
setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
// Don't quit on hiding the last window
|
||||
this->setQuitOnLastWindowClosed(false);
|
||||
|
||||
// Commandline parsing
|
||||
QHash<QString, QVariant> args;
|
||||
{
|
||||
Parser parser(FlagStyle::GNU, ArgumentStyle::SpaceAndEquals);
|
||||
|
||||
// --help
|
||||
parser.addSwitch("help");
|
||||
parser.addShortOpt("help", 'h');
|
||||
parser.addDocumentation("help", "display this help and exit.");
|
||||
// --version
|
||||
parser.addSwitch("version");
|
||||
parser.addShortOpt("version", 'V');
|
||||
parser.addDocumentation("version", "display program version and exit.");
|
||||
// --dir
|
||||
parser.addOption("dir", applicationDirPath());
|
||||
parser.addShortOpt("dir", 'd');
|
||||
parser.addDocumentation("dir", "use the supplied directory as MultiMC root instead of "
|
||||
"the binary location (use '.' for current)");
|
||||
|
||||
// parse the arguments
|
||||
try
|
||||
{
|
||||
args = parser.parse(arguments());
|
||||
}
|
||||
catch (ParsingError e)
|
||||
{
|
||||
std::cerr << "CommandLineError: " << e.what() << std::endl;
|
||||
std::cerr << "Try '%1 -h' to get help on MultiMC's command line parameters."
|
||||
<< std::endl;
|
||||
m_status = MultiMC::Failed;
|
||||
return;
|
||||
}
|
||||
|
||||
// display help and exit
|
||||
if (args["help"].toBool())
|
||||
{
|
||||
std::cout << qPrintable(parser.compileHelp(arguments()[0]));
|
||||
m_status = MultiMC::Succeeded;
|
||||
return;
|
||||
}
|
||||
|
||||
// display version and exit
|
||||
if (args["version"].toBool())
|
||||
{
|
||||
std::cout << "Version " << BuildConfig.VERSION_STR.toStdString() << std::endl;
|
||||
std::cout << "Git " << BuildConfig.GIT_COMMIT.toStdString() << std::endl;
|
||||
m_status = MultiMC::Succeeded;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QString origcwdPath = QDir::currentPath();
|
||||
QString binPath = applicationDirPath();
|
||||
QString adjustedBy;
|
||||
// change directory
|
||||
QString dirParam = args["dir"].toString();
|
||||
if (!dirParam.isEmpty())
|
||||
{
|
||||
// the dir param. it makes multimc data path point to whatever the user specified
|
||||
// on command line
|
||||
adjustedBy += "Command line " + dirParam;
|
||||
dataPath = dirParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
dataPath = applicationDirPath();
|
||||
adjustedBy += "Fallback to binary path " + dataPath;
|
||||
}
|
||||
|
||||
if (!ensureFolderPathExists(dataPath) || !QDir::setCurrent(dataPath))
|
||||
{
|
||||
// BAD STUFF. WHAT DO?
|
||||
initLogger();
|
||||
qCritical() << "Failed to set work path. Will exit. NOW.";
|
||||
m_status = MultiMC::Failed;
|
||||
return;
|
||||
}
|
||||
|
||||
// in test mode, root path is the same as the binary path.
|
||||
if (test_mode)
|
||||
{
|
||||
rootPath = binPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
QDir foo(PathCombine(binPath, ".."));
|
||||
rootPath = foo.absolutePath();
|
||||
#elif defined(Q_OS_WIN32)
|
||||
rootPath = binPath;
|
||||
#elif defined(Q_OS_MAC)
|
||||
QDir foo(PathCombine(binPath, "../.."));
|
||||
rootPath = foo.absolutePath();
|
||||
#endif
|
||||
}
|
||||
|
||||
// static data paths... mostly just for translations
|
||||
#ifdef Q_OS_LINUX
|
||||
QDir foo(PathCombine(binPath, ".."));
|
||||
staticDataPath = foo.absolutePath();
|
||||
#elif defined(Q_OS_WIN32)
|
||||
staticDataPath = binPath;
|
||||
#elif defined(Q_OS_MAC)
|
||||
QDir foo(PathCombine(rootPath, "Contents/Resources"));
|
||||
staticDataPath = foo.absolutePath();
|
||||
#endif
|
||||
|
||||
// init the logger
|
||||
initLogger();
|
||||
|
||||
qDebug() << "MultiMC 5, (c) 2013-2015 MultiMC Contributors";
|
||||
qDebug() << "Version : " << BuildConfig.VERSION_STR;
|
||||
qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
|
||||
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 : " << rootPath;
|
||||
qDebug() << "Static data path : " << staticDataPath;
|
||||
|
||||
// load settings
|
||||
initGlobalSettings(test_mode);
|
||||
|
||||
// load translations
|
||||
initTranslations();
|
||||
|
||||
// initialize the updater
|
||||
m_updateChecker.reset(new UpdateChecker(BuildConfig.CHANLIST_URL, BuildConfig.VERSION_CHANNEL, BuildConfig.VERSION_BUILD));
|
||||
|
||||
m_translationChecker.reset(new TranslationDownloader());
|
||||
|
||||
// load icons
|
||||
initIcons();
|
||||
|
||||
// and 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 = m_settings->get("InstanceDir").toString();
|
||||
qDebug() << "Instance path : " << instDir;
|
||||
if (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));
|
||||
qDebug() << "Loading Instances...";
|
||||
m_instances->loadList();
|
||||
connect(InstDirSetting.get(), SIGNAL(SettingChanged(const Setting &, QVariant)),
|
||||
m_instances.get(), SLOT(on_InstFolderChanged(const Setting &, QVariant)));
|
||||
|
||||
// and accounts
|
||||
m_accounts.reset(new MojangAccountList(this));
|
||||
qDebug() << "Loading accounts...";
|
||||
m_accounts->setListFilePath("accounts.json", true);
|
||||
m_accounts->loadList();
|
||||
|
||||
// init the http meta cache
|
||||
ENV.initHttpMetaCache(rootPath, staticDataPath);
|
||||
|
||||
// create the global network manager
|
||||
ENV.m_qnam.reset(new QNetworkAccessManager(this));
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
m_translationChecker->downloadTranslations();
|
||||
|
||||
//FIXME: what to do with these?
|
||||
m_profilers.insert("jprofiler",
|
||||
std::shared_ptr<BaseProfilerFactory>(new JProfilerFactory()));
|
||||
m_profilers.insert("jvisualvm",
|
||||
std::shared_ptr<BaseProfilerFactory>(new JVisualVMFactory()));
|
||||
for (auto profiler : m_profilers.values())
|
||||
{
|
||||
profiler->registerSettings(m_settings);
|
||||
}
|
||||
|
||||
//FIXME: what to do with these?
|
||||
m_tools.insert("mcedit", std::shared_ptr<BaseDetachedToolFactory>(new MCEditFactory()));
|
||||
for (auto tool : m_tools.values())
|
||||
{
|
||||
tool->registerSettings(m_settings);
|
||||
}
|
||||
|
||||
connect(this, SIGNAL(aboutToQuit()), SLOT(onExit()));
|
||||
m_status = MultiMC::Initialized;
|
||||
}
|
||||
|
||||
MultiMC::~MultiMC()
|
||||
{
|
||||
if (m_mmc_translator)
|
||||
{
|
||||
removeTranslator(m_mmc_translator.get());
|
||||
}
|
||||
if (m_qt_translator)
|
||||
{
|
||||
removeTranslator(m_qt_translator.get());
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMC::initTranslations()
|
||||
{
|
||||
QLocale locale(m_settings->get("Language").toString());
|
||||
QLocale::setDefault(locale);
|
||||
qDebug() << "Your language is" << locale.bcp47Name();
|
||||
m_qt_translator.reset(new QTranslator());
|
||||
if (m_qt_translator->load("qt_" + locale.bcp47Name(),
|
||||
QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
||||
{
|
||||
qDebug() << "Loading Qt Language File for"
|
||||
<< locale.bcp47Name().toLocal8Bit().constData() << "...";
|
||||
if (!installTranslator(m_qt_translator.get()))
|
||||
{
|
||||
qCritical() << "Loading Qt Language File failed.";
|
||||
m_qt_translator.reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_qt_translator.reset();
|
||||
}
|
||||
|
||||
m_mmc_translator.reset(new QTranslator());
|
||||
if (m_mmc_translator->load("mmc_" + locale.bcp47Name(), staticDataPath + "/translations"))
|
||||
{
|
||||
qDebug() << "Loading MMC Language File for"
|
||||
<< locale.bcp47Name().toLocal8Bit().constData() << "...";
|
||||
if (!installTranslator(m_mmc_translator.get()))
|
||||
{
|
||||
qCritical() << "Loading MMC Language File failed.";
|
||||
m_mmc_translator.reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mmc_translator.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMC::initIcons()
|
||||
{
|
||||
auto setting = MMC->settings()->getSetting("IconsDir");
|
||||
ENV.m_icons.reset(new IconList(QString(":/icons/instances/"), setting->get().toString()));
|
||||
connect(setting.get(), &Setting::SettingChanged,[&](const Setting &, QVariant value)
|
||||
{
|
||||
ENV.m_icons->directoryChanged(value.toString());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void moveFile(const QString &oldName, const QString &newName)
|
||||
{
|
||||
QFile::remove(newName);
|
||||
QFile::copy(oldName, newName);
|
||||
QFile::remove(oldName);
|
||||
}
|
||||
|
||||
|
||||
void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||
{
|
||||
const char *levels = "DWCF";
|
||||
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);
|
||||
}
|
||||
|
||||
void 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));
|
||||
|
||||
qInstallMessageHandler(appDebugOutput);
|
||||
|
||||
logFile = std::make_shared<QFile>(logBase.arg(0));
|
||||
logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
|
||||
}
|
||||
|
||||
void MultiMC::initGlobalSettings(bool test_mode)
|
||||
{
|
||||
m_settings.reset(new INISettingsObject("multimc.cfg", this));
|
||||
// Updates
|
||||
m_settings->registerSetting("UpdateChannel", BuildConfig.VERSION_CHANNEL);
|
||||
m_settings->registerSetting("AutoUpdate", true);
|
||||
m_settings->registerSetting("IconTheme", QString("multimc"));
|
||||
|
||||
// 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
|
||||
if(!test_mode)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
// in test mode, we don't have UI, so we don't do any font resolving
|
||||
m_settings->registerSetting("ConsoleFont", defaultMonospace);
|
||||
}
|
||||
m_settings->registerSetting("ConsoleFontSize", defaultSize);
|
||||
|
||||
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", QLocale(QLocale::system().language()).bcp47Name());
|
||||
|
||||
// Console
|
||||
m_settings->registerSetting("ShowConsole", true);
|
||||
m_settings->registerSetting("RaiseConsole", true);
|
||||
m_settings->registerSetting("AutoCloseConsole", 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("LastHostname", "");
|
||||
m_settings->registerSetting("JavaDetectionHack", "");
|
||||
m_settings->registerSetting("JvmArgs", "");
|
||||
|
||||
// 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", "");
|
||||
}
|
||||
|
||||
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<ForgeVersionList> MultiMC::forgelist()
|
||||
{
|
||||
if (!m_forgelist)
|
||||
{
|
||||
m_forgelist.reset(new ForgeVersionList());
|
||||
ENV.registerVersionList("net.minecraftforge", m_forgelist);
|
||||
}
|
||||
return m_forgelist;
|
||||
}
|
||||
|
||||
std::shared_ptr<LiteLoaderVersionList> MultiMC::liteloaderlist()
|
||||
{
|
||||
if (!m_liteloaderlist)
|
||||
{
|
||||
m_liteloaderlist.reset(new LiteLoaderVersionList());
|
||||
ENV.registerVersionList("com.mumfrey.liteloader", m_liteloaderlist);
|
||||
}
|
||||
return m_liteloaderlist;
|
||||
}
|
||||
|
||||
std::shared_ptr<MinecraftVersionList> MultiMC::minecraftlist()
|
||||
{
|
||||
if (!m_minecraftlist)
|
||||
{
|
||||
m_minecraftlist.reset(new MinecraftVersionList());
|
||||
ENV.registerVersionList("net.minecraft", m_minecraftlist);
|
||||
}
|
||||
return m_minecraftlist;
|
||||
}
|
||||
|
||||
std::shared_ptr<JavaVersionList> MultiMC::javalist()
|
||||
{
|
||||
if (!m_javalist)
|
||||
{
|
||||
m_javalist.reset(new JavaVersionList());
|
||||
ENV.registerVersionList("com.java", m_javalist);
|
||||
}
|
||||
return m_javalist;
|
||||
}
|
||||
|
||||
void MultiMC::installUpdates(const QString updateFilesDir, UpdateFlags flags)
|
||||
{
|
||||
// if we are going to update on exit, save the params now
|
||||
if (flags & OnExit)
|
||||
{
|
||||
m_updateOnExitPath = updateFilesDir;
|
||||
m_updateOnExitFlags = flags & ~OnExit;
|
||||
return;
|
||||
}
|
||||
// otherwise if there already were some params for on exit update, clear them and continue
|
||||
else if (m_updateOnExitPath.size())
|
||||
{
|
||||
m_updateOnExitFlags = None;
|
||||
m_updateOnExitPath.clear();
|
||||
}
|
||||
qDebug() << "Installing updates.";
|
||||
#ifdef WINDOWS
|
||||
QString finishCmd = applicationFilePath();
|
||||
QString updaterBinary = PathCombine(applicationDirPath(), "updater.exe");
|
||||
#elif LINUX
|
||||
QString finishCmd = PathCombine(root(), "MultiMC");
|
||||
QString updaterBinary = PathCombine(applicationDirPath(), "updater");
|
||||
#elif OSX
|
||||
QString finishCmd = applicationFilePath();
|
||||
QString updaterBinary = PathCombine(applicationDirPath(), "updater");
|
||||
#else
|
||||
#error Unsupported operating system.
|
||||
#endif
|
||||
|
||||
QStringList args;
|
||||
// ./updater --install-dir $INSTALL_DIR --package-dir $UPDATEFILES_DIR --script
|
||||
// $UPDATEFILES_DIR/file_list.xml --wait $PID --mode main
|
||||
args << "--install-dir" << root();
|
||||
args << "--package-dir" << updateFilesDir;
|
||||
args << "--script" << PathCombine(updateFilesDir, "file_list.xml");
|
||||
args << "--wait" << QString::number(applicationPid());
|
||||
if (flags & DryRun)
|
||||
args << "--dry-run";
|
||||
if (flags & RestartOnFinish)
|
||||
{
|
||||
args << "--finish-cmd" << finishCmd;
|
||||
args << "--finish-dir" << dataPath;
|
||||
}
|
||||
qDebug() << "Running updater with command" << updaterBinary << args.join(" ");
|
||||
QFile::setPermissions(updaterBinary, (QFileDevice::Permission)0x7755);
|
||||
|
||||
if (!QProcess::startDetached(updaterBinary, args /*, root()*/))
|
||||
{
|
||||
qCritical() << "Failed to start the updater process!";
|
||||
return;
|
||||
}
|
||||
|
||||
ENV.destroy();
|
||||
// Now that we've started the updater, quit MultiMC.
|
||||
quit();
|
||||
}
|
||||
|
||||
void MultiMC::setIconTheme(const QString& name)
|
||||
{
|
||||
XdgIcon::setThemeName(name);
|
||||
}
|
||||
|
||||
QIcon MultiMC::getThemedIcon(const QString& name)
|
||||
{
|
||||
return XdgIcon::fromTheme(name);
|
||||
}
|
||||
|
||||
void MultiMC::onExit()
|
||||
{
|
||||
if(m_instances)
|
||||
{
|
||||
m_instances->saveGroupList();
|
||||
}
|
||||
if (m_updateOnExitPath.size())
|
||||
{
|
||||
installUpdates(m_updateOnExitPath, m_updateOnExitFlags);
|
||||
}
|
||||
ENV.destroy();
|
||||
if(logFile)
|
||||
{
|
||||
logFile->flush();
|
||||
logFile->close();
|
||||
}
|
||||
}
|
||||
|
||||
bool MultiMC::openJsonEditor(const QString &filename)
|
||||
{
|
||||
const QString file = QDir::current().absoluteFilePath(filename);
|
||||
if (m_settings->get("JsonEditor").toString().isEmpty())
|
||||
{
|
||||
return QDesktopServices::openUrl(QUrl::fromLocalFile(file));
|
||||
}
|
||||
else
|
||||
{
|
||||
return QProcess::startDetached(m_settings->get("JsonEditor").toString(), QStringList()
|
||||
<< file);
|
||||
}
|
||||
}
|
||||
|
||||
#include "MultiMC.moc"
|
188
application/MultiMC.h
Normal file
188
application/MultiMC.h
Normal file
@ -0,0 +1,188 @@
|
||||
#pragma once
|
||||
|
||||
#include <QApplication>
|
||||
#include <memory>
|
||||
#include <QDebug>
|
||||
#include <QFlag>
|
||||
#include <QIcon>
|
||||
#include <QDateTime>
|
||||
|
||||
class QFile;
|
||||
class MinecraftVersionList;
|
||||
class LWJGLVersionList;
|
||||
class HttpMetaCache;
|
||||
class SettingsObject;
|
||||
class InstanceList;
|
||||
class MojangAccountList;
|
||||
class IconList;
|
||||
class QNetworkAccessManager;
|
||||
class ForgeVersionList;
|
||||
class LiteLoaderVersionList;
|
||||
class JavaVersionList;
|
||||
class UpdateChecker;
|
||||
class BaseProfilerFactory;
|
||||
class BaseDetachedToolFactory;
|
||||
class TranslationDownloader;
|
||||
|
||||
#if defined(MMC)
|
||||
#undef MMC
|
||||
#endif
|
||||
#define MMC (static_cast<MultiMC *>(QCoreApplication::instance()))
|
||||
|
||||
enum UpdateFlag
|
||||
{
|
||||
None = 0x0,
|
||||
RestartOnFinish = 0x1,
|
||||
DryRun = 0x2,
|
||||
OnExit = 0x4
|
||||
};
|
||||
Q_DECLARE_FLAGS(UpdateFlags, UpdateFlag);
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(UpdateFlags);
|
||||
|
||||
class MultiMC : public QApplication
|
||||
{
|
||||
// friends for the purpose of limiting access to deprecated stuff
|
||||
friend class MultiMCPage;
|
||||
friend class MainWindow;
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Status
|
||||
{
|
||||
Failed,
|
||||
Succeeded,
|
||||
Initialized
|
||||
};
|
||||
|
||||
public:
|
||||
MultiMC(int &argc, char **argv, bool test_mode = false);
|
||||
virtual ~MultiMC();
|
||||
|
||||
// InstanceList, IconList, OneSixFTBInstance, LegacyUpdate, LegacyInstance, MCEditTool, JVisualVM, MinecraftInstance, JProfiler, BaseInstance
|
||||
std::shared_ptr<SettingsObject> settings()
|
||||
{
|
||||
return m_settings;
|
||||
}
|
||||
|
||||
qint64 timeSinceStart() const
|
||||
{
|
||||
return startTime.msecsTo(QDateTime::currentDateTime());
|
||||
}
|
||||
|
||||
QIcon getThemedIcon(const QString& name);
|
||||
|
||||
void setIconTheme(const QString& name);
|
||||
|
||||
// DownloadUpdateTask
|
||||
std::shared_ptr<UpdateChecker> updateChecker()
|
||||
{
|
||||
return m_updateChecker;
|
||||
}
|
||||
|
||||
std::shared_ptr<MinecraftVersionList> minecraftlist();
|
||||
std::shared_ptr<LWJGLVersionList> lwjgllist();
|
||||
std::shared_ptr<ForgeVersionList> forgelist();
|
||||
std::shared_ptr<LiteLoaderVersionList> liteloaderlist();
|
||||
std::shared_ptr<JavaVersionList> javalist();
|
||||
|
||||
// APPLICATION ONLY
|
||||
std::shared_ptr<InstanceList> instances()
|
||||
{
|
||||
return m_instances;
|
||||
}
|
||||
|
||||
// APPLICATION ONLY
|
||||
std::shared_ptr<MojangAccountList> accounts()
|
||||
{
|
||||
return m_accounts;
|
||||
}
|
||||
|
||||
// APPLICATION ONLY
|
||||
Status status()
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
// APPLICATION ONLY
|
||||
QMap<QString, std::shared_ptr<BaseProfilerFactory>> profilers()
|
||||
{
|
||||
return m_profilers;
|
||||
}
|
||||
|
||||
// APPLICATION ONLY
|
||||
QMap<QString, std::shared_ptr<BaseDetachedToolFactory>> tools()
|
||||
{
|
||||
return m_tools;
|
||||
}
|
||||
|
||||
// APPLICATION ONLY
|
||||
void installUpdates(const QString updateFilesDir, UpdateFlags flags = None);
|
||||
|
||||
/*!
|
||||
* Opens a json file using either a system default editor, or, if note empty, the editor
|
||||
* specified in the settings
|
||||
*/
|
||||
bool openJsonEditor(const QString &filename);
|
||||
|
||||
protected: /* to be removed! */
|
||||
// FIXME: remove. used by MultiMCPage to enumerate translations.
|
||||
/// this is the static data. it stores things that don't move.
|
||||
const QString &staticData()
|
||||
{
|
||||
return staticDataPath;
|
||||
}
|
||||
|
||||
// FIXME: remove. used by MainWindow to create application update tasks
|
||||
/// this is the root of the 'installation'. Used for automatic updates
|
||||
const QString &root()
|
||||
{
|
||||
return rootPath;
|
||||
}
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* Do all the things that should be done before we exit
|
||||
*/
|
||||
void onExit();
|
||||
|
||||
private:
|
||||
void initLogger();
|
||||
|
||||
void initIcons();
|
||||
|
||||
void initGlobalSettings(bool test_mode);
|
||||
|
||||
void initTranslations();
|
||||
|
||||
private:
|
||||
friend class UpdateCheckerTest;
|
||||
friend class DownloadTaskTest;
|
||||
|
||||
QDateTime startTime;
|
||||
|
||||
std::shared_ptr<QTranslator> m_qt_translator;
|
||||
std::shared_ptr<QTranslator> m_mmc_translator;
|
||||
std::shared_ptr<SettingsObject> m_settings;
|
||||
std::shared_ptr<InstanceList> m_instances;
|
||||
std::shared_ptr<UpdateChecker> m_updateChecker;
|
||||
std::shared_ptr<MojangAccountList> m_accounts;
|
||||
std::shared_ptr<LWJGLVersionList> m_lwjgllist;
|
||||
std::shared_ptr<ForgeVersionList> m_forgelist;
|
||||
std::shared_ptr<LiteLoaderVersionList> m_liteloaderlist;
|
||||
std::shared_ptr<MinecraftVersionList> m_minecraftlist;
|
||||
std::shared_ptr<JavaVersionList> m_javalist;
|
||||
std::shared_ptr<TranslationDownloader> m_translationChecker;
|
||||
|
||||
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;
|
||||
QMap<QString, std::shared_ptr<BaseDetachedToolFactory>> m_tools;
|
||||
|
||||
QString m_updateOnExitPath;
|
||||
UpdateFlags m_updateOnExitFlags = None;
|
||||
|
||||
QString rootPath;
|
||||
QString staticDataPath;
|
||||
QString dataPath;
|
||||
|
||||
Status m_status = MultiMC::Failed;
|
||||
public:
|
||||
std::shared_ptr<QFile> logFile;
|
||||
};
|
38
application/NagUtils.cpp
Normal file
38
application/NagUtils.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
/* Copyright 2013-2015 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 "NagUtils.h"
|
||||
#include "dialogs/CustomMessageBox.h"
|
||||
|
||||
namespace NagUtils
|
||||
{
|
||||
void checkJVMArgs(QString jvmargs, QWidget *parent)
|
||||
{
|
||||
if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegExp("-Xm[sx]")))
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
parent, QObject::tr("JVM arguments warning"),
|
||||
QObject::tr("You tried to manually set a JVM memory option (using "
|
||||
" \"-XX:PermSize\", \"-Xmx\" or \"-Xms\") - there"
|
||||
" are dedicated boxes for these in the settings (Java"
|
||||
" tab, in the Memory group at the top).\n"
|
||||
"Your manual settings will be overridden by the"
|
||||
" dedicated options.\n"
|
||||
"This message will be displayed until you remove them"
|
||||
" from the JVM arguments."),
|
||||
QMessageBox::Warning)->exec();
|
||||
}
|
||||
}
|
||||
}
|
23
application/NagUtils.h
Normal file
23
application/NagUtils.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* Copyright 2013-2015 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 NagUtils
|
||||
{
|
||||
void checkJVMArgs(QString args, QWidget *parent);
|
||||
}
|
32
application/Platform.h
Normal file
32
application/Platform.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
||||
/**
|
||||
* @file Platform.h
|
||||
* This file contains platform-specific functions, tweaks and fixes.
|
||||
*/
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class MultiMCPlatform
|
||||
{
|
||||
public:
|
||||
// X11 WM_CLASS
|
||||
static void fixWM_CLASS(QWidget *widget);
|
||||
};
|
27
application/Platform_Other.cpp
Normal file
27
application/Platform_Other.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||
*
|
||||
* 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 <Platform.h>
|
||||
/**
|
||||
* Stub for non-X11 platforms
|
||||
* @brief MultiMCPlatform::fixWM_CLASS
|
||||
* @param widget
|
||||
*/
|
||||
void MultiMCPlatform::fixWM_CLASS(QWidget *widget)
|
||||
{
|
||||
Q_UNUSED(widget);
|
||||
}
|
62
application/Platform_X11.cpp
Normal file
62
application/Platform_X11.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||
*
|
||||
* 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 <Platform.h>
|
||||
#include <QtX11Extras/QX11Info>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
static QByteArray WM_CLASS = "MultiMC5\0MultiMC5";
|
||||
|
||||
template <typename... ArgTypes, typename... ArgTypes2>
|
||||
static inline unsigned int XcbCallVoid(xcb_void_cookie_t (*func)(xcb_connection_t *, ArgTypes...), ArgTypes2... args...)
|
||||
{
|
||||
return func(QX11Info::connection(), args...).sequence;
|
||||
}
|
||||
|
||||
static void getAtoms(size_t n, xcb_atom_t *atoms, const char *const names[], bool create)
|
||||
{
|
||||
xcb_connection_t *conn = QX11Info::connection();
|
||||
xcb_intern_atom_cookie_t *cookies = (xcb_intern_atom_cookie_t *)malloc(sizeof(xcb_intern_atom_cookie_t) * 2);
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
cookies[i] = xcb_intern_atom(conn, create, strlen(names[i]), names[i]);
|
||||
memset(atoms, 0, sizeof(xcb_atom_t) * n);
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
{
|
||||
xcb_intern_atom_reply_t *r = xcb_intern_atom_reply(conn, cookies[i], 0);
|
||||
if (r)
|
||||
{
|
||||
atoms[i] = r->atom;
|
||||
free(r);
|
||||
}
|
||||
}
|
||||
free(cookies);
|
||||
}
|
||||
|
||||
static inline xcb_atom_t getAtom(const char *name, bool create=false)
|
||||
{
|
||||
xcb_atom_t atom;
|
||||
getAtoms(1, &atom, &name, create);
|
||||
return atom;
|
||||
}
|
||||
|
||||
void MultiMCPlatform::fixWM_CLASS(QWidget *widget)
|
||||
{
|
||||
static const xcb_atom_t atom = getAtom("WM_CLASS");
|
||||
XcbCallVoid(xcb_change_property, XCB_PROP_MODE_REPLACE,
|
||||
widget->winId(), atom, XCB_ATOM_STRING, 8, WM_CLASS.count(),
|
||||
WM_CLASS.constData());
|
||||
}
|
127
application/dialogs/AboutDialog.cpp
Normal file
127
application/dialogs/AboutDialog.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/* Copyright 2013-2015 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 "AboutDialog.h"
|
||||
#include "ui_AboutDialog.h"
|
||||
#include <QIcon>
|
||||
#include "MultiMC.h"
|
||||
#include "Platform.h"
|
||||
#include "BuildConfig.h"
|
||||
|
||||
#include <net/NetJob.h>
|
||||
|
||||
// Credits
|
||||
// This is a hack, but I can't think of a better way to do this easily without screwing with QTextDocument...
|
||||
QString getCreditsHtml(QStringList patrons)
|
||||
{
|
||||
QString creditsHtml = QObject::tr(
|
||||
"<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0//EN' 'http://www.w3.org/TR/REC-html40/strict.dtd'>"
|
||||
"<html>"
|
||||
""
|
||||
"<head>"
|
||||
"<meta name='qrichtext' content='1' />"
|
||||
"<style type='text/css'>"
|
||||
"p { white-space: pre-wrap; margin-top:2px; margin-bottom:2px; }"
|
||||
"</style>"
|
||||
"</head>"
|
||||
""
|
||||
"<body style=' font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;'>"
|
||||
""
|
||||
"<h3>MultiMC Developers</h3>"
|
||||
"<p>Andrew Okin <<a href='mailto:forkk@forkk.net'>forkk@forkk.net</a>></p>"
|
||||
"<p>Petr Mrázek <<a href='mailto:peterix@gmail.com'>peterix@gmail.com</a>></p>"
|
||||
"<p>Sky Welch <<a href='mailto:multimc@bunnies.io'>multimc@bunnies.io</a>></p>"
|
||||
"<p>Jan (02JanDal) <<a href='mailto:02jandal@gmail.com'>02jandal@gmail.com</a>></p>"
|
||||
""
|
||||
"<h3>With thanks to</h3>"
|
||||
"<p>Orochimarufan <<a href='mailto:orochimarufan.x3@gmail.com'>orochimarufan.x3@gmail.com</a>></p>"
|
||||
"<p>TakSuyu <<a href='mailto:taksuyu@gmail.com'>taksuyu@gmail.com</a>></p>"
|
||||
"<p>Kilobyte <<a href='mailto:stiepen22@gmx.de'>stiepen22@gmx.de</a>></p>"
|
||||
"<p>Robotbrain <<a href='https://twitter.com/skylordelros'>@skylordelros</a>></p>"
|
||||
"<p>Rootbear75 <<a href='https://twitter.com/rootbear75'>@rootbear75</a>> (build server)</p>"
|
||||
""
|
||||
"<h3>Patreon Patrons</h3>"
|
||||
"%1"
|
||||
""
|
||||
"</body>"
|
||||
"</html>");
|
||||
if (patrons.isEmpty())
|
||||
return creditsHtml.arg(QObject::tr("<p>Loading...</p>"));
|
||||
else
|
||||
{
|
||||
QString patronsStr;
|
||||
for (QString patron : patrons)
|
||||
{
|
||||
patronsStr.append(QString("<p>%1</p>").arg(patron));
|
||||
}
|
||||
|
||||
return creditsHtml.arg(patronsStr);
|
||||
}
|
||||
}
|
||||
|
||||
AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
|
||||
QString chtml = getCreditsHtml(QStringList());
|
||||
ui->creditsText->setHtml(chtml);
|
||||
|
||||
ui->urlLabel->setOpenExternalLinks(true);
|
||||
|
||||
ui->icon->setPixmap(MMC->getThemedIcon("multimc").pixmap(64));
|
||||
ui->title->setText("MultiMC 5");
|
||||
|
||||
ui->versionLabel->setText(tr("Version") +": " + BuildConfig.printableVersionString());
|
||||
ui->platformLabel->setText(tr("Platform") +": " + BuildConfig.BUILD_PLATFORM);
|
||||
|
||||
if (BuildConfig.VERSION_BUILD >= 0)
|
||||
ui->buildNumLabel->setText(tr("Build Number") +": " + QString::number(BuildConfig.VERSION_BUILD));
|
||||
else
|
||||
ui->buildNumLabel->setVisible(false);
|
||||
|
||||
if (!BuildConfig.VERSION_CHANNEL.isEmpty())
|
||||
ui->channelLabel->setText(tr("Channel") +": " + BuildConfig.VERSION_CHANNEL);
|
||||
else
|
||||
ui->channelLabel->setVisible(false);
|
||||
|
||||
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
|
||||
|
||||
connect(ui->aboutQt, &QPushButton::clicked, &QApplication::aboutQt);
|
||||
|
||||
loadPatronList();
|
||||
}
|
||||
|
||||
AboutDialog::~AboutDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AboutDialog::loadPatronList()
|
||||
{
|
||||
NetJob* job = new NetJob("Patreon Patron List");
|
||||
patronListDownload = ByteArrayDownload::make(QUrl("http://files.multimc.org/patrons.txt"));
|
||||
job->addNetAction(patronListDownload);
|
||||
connect(job, &NetJob::succeeded, this, &AboutDialog::patronListLoaded);
|
||||
job->start();
|
||||
}
|
||||
|
||||
void AboutDialog::patronListLoaded()
|
||||
{
|
||||
QString patronListStr(patronListDownload->m_data);
|
||||
QString html = getCreditsHtml(patronListStr.split("\n", QString::SkipEmptyParts));
|
||||
ui->creditsText->setHtml(html);
|
||||
}
|
||||
|
47
application/dialogs/AboutDialog.h
Normal file
47
application/dialogs/AboutDialog.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* Copyright 2013-2015 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 <net/ByteArrayDownload.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class AboutDialog;
|
||||
}
|
||||
|
||||
class AboutDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AboutDialog(QWidget *parent = 0);
|
||||
~AboutDialog();
|
||||
|
||||
public
|
||||
slots:
|
||||
/// Starts loading a list of Patreon patrons.
|
||||
void loadPatronList();
|
||||
|
||||
/// Slot for when the patron list loads successfully.
|
||||
void patronListLoaded();
|
||||
|
||||
private:
|
||||
Ui::AboutDialog *ui;
|
||||
|
||||
ByteArrayDownloadPtr patronListDownload;
|
||||
};
|
544
application/dialogs/AboutDialog.ui
Normal file
544
application/dialogs/AboutDialog.ui
Normal file
@ -0,0 +1,544 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AboutDialog</class>
|
||||
<widget class="QDialog" name="AboutDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>707</width>
|
||||
<height>593</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>450</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>About MultiMC</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="icon">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="title">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>15</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MultiMC 5</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolBox" name="toolBox">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="aboutPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>695</width>
|
||||
<height>297</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>About</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="versionLabel">
|
||||
<property name="text">
|
||||
<string>Version:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="platformLabel">
|
||||
<property name="text">
|
||||
<string>Platform:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="buildNumLabel">
|
||||
<property name="text">
|
||||
<string>Build Number:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="channelLabel">
|
||||
<property name="text">
|
||||
<string>Channel:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="aboutLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>MultiMC is a custom launcher that makes managing Minecraft easier by allowing you to have multiple instances of Minecraft at once.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="copyLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>© 2013-2015 MultiMC Contributors</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="urlLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><a href="http://github.com/MultiMC/MultiMC5"><span style=" text-decoration: underline; color:#0000ff;">http://github.com/MultiMC/MultiMC5</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</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>
|
||||
<widget class="QWidget" name="creditsPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>695</width>
|
||||
<height>297</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Credits</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="creditsText">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Oxygen-Sans'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html></string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="translationInfo">
|
||||
<property name="text">
|
||||
<string extracomment="Hey, Translator, feel free to put credit to you here">No Language file loaded.</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="licensePage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>695</width>
|
||||
<height>297</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>License</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="licenseText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans Mono</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'DejaVu Sans Mono'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">MultiMC</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Copyright 2012-2014 MultiMC Contributors</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">you may not use this file except in compliance with the License.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may obtain a copy of the License at</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> http://www.apache.org/licenses/LICENSE-2.0</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Unless required by applicable law or agreed to in writing, software</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">See the License for the specific language governing permissions and</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">limitations under the License.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">QSLog</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Copyright (c) 2010, Razvan Petru</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">All rights reserved.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Redistribution and use in source and binary forms, with or without modification,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">are permitted provided that the following conditions are met:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">* Redistributions of source code must retain the above copyright notice, this</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> list of conditions and the following disclaimer.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">* Redistributions in binary form must reproduce the above copyright notice, this</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> list of conditions and the following disclaimer in the documentation and/or other</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> materials provided with the distribution.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">* The name of the contributors may not be used to endorse or promote products</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> derived from this software without specific prior written permission.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; AND</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">OF THE POSSIBILITY OF SUCH DAMAGE.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">Group View (instance view)</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> /*</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Copyright (C) 2007 Rafael Fernández López &lt;ereslibre@kde.org&gt;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Copyright (C) 2007 John Tapsell &lt;tapsell@kde.org&gt;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> *</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * This library is free software; you can redistribute it and/or</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * modify it under the terms of the GNU Library General Public</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * License as published by the Free Software Foundation; either</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * version 2 of the License, or (at your option) any later version.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> *</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * This library is distributed in the hope that it will be useful,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Library General Public License for more details.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> *</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * You should have received a copy of the GNU Library General Public License</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * along with this library; see the file COPYING.LIB. If not, write to</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Boston, MA 02110-1301, USA.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> */</span></p>
|
||||
<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">Batch icon set</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You are free to use Batch (the &quot;icon set&quot;) or any part thereof (the &quot;icons&quot;)</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">in any personal, open-source or commercial work without obligation of payment</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">(monetary or otherwise) or attribution. Do not sell the icon set, host</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">the icon set or rent the icon set (either in existing or modified form).</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">While attribution is optional, it is always appreciated.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Intellectual property rights are not transferred with the download of the icons.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL ADAM WHITCROFT</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THE USE OF THE ICONS,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://adamwhitcroft.com/batch/"><span style=" text-decoration: underline; color:#68a0df;">http://adamwhitcroft.com/batch/</span></a></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">Pack200</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The GNU General Public License (GPL)</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Version 2, June 1991</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">+ &quot;CLASSPATH&quot; EXCEPTION TO THE GPL</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Certain source files distributed by Oracle America and/or its affiliates are</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">subject to the following clarification and special exception to the GPL, but</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">only where Oracle has expressly included in the particular source file's header</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">the words &quot;Oracle designates this particular file as subject to the &quot;Classpath&quot;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">exception as provided by Oracle in the LICENSE file that accompanied this code.&quot;</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> Linking this library statically or dynamically with other modules is making</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> a combined work based on this library. Thus, the terms and conditions of</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> the GNU General Public License cover the whole combination.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> As a special exception, the copyright holders of this library give you</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> permission to link this library with independent modules to produce an</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> executable, regardless of the license terms of these independent modules,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> and to copy and distribute the resulting executable under terms of your</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> choice, provided that you also meet, for each linked independent module,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> the terms and conditions of the license of that module. An independent</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> module is a module which is not derived from or based on this library. If</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> you modify this library, you may extend this exception to your version of</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> the library, but you are not obligated to do so. If you do not wish to do</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> so, delete this exception statement from your version.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">Quazip</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Copyright (C) 2005-2011 Sergey A. Tachenov</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This program is free software; you can redistribute it and/or modify it</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">under the terms of the GNU Lesser General Public License as published by</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">the Free Software Foundation; either version 2 of the License, or (at</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">your option) any later version.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This program is distributed in the hope that it will be useful, but</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">WITHOUT ANY WARRANTY; without even the implied warranty of</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">General Public License for more details.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You should have received a copy of the GNU Lesser General Public License</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">along with this program; if not, write to the Free Software Foundation,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">See COPYING file for the full LGPL text.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Original ZIP package is copyrighted by Gilles Vollant, see</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">quazip/(un)zip.h files for details, basically it's zlib license.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">xz-minidec</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">/*</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * XZ decompressor</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> *</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Authors: Lasse Collin &lt;lasse.collin@tukaani.org&gt;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Igor Pavlov &lt;http://7-zip.org/&gt;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> *</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * This file has been put into the public domain.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * You can do whatever you want with this file.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> */</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">Java IconLoader class</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Copyright (c) 2011, Chris Molini</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">All rights reserved.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Redistribution and use in source and binary forms, with or without</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">modification, are permitted provided that the following conditions are met:</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Redistributions of source code must retain the above copyright</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> notice, this list of conditions and the following disclaimer.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Redistributions in binary form must reproduce the above copyright</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> notice, this list of conditions and the following disclaimer in the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> documentation and/or other materials provided with the distribution.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Neither the name of the &lt;organization&gt; nor the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> names of its contributors may be used to endorse or promote products</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> derived from this software without specific prior written permission.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; AND</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">DISCLAIMED. IN NO EVENT SHALL &lt;COPYRIGHT HOLDER&gt; BE LIABLE FOR ANY</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span></p>
|
||||
<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">ColumnResizer</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">/*</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Copyright 2011 Aurélien Gâteau &lt;agateau@kde.org&gt;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * License: LGPL v2.1 or later (see COPYING)</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> */</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="forkPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>695</width>
|
||||
<height>297</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Forking/Redistribution</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_33">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEdit">
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Oxygen-Sans'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans';">We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans';"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans';">Part of the reason for using the Apache license is we don't want people using the &quot;MultiMC&quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &quot;MultiMC&quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans';"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans';">The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork </span><span style=" font-family:'Bitstream Vera Sans'; font-weight:600;">without</span><span style=" font-family:'Bitstream Vera Sans';"> implying that you have our blessing.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="aboutQt">
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>About Qt</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="closeButton">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../resources/multimc/multimc.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
85
application/dialogs/AccountSelectDialog.cpp
Normal file
85
application/dialogs/AccountSelectDialog.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
/* Copyright 2013-2015 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 "AccountSelectDialog.h"
|
||||
#include "ui_AccountSelectDialog.h"
|
||||
|
||||
#include <QItemSelectionModel>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <dialogs/ProgressDialog.h>
|
||||
|
||||
#include <MultiMC.h>
|
||||
|
||||
AccountSelectDialog::AccountSelectDialog(const QString &message, int flags, QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::AccountSelectDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_accounts = MMC->accounts();
|
||||
ui->listView->setModel(m_accounts.get());
|
||||
ui->listView->hideColumn(MojangAccountList::ActiveColumn);
|
||||
|
||||
// Set the message label.
|
||||
ui->msgLabel->setVisible(!message.isEmpty());
|
||||
ui->msgLabel->setText(message);
|
||||
|
||||
// Flags...
|
||||
ui->globalDefaultCheck->setVisible(flags & GlobalDefaultCheckbox);
|
||||
ui->instDefaultCheck->setVisible(flags & InstanceDefaultCheckbox);
|
||||
qDebug() << flags;
|
||||
|
||||
// Select the first entry in the list.
|
||||
ui->listView->setCurrentIndex(ui->listView->model()->index(0, 0));
|
||||
|
||||
connect(ui->listView, SIGNAL(doubleClicked(QModelIndex)), SLOT(on_buttonBox_accepted()));
|
||||
}
|
||||
|
||||
AccountSelectDialog::~AccountSelectDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
MojangAccountPtr AccountSelectDialog::selectedAccount() const
|
||||
{
|
||||
return m_selected;
|
||||
}
|
||||
|
||||
bool AccountSelectDialog::useAsGlobalDefault() const
|
||||
{
|
||||
return ui->globalDefaultCheck->isChecked();
|
||||
}
|
||||
|
||||
bool AccountSelectDialog::useAsInstDefaullt() const
|
||||
{
|
||||
return ui->instDefaultCheck->isChecked();
|
||||
}
|
||||
|
||||
void AccountSelectDialog::on_buttonBox_accepted()
|
||||
{
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
if (selection.size() > 0)
|
||||
{
|
||||
QModelIndex selected = selection.first();
|
||||
m_selected = selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>();
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
void AccountSelectDialog::on_buttonBox_rejected()
|
||||
{
|
||||
close();
|
||||
}
|
90
application/dialogs/AccountSelectDialog.h
Normal file
90
application/dialogs/AccountSelectDialog.h
Normal file
@ -0,0 +1,90 @@
|
||||
/* Copyright 2013-2015 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 <memory>
|
||||
|
||||
#include "auth/MojangAccountList.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class AccountSelectDialog;
|
||||
}
|
||||
|
||||
class AccountSelectDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Flags
|
||||
{
|
||||
NoFlags = 0,
|
||||
|
||||
/*!
|
||||
* Shows a check box on the dialog that allows the user to specify that the account
|
||||
* they've selected should be used as the global default for all instances.
|
||||
*/
|
||||
GlobalDefaultCheckbox,
|
||||
|
||||
/*!
|
||||
* Shows a check box on the dialog that allows the user to specify that the account
|
||||
* they've selected should be used as the default for the instance they are currently launching.
|
||||
* This is not currently implemented.
|
||||
*/
|
||||
InstanceDefaultCheckbox,
|
||||
};
|
||||
|
||||
/*!
|
||||
* Constructs a new account select dialog with the given parent and message.
|
||||
* The message will be shown at the top of the dialog. It is an empty string by default.
|
||||
*/
|
||||
explicit AccountSelectDialog(const QString& message="", int flags=0, QWidget *parent = 0);
|
||||
~AccountSelectDialog();
|
||||
|
||||
/*!
|
||||
* Gets a pointer to the account that the user selected.
|
||||
* This is null if the user clicked cancel or hasn't clicked OK yet.
|
||||
*/
|
||||
MojangAccountPtr selectedAccount() const;
|
||||
|
||||
/*!
|
||||
* Returns true if the user checked the "use as global default" checkbox.
|
||||
* If the checkbox wasn't shown, this function returns false.
|
||||
*/
|
||||
bool useAsGlobalDefault() const;
|
||||
|
||||
/*!
|
||||
* Returns true if the user checked the "use as instance default" checkbox.
|
||||
* If the checkbox wasn't shown, this function returns false.
|
||||
*/
|
||||
bool useAsInstDefaullt() const;
|
||||
|
||||
public
|
||||
slots:
|
||||
void on_buttonBox_accepted();
|
||||
|
||||
void on_buttonBox_rejected();
|
||||
|
||||
protected:
|
||||
std::shared_ptr<MojangAccountList> m_accounts;
|
||||
|
||||
//! The account that was selected when the user clicked OK.
|
||||
MojangAccountPtr m_selected;
|
||||
|
||||
private:
|
||||
Ui::AccountSelectDialog *ui;
|
||||
};
|
56
application/dialogs/AccountSelectDialog.ui
Normal file
56
application/dialogs/AccountSelectDialog.ui
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AccountSelectDialog</class>
|
||||
<widget class="QDialog" name="AccountSelectDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>413</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Select an Account</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="msgLabel">
|
||||
<property name="text">
|
||||
<string>Select an account.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="listView"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="globalDefaultCheck">
|
||||
<property name="text">
|
||||
<string>Use as default?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="instDefaultCheck">
|
||||
<property name="text">
|
||||
<string>Use as default for this instance only?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
101
application/dialogs/CopyInstanceDialog.cpp
Normal file
101
application/dialogs/CopyInstanceDialog.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/* Copyright 2013-2015 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 <QLayout>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "MultiMC.h"
|
||||
#include "CopyInstanceDialog.h"
|
||||
#include "ui_CopyInstanceDialog.h"
|
||||
|
||||
#include "Platform.h"
|
||||
#include "dialogs/VersionSelectDialog.h"
|
||||
#include "dialogs/ProgressDialog.h"
|
||||
#include "dialogs/IconPickerDialog.h"
|
||||
|
||||
#include "BaseVersion.h"
|
||||
#include "icons/IconList.h"
|
||||
#include "tasks/Task.h"
|
||||
#include "BaseInstance.h"
|
||||
#include "InstanceList.h"
|
||||
|
||||
CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget *parent)
|
||||
:QDialog(parent), ui(new Ui::CopyInstanceDialog), m_original(original)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
resize(minimumSizeHint());
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
||||
InstIconKey = original->iconKey();
|
||||
ui->iconButton->setIcon(ENV.icons()->getIcon(InstIconKey));
|
||||
ui->instNameTextBox->setText(original->name());
|
||||
ui->instNameTextBox->setFocus();
|
||||
auto groups = MMC->instances()->getGroups().toSet();
|
||||
auto groupList = QStringList(groups.toList());
|
||||
groupList.sort(Qt::CaseInsensitive);
|
||||
groupList.removeOne("");
|
||||
groupList.push_front("");
|
||||
ui->groupBox->addItems(groupList);
|
||||
int index = groupList.indexOf(m_original->group());
|
||||
if(index == -1)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
ui->groupBox->setCurrentIndex(index);
|
||||
ui->groupBox->lineEdit()->setPlaceholderText(tr("No group"));
|
||||
}
|
||||
|
||||
CopyInstanceDialog::~CopyInstanceDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::updateDialogState()
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!instName().isEmpty());
|
||||
}
|
||||
|
||||
QString CopyInstanceDialog::instName() const
|
||||
{
|
||||
return ui->instNameTextBox->text();
|
||||
}
|
||||
|
||||
QString CopyInstanceDialog::iconKey() const
|
||||
{
|
||||
return InstIconKey;
|
||||
}
|
||||
|
||||
QString CopyInstanceDialog::instGroup() const
|
||||
{
|
||||
return ui->groupBox->currentText();
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::on_iconButton_clicked()
|
||||
{
|
||||
IconPickerDialog dlg(this);
|
||||
dlg.exec(InstIconKey);
|
||||
|
||||
if (dlg.result() == QDialog::Accepted)
|
||||
{
|
||||
InstIconKey = dlg.selectedIconKey;
|
||||
ui->iconButton->setIcon(ENV.icons()->getIcon(InstIconKey));
|
||||
}
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::on_instNameTextBox_textChanged(const QString &arg1)
|
||||
{
|
||||
updateDialogState();
|
||||
}
|
52
application/dialogs/CopyInstanceDialog.h
Normal file
52
application/dialogs/CopyInstanceDialog.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* Copyright 2013-2015 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 "BaseVersion.h"
|
||||
#include <BaseInstance.h>
|
||||
|
||||
class BaseInstance;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class CopyInstanceDialog;
|
||||
}
|
||||
|
||||
class CopyInstanceDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CopyInstanceDialog(InstancePtr original, QWidget *parent = 0);
|
||||
~CopyInstanceDialog();
|
||||
|
||||
void updateDialogState();
|
||||
|
||||
QString instName() const;
|
||||
QString instGroup() const;
|
||||
QString iconKey() const;
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_iconButton_clicked();
|
||||
void on_instNameTextBox_textChanged(const QString &arg1);
|
||||
|
||||
private:
|
||||
Ui::CopyInstanceDialog *ui;
|
||||
QString InstIconKey;
|
||||
InstancePtr m_original;
|
||||
};
|
161
application/dialogs/CopyInstanceDialog.ui
Normal file
161
application/dialogs/CopyInstanceDialog.ui
Normal file
@ -0,0 +1,161 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CopyInstanceDialog</class>
|
||||
<widget class="QDialog" name="CopyInstanceDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>345</width>
|
||||
<height>205</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>
|
||||
<layout class="QHBoxLayout" name="iconBtnLayout">
|
||||
<item>
|
||||
<spacer name="iconBtnLeftSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="iconButton">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/icons/instances/infinity</normaloff>:/icons/instances/infinity</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>80</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="iconBtnRightSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="instNameTextBox">
|
||||
<property name="placeholderText">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelVersion_3">
|
||||
<property name="text">
|
||||
<string>Group</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>groupBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="groupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</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>
|
||||
<resources>
|
||||
<include location="../../graphics.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>CopyInstanceDialog</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>CopyInstanceDialog</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>
|
35
application/dialogs/CustomMessageBox.cpp
Normal file
35
application/dialogs/CustomMessageBox.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/* Copyright 2013-2015 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 "CustomMessageBox.h"
|
||||
|
||||
namespace CustomMessageBox
|
||||
{
|
||||
QMessageBox *selectable(QWidget *parent, const QString &title, const QString &text,
|
||||
QMessageBox::Icon icon, QMessageBox::StandardButtons buttons,
|
||||
QMessageBox::StandardButton defaultButton)
|
||||
{
|
||||
QMessageBox *messageBox = new QMessageBox(parent);
|
||||
messageBox->setWindowTitle(title);
|
||||
messageBox->setText(text);
|
||||
messageBox->setStandardButtons(buttons);
|
||||
messageBox->setDefaultButton(defaultButton);
|
||||
messageBox->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
messageBox->setIcon(icon);
|
||||
messageBox->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
|
||||
return messageBox;
|
||||
}
|
||||
}
|
26
application/dialogs/CustomMessageBox.h
Normal file
26
application/dialogs/CustomMessageBox.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* Copyright 2013-2015 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 <QMessageBox>
|
||||
|
||||
namespace CustomMessageBox
|
||||
{
|
||||
QMessageBox *selectable(QWidget *parent, const QString &title, const QString &text,
|
||||
QMessageBox::Icon icon = QMessageBox::NoIcon,
|
||||
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||
}
|
51
application/dialogs/EditAccountDialog.cpp
Normal file
51
application/dialogs/EditAccountDialog.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/* Copyright 2013-2015 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 "EditAccountDialog.h"
|
||||
#include "ui_EditAccountDialog.h"
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
|
||||
EditAccountDialog::EditAccountDialog(const QString &text, QWidget *parent, int flags)
|
||||
: QDialog(parent), ui(new Ui::EditAccountDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->label->setText(text);
|
||||
ui->label->setVisible(!text.isEmpty());
|
||||
|
||||
ui->userTextBox->setVisible(flags & UsernameField);
|
||||
ui->passTextBox->setVisible(flags & PasswordField);
|
||||
}
|
||||
|
||||
EditAccountDialog::~EditAccountDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EditAccountDialog::on_label_linkActivated(const QString &link)
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl(link));
|
||||
}
|
||||
|
||||
QString EditAccountDialog::username() const
|
||||
{
|
||||
return ui->userTextBox->text();
|
||||
}
|
||||
|
||||
QString EditAccountDialog::password() const
|
||||
{
|
||||
return ui->passTextBox->text();
|
||||
}
|
60
application/dialogs/EditAccountDialog.h
Normal file
60
application/dialogs/EditAccountDialog.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* Copyright 2013-2015 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>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class EditAccountDialog;
|
||||
}
|
||||
|
||||
class EditAccountDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EditAccountDialog(const QString &text = "", QWidget *parent = 0,
|
||||
int flags = UsernameField | PasswordField);
|
||||
~EditAccountDialog();
|
||||
|
||||
/*!
|
||||
* Gets the text entered in the dialog's username field.
|
||||
*/
|
||||
QString username() const;
|
||||
|
||||
/*!
|
||||
* Gets the text entered in the dialog's password field.
|
||||
*/
|
||||
QString password() const;
|
||||
|
||||
enum Flags
|
||||
{
|
||||
NoFlags = 0,
|
||||
|
||||
//! Specifies that the dialog should have a username field.
|
||||
UsernameField,
|
||||
|
||||
//! Specifies that the dialog should have a password field.
|
||||
PasswordField,
|
||||
};
|
||||
|
||||
private slots:
|
||||
void on_label_linkActivated(const QString &link);
|
||||
|
||||
private:
|
||||
Ui::EditAccountDialog *ui;
|
||||
};
|
94
application/dialogs/EditAccountDialog.ui
Normal file
94
application/dialogs/EditAccountDialog.ui
Normal file
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EditAccountDialog</class>
|
||||
<widget class="QDialog" name="EditAccountDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>148</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Edit Account</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Message label placeholder.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="userTextBox">
|
||||
<property name="placeholderText">
|
||||
<string>Email / Username</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="passTextBox">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Password</string>
|
||||
</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>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>EditAccountDialog</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>EditAccountDialog</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>
|
156
application/dialogs/IconPickerDialog.cpp
Normal file
156
application/dialogs/IconPickerDialog.cpp
Normal file
@ -0,0 +1,156 @@
|
||||
/* Copyright 2013-2015 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 <QKeyEvent>
|
||||
#include <QPushButton>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "MultiMC.h"
|
||||
|
||||
#include "IconPickerDialog.h"
|
||||
#include "ui_IconPickerDialog.h"
|
||||
|
||||
#include "Platform.h"
|
||||
#include "groupview/InstanceDelegate.h"
|
||||
|
||||
#include "icons/IconList.h"
|
||||
|
||||
IconPickerDialog::IconPickerDialog(QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::IconPickerDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
setWindowModality(Qt::WindowModal);
|
||||
|
||||
auto contentsWidget = ui->iconView;
|
||||
contentsWidget->setViewMode(QListView::IconMode);
|
||||
contentsWidget->setFlow(QListView::LeftToRight);
|
||||
contentsWidget->setIconSize(QSize(48, 48));
|
||||
contentsWidget->setMovement(QListView::Static);
|
||||
contentsWidget->setResizeMode(QListView::Adjust);
|
||||
contentsWidget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
contentsWidget->setSpacing(5);
|
||||
contentsWidget->setWordWrap(false);
|
||||
contentsWidget->setWrapping(true);
|
||||
contentsWidget->setUniformItemSizes(true);
|
||||
contentsWidget->setTextElideMode(Qt::ElideRight);
|
||||
contentsWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
contentsWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
contentsWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
contentsWidget->setItemDelegate(new ListViewDelegate());
|
||||
|
||||
// contentsWidget->setAcceptDrops(true);
|
||||
contentsWidget->setDropIndicatorShown(true);
|
||||
contentsWidget->viewport()->setAcceptDrops(true);
|
||||
contentsWidget->setDragDropMode(QAbstractItemView::DropOnly);
|
||||
contentsWidget->setDefaultDropAction(Qt::CopyAction);
|
||||
|
||||
contentsWidget->installEventFilter(this);
|
||||
|
||||
contentsWidget->setModel(ENV.icons().get());
|
||||
|
||||
auto buttonAdd = ui->buttonBox->addButton(tr("Add 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)));
|
||||
}
|
||||
bool IconPickerDialog::eventFilter(QObject *obj, QEvent *evt)
|
||||
{
|
||||
if (obj != ui->iconView)
|
||||
return QDialog::eventFilter(obj, evt);
|
||||
if (evt->type() != QEvent::KeyPress)
|
||||
{
|
||||
return QDialog::eventFilter(obj, evt);
|
||||
}
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(evt);
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
removeSelectedIcon();
|
||||
return true;
|
||||
case Qt::Key_Plus:
|
||||
addNewIcon();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QDialog::eventFilter(obj, evt);
|
||||
}
|
||||
|
||||
void IconPickerDialog::addNewIcon()
|
||||
{
|
||||
//: The title of the select icons open file dialog
|
||||
QString selectIcons = tr("Select Icons");
|
||||
//: The type of icon files
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, selectIcons, QString(),
|
||||
tr("Icons") + "(*.png *.jpg *.jpeg *.ico)");
|
||||
ENV.icons()->installIcons(fileNames);
|
||||
}
|
||||
|
||||
void IconPickerDialog::removeSelectedIcon()
|
||||
{
|
||||
ENV.icons()->deleteIcon(selectedIconKey);
|
||||
}
|
||||
|
||||
void IconPickerDialog::activated(QModelIndex index)
|
||||
{
|
||||
selectedIconKey = index.data(Qt::UserRole).toString();
|
||||
accept();
|
||||
}
|
||||
|
||||
void IconPickerDialog::selectionChanged(QItemSelection selected, QItemSelection deselected)
|
||||
{
|
||||
if (selected.empty())
|
||||
return;
|
||||
|
||||
QString key = selected.first().indexes().first().data(Qt::UserRole).toString();
|
||||
if (!key.isEmpty())
|
||||
selectedIconKey = key;
|
||||
}
|
||||
|
||||
int IconPickerDialog::exec(QString selection)
|
||||
{
|
||||
auto list = ENV.icons();
|
||||
auto contentsWidget = ui->iconView;
|
||||
selectedIconKey = selection;
|
||||
|
||||
int index_nr = list->getIconIndex(selection);
|
||||
auto model_index = list->index(index_nr);
|
||||
contentsWidget->selectionModel()->select(
|
||||
model_index, QItemSelectionModel::Current | QItemSelectionModel::Select);
|
||||
|
||||
QMetaObject::invokeMethod(this, "delayed_scroll", Qt::QueuedConnection,
|
||||
Q_ARG(QModelIndex, model_index));
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
void IconPickerDialog::delayed_scroll(QModelIndex model_index)
|
||||
{
|
||||
auto contentsWidget = ui->iconView;
|
||||
contentsWidget->scrollTo(model_index);
|
||||
}
|
||||
|
||||
IconPickerDialog::~IconPickerDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
48
application/dialogs/IconPickerDialog.h
Normal file
48
application/dialogs/IconPickerDialog.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* Copyright 2013-2015 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 <QItemSelection>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class IconPickerDialog;
|
||||
}
|
||||
|
||||
class IconPickerDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit IconPickerDialog(QWidget *parent = 0);
|
||||
~IconPickerDialog();
|
||||
int exec(QString selection);
|
||||
QString selectedIconKey;
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject *, QEvent *);
|
||||
|
||||
private:
|
||||
Ui::IconPickerDialog *ui;
|
||||
|
||||
private
|
||||
slots:
|
||||
void selectionChanged(QItemSelection, QItemSelection);
|
||||
void activated(QModelIndex);
|
||||
void delayed_scroll(QModelIndex);
|
||||
void addNewIcon();
|
||||
void removeSelectedIcon();
|
||||
};
|
67
application/dialogs/IconPickerDialog.ui
Normal file
67
application/dialogs/IconPickerDialog.ui
Normal file
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>IconPickerDialog</class>
|
||||
<widget class="QDialog" name="IconPickerDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>676</width>
|
||||
<height>555</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Pick icon</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QListView" name="iconView"/>
|
||||
</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>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>IconPickerDialog</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>IconPickerDialog</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>
|
110
application/dialogs/LoginDialog.cpp
Normal file
110
application/dialogs/LoginDialog.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
/* Copyright 2013-2015 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 "LoginDialog.h"
|
||||
#include "ui_LoginDialog.h"
|
||||
|
||||
#include "auth/YggdrasilTask.h"
|
||||
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LoginDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->progressBar->setVisible(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
LoginDialog::~LoginDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
// Stage 1: User interaction
|
||||
void LoginDialog::accept()
|
||||
{
|
||||
setUserInputsEnabled(false);
|
||||
ui->progressBar->setVisible(true);
|
||||
|
||||
// Setup the login task and start it
|
||||
m_account = MojangAccount::createFromUsername(ui->userTextBox->text());
|
||||
m_loginTask = m_account->login(nullptr, ui->passTextBox->text());
|
||||
connect(m_loginTask.get(), &ProgressProvider::failed, this, &LoginDialog::onTaskFailed);
|
||||
connect(m_loginTask.get(), &ProgressProvider::succeeded, this,
|
||||
&LoginDialog::onTaskSucceeded);
|
||||
connect(m_loginTask.get(), &ProgressProvider::status, this, &LoginDialog::onTaskStatus);
|
||||
connect(m_loginTask.get(), &ProgressProvider::progress, this, &LoginDialog::onTaskProgress);
|
||||
m_loginTask->start();
|
||||
}
|
||||
|
||||
void LoginDialog::setUserInputsEnabled(bool enable)
|
||||
{
|
||||
ui->userTextBox->setEnabled(enable);
|
||||
ui->passTextBox->setEnabled(enable);
|
||||
ui->buttonBox->setEnabled(enable);
|
||||
}
|
||||
|
||||
// Enable the OK button only when both textboxes contain something.
|
||||
void LoginDialog::on_userTextBox_textEdited(const QString &newText)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setEnabled(!newText.isEmpty() && !ui->passTextBox->text().isEmpty());
|
||||
}
|
||||
void LoginDialog::on_passTextBox_textEdited(const QString &newText)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty());
|
||||
}
|
||||
|
||||
void LoginDialog::onTaskFailed(const QString &reason)
|
||||
{
|
||||
// Set message
|
||||
ui->label->setText("<span style='color:red'>" + reason + "</span>");
|
||||
|
||||
// Re-enable user-interaction
|
||||
setUserInputsEnabled(true);
|
||||
ui->progressBar->setVisible(false);
|
||||
}
|
||||
|
||||
void LoginDialog::onTaskSucceeded()
|
||||
{
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void LoginDialog::onTaskStatus(const QString &status)
|
||||
{
|
||||
ui->label->setText(status);
|
||||
}
|
||||
|
||||
void LoginDialog::onTaskProgress(qint64 current, qint64 total)
|
||||
{
|
||||
ui->progressBar->setMaximum(total);
|
||||
ui->progressBar->setValue(current);
|
||||
}
|
||||
|
||||
// Public interface
|
||||
MojangAccountPtr LoginDialog::newAccount(QWidget *parent, QString msg)
|
||||
{
|
||||
LoginDialog dlg(parent);
|
||||
dlg.ui->label->setText(msg);
|
||||
if (dlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
return dlg.m_account;
|
||||
}
|
||||
return 0;
|
||||
}
|
58
application/dialogs/LoginDialog.h
Normal file
58
application/dialogs/LoginDialog.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* Copyright 2013-2015 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 <QtWidgets/QDialog>
|
||||
#include <QtCore/QEventLoop>
|
||||
|
||||
#include "auth/MojangAccount.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class LoginDialog;
|
||||
}
|
||||
|
||||
class LoginDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
~LoginDialog();
|
||||
|
||||
static MojangAccountPtr newAccount(QWidget *parent, QString message);
|
||||
|
||||
private:
|
||||
explicit LoginDialog(QWidget *parent = 0);
|
||||
|
||||
void setUserInputsEnabled(bool enable);
|
||||
|
||||
protected
|
||||
slots:
|
||||
void accept();
|
||||
|
||||
void onTaskFailed(const QString &reason);
|
||||
void onTaskSucceeded();
|
||||
void onTaskStatus(const QString &status);
|
||||
void onTaskProgress(qint64 current, qint64 total);
|
||||
|
||||
void on_userTextBox_textEdited(const QString &newText);
|
||||
void on_passTextBox_textEdited(const QString &newText);
|
||||
|
||||
private:
|
||||
Ui::LoginDialog *ui;
|
||||
MojangAccountPtr m_account;
|
||||
std::shared_ptr<Task> m_loginTask;
|
||||
};
|
77
application/dialogs/LoginDialog.ui
Normal file
77
application/dialogs/LoginDialog.ui
Normal file
@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LoginDialog</class>
|
||||
<widget class="QDialog" name="LoginDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>162</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Add Account</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Message label placeholder.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="userTextBox">
|
||||
<property name="placeholderText">
|
||||
<string>Email / Username</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="passTextBox">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</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>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
40
application/dialogs/ModEditDialogCommon.cpp
Normal file
40
application/dialogs/ModEditDialogCommon.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include "ModEditDialogCommon.h"
|
||||
#include "CustomMessageBox.h"
|
||||
#include <QUrl>
|
||||
|
||||
bool lastfirst(QModelIndexList &list, int &first, int &last)
|
||||
{
|
||||
if (list.isEmpty())
|
||||
return false;
|
||||
first = last = list[0].row();
|
||||
for (auto item : list)
|
||||
{
|
||||
int row = item.row();
|
||||
if (row < first)
|
||||
first = row;
|
||||
if (row > last)
|
||||
last = row;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void showWebsiteForMod(QWidget *parentDlg, Mod &m)
|
||||
{
|
||||
QString url = m.homeurl();
|
||||
if (url.size())
|
||||
{
|
||||
// catch the cases where the protocol is missing
|
||||
if (!url.startsWith("http"))
|
||||
{
|
||||
url = "http://" + url;
|
||||
}
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
else
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
parentDlg, QObject::tr("How sad!"),
|
||||
QObject::tr("The mod author didn't provide a website link for this mod."),
|
||||
QMessageBox::Warning);
|
||||
}
|
||||
}
|
9
application/dialogs/ModEditDialogCommon.h
Normal file
9
application/dialogs/ModEditDialogCommon.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <QModelIndex>
|
||||
#include <QDesktopServices>
|
||||
#include <QWidget>
|
||||
#include <minecraft/Mod.h>
|
||||
|
||||
bool lastfirst(QModelIndexList &list, int &first, int &last);
|
||||
|
||||
void showWebsiteForMod(QWidget *parentDlg, Mod &m);
|
207
application/dialogs/NewInstanceDialog.cpp
Normal file
207
application/dialogs/NewInstanceDialog.cpp
Normal file
@ -0,0 +1,207 @@
|
||||
/* Copyright 2013-2015 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 "NewInstanceDialog.h"
|
||||
#include "ui_NewInstanceDialog.h"
|
||||
|
||||
#include <BaseVersion.h>
|
||||
#include <icons/IconList.h>
|
||||
#include <minecraft/MinecraftVersionList.h>
|
||||
#include <tasks/Task.h>
|
||||
#include <InstanceList.h>
|
||||
|
||||
#include "Platform.h"
|
||||
#include "VersionSelectDialog.h"
|
||||
#include "ProgressDialog.h"
|
||||
#include "IconPickerDialog.h"
|
||||
|
||||
#include <QLayout>
|
||||
#include <QPushButton>
|
||||
#include <QFileDialog>
|
||||
#include <QValidator>
|
||||
|
||||
class UrlValidator : public QValidator
|
||||
{
|
||||
public:
|
||||
using QValidator::QValidator;
|
||||
|
||||
State validate(QString &in, int &pos) const
|
||||
{
|
||||
const QUrl url(in);
|
||||
if (url.isValid() && !url.isRelative() && !url.isEmpty())
|
||||
{
|
||||
return Acceptable;
|
||||
}
|
||||
else if (QFile::exists(in))
|
||||
{
|
||||
return Acceptable;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Intermediate;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
NewInstanceDialog::NewInstanceDialog(QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::NewInstanceDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
resize(minimumSizeHint());
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
||||
setSelectedVersion(MMC->minecraftlist()->getLatestStable(), true);
|
||||
InstIconKey = "infinity";
|
||||
ui->iconButton->setIcon(ENV.icons()->getIcon(InstIconKey));
|
||||
|
||||
ui->modpackEdit->setValidator(new UrlValidator(ui->modpackEdit));
|
||||
connect(ui->modpackEdit, &QLineEdit::textChanged, this, &NewInstanceDialog::updateDialogState);
|
||||
connect(ui->modpackBox, &QRadioButton::clicked, this, &NewInstanceDialog::updateDialogState);
|
||||
connect(ui->versionBox, &QRadioButton::clicked, this, &NewInstanceDialog::updateDialogState);
|
||||
|
||||
auto groups = MMC->instances()->getGroups().toSet();
|
||||
auto groupList = QStringList(groups.toList());
|
||||
groupList.sort(Qt::CaseInsensitive);
|
||||
groupList.removeOne("");
|
||||
QString oldValue = MMC->settings()->get("LastUsedGroupForNewInstance").toString();
|
||||
groupList.push_front(oldValue);
|
||||
groupList.push_front("");
|
||||
ui->groupBox->addItems(groupList);
|
||||
int index = groupList.indexOf(oldValue);
|
||||
if(index == -1)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
ui->groupBox->setCurrentIndex(index);
|
||||
ui->groupBox->lineEdit()->setPlaceholderText(tr("No group"));
|
||||
}
|
||||
|
||||
NewInstanceDialog::~NewInstanceDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NewInstanceDialog::updateDialogState()
|
||||
{
|
||||
bool allowOK = !instName().isEmpty() &&
|
||||
(ui->versionBox->isChecked() && m_selectedVersion ||
|
||||
(ui->modpackBox->isChecked() && ui->modpackEdit->hasAcceptableInput()));
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(allowOK);
|
||||
}
|
||||
|
||||
void NewInstanceDialog::setSelectedVersion(BaseVersionPtr version, bool initial)
|
||||
{
|
||||
m_selectedVersion = version;
|
||||
|
||||
if (m_selectedVersion)
|
||||
{
|
||||
ui->versionTextBox->setText(version->name());
|
||||
if(ui->instNameTextBox->text().isEmpty() && !initial)
|
||||
{
|
||||
ui->instNameTextBox->setText(version->name());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->versionTextBox->setText("");
|
||||
}
|
||||
|
||||
updateDialogState();
|
||||
}
|
||||
|
||||
QString NewInstanceDialog::instName() const
|
||||
{
|
||||
return ui->instNameTextBox->text();
|
||||
}
|
||||
QString NewInstanceDialog::instGroup() const
|
||||
{
|
||||
return ui->groupBox->currentText();
|
||||
}
|
||||
QString NewInstanceDialog::iconKey() const
|
||||
{
|
||||
return InstIconKey;
|
||||
}
|
||||
QUrl NewInstanceDialog::modpackUrl() const
|
||||
{
|
||||
if (ui->modpackBox->isChecked())
|
||||
{
|
||||
const QUrl url(ui->modpackEdit->text());
|
||||
if (url.isValid() && !url.isRelative() && !url.host().isEmpty())
|
||||
{
|
||||
return url;
|
||||
}
|
||||
else
|
||||
{
|
||||
return QUrl::fromLocalFile(ui->modpackEdit->text());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return QUrl();
|
||||
}
|
||||
}
|
||||
|
||||
BaseVersionPtr NewInstanceDialog::selectedVersion() const
|
||||
{
|
||||
return m_selectedVersion;
|
||||
}
|
||||
|
||||
void NewInstanceDialog::on_btnChangeVersion_clicked()
|
||||
{
|
||||
VersionSelectDialog vselect(MMC->minecraftlist().get(), tr("Change Minecraft version"),
|
||||
this);
|
||||
vselect.exec();
|
||||
if (vselect.result() == QDialog::Accepted)
|
||||
{
|
||||
BaseVersionPtr version = vselect.selectedVersion();
|
||||
if (version)
|
||||
setSelectedVersion(version);
|
||||
}
|
||||
}
|
||||
|
||||
void NewInstanceDialog::on_iconButton_clicked()
|
||||
{
|
||||
IconPickerDialog dlg(this);
|
||||
dlg.exec(InstIconKey);
|
||||
|
||||
if (dlg.result() == QDialog::Accepted)
|
||||
{
|
||||
InstIconKey = dlg.selectedIconKey;
|
||||
ui->iconButton->setIcon(ENV.icons()->getIcon(InstIconKey));
|
||||
}
|
||||
}
|
||||
|
||||
void NewInstanceDialog::on_instNameTextBox_textChanged(const QString &arg1)
|
||||
{
|
||||
updateDialogState();
|
||||
}
|
||||
|
||||
void NewInstanceDialog::on_modpackBtn_clicked()
|
||||
{
|
||||
const QUrl url = QFileDialog::getOpenFileUrl(this, tr("Choose modpack"), modpackUrl(), tr("Zip (*.zip)"));
|
||||
if (url.isValid())
|
||||
{
|
||||
if (url.isLocalFile())
|
||||
{
|
||||
ui->modpackEdit->setText(url.toLocalFile());
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->modpackEdit->setText(url.toString());
|
||||
}
|
||||
}
|
||||
}
|
59
application/dialogs/NewInstanceDialog.h
Normal file
59
application/dialogs/NewInstanceDialog.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* Copyright 2013-2015 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 "BaseVersion.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class NewInstanceDialog;
|
||||
}
|
||||
|
||||
class NewInstanceDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NewInstanceDialog(QWidget *parent = 0);
|
||||
~NewInstanceDialog();
|
||||
|
||||
void updateDialogState();
|
||||
|
||||
void setSelectedVersion(BaseVersionPtr version, bool initial = false);
|
||||
|
||||
void loadVersionList();
|
||||
|
||||
QString instName() const;
|
||||
QString instGroup() const;
|
||||
QString iconKey() const;
|
||||
QUrl modpackUrl() const;
|
||||
BaseVersionPtr selectedVersion() const;
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_btnChangeVersion_clicked();
|
||||
void on_iconButton_clicked();
|
||||
void on_modpackBtn_clicked();
|
||||
void on_instNameTextBox_textChanged(const QString &arg1);
|
||||
|
||||
private:
|
||||
Ui::NewInstanceDialog *ui;
|
||||
|
||||
BaseVersionPtr m_selectedVersion;
|
||||
QString InstIconKey;
|
||||
};
|
309
application/dialogs/NewInstanceDialog.ui
Normal file
309
application/dialogs/NewInstanceDialog.ui
Normal file
@ -0,0 +1,309 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NewInstanceDialog</class>
|
||||
<widget class="QDialog" name="NewInstanceDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>277</width>
|
||||
<height>404</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>New Instance</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset>
|
||||
<normaloff>:/icons/toolbar/new</normaloff>:/icons/toolbar/new</iconset>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="iconBtnLayout">
|
||||
<item>
|
||||
<spacer name="iconBtnLeftSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="iconButton">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/icons/instances/infinity</normaloff>:/icons/instances/infinity</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>80</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="iconBtnRightSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="instNameTextBox">
|
||||
<property name="placeholderText">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelVersion_3">
|
||||
<property name="text">
|
||||
<string>&Group:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>groupBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="groupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="4" column="2">
|
||||
<widget class="QToolButton" name="modpackBtn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLineEdit" name="modpackEdit">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>http://</string>
|
||||
</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="2" column="2">
|
||||
<widget class="QToolButton" name="btnChangeVersion">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
<widget class="QRadioButton" name="modpackBox">
|
||||
<property name="text">
|
||||
<string>Impor&t Modpack (local file or link):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<widget class="QRadioButton" name="versionBox">
|
||||
<property name="text">
|
||||
<string>Vani&lla Minecraft (select version):</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</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="Line" name="line_2">
|
||||
<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>instNameTextBox</tabstop>
|
||||
<tabstop>groupBox</tabstop>
|
||||
<tabstop>versionBox</tabstop>
|
||||
<tabstop>versionTextBox</tabstop>
|
||||
<tabstop>btnChangeVersion</tabstop>
|
||||
<tabstop>modpackBox</tabstop>
|
||||
<tabstop>modpackEdit</tabstop>
|
||||
<tabstop>modpackBtn</tabstop>
|
||||
<tabstop>iconButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>NewInstanceDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>257</x>
|
||||
<y>333</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>NewInstanceDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>325</x>
|
||||
<y>333</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>modpackBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>modpackEdit</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>81</x>
|
||||
<y>229</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>236</x>
|
||||
<y>221</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>modpackBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>modpackBtn</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>129</x>
|
||||
<y>225</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>328</x>
|
||||
<y>229</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>versionBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>versionTextBox</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>93</x>
|
||||
<y>195</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>213</x>
|
||||
<y>191</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>versionBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>btnChangeVersion</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>104</x>
|
||||
<y>198</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>322</x>
|
||||
<y>192</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
84
application/dialogs/NotificationDialog.cpp
Normal file
84
application/dialogs/NotificationDialog.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include "NotificationDialog.h"
|
||||
#include "ui_NotificationDialog.h"
|
||||
|
||||
#include <QTimerEvent>
|
||||
|
||||
NotificationDialog::NotificationDialog(const NotificationChecker::NotificationEntry &entry, QWidget *parent) :
|
||||
QDialog(parent, Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::CustomizeWindowHint),
|
||||
ui(new Ui::NotificationDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QStyle::StandardPixmap icon;
|
||||
switch (entry.type)
|
||||
{
|
||||
case NotificationChecker::NotificationEntry::Critical:
|
||||
icon = QStyle::SP_MessageBoxCritical;
|
||||
break;
|
||||
case NotificationChecker::NotificationEntry::Warning:
|
||||
icon = QStyle::SP_MessageBoxWarning;
|
||||
break;
|
||||
case NotificationChecker::NotificationEntry::Information:
|
||||
icon = QStyle::SP_MessageBoxInformation;
|
||||
break;
|
||||
}
|
||||
ui->iconLabel->setPixmap(style()->standardPixmap(icon, 0, this));
|
||||
ui->messageLabel->setText(entry.message);
|
||||
|
||||
m_dontShowAgainText = tr("Don't show again");
|
||||
m_closeText = tr("Close");
|
||||
|
||||
ui->dontShowAgainBtn->setText(m_dontShowAgainText + QString(" (%1)").arg(m_dontShowAgainTime));
|
||||
ui->closeBtn->setText(m_closeText + QString(" (%1)").arg(m_closeTime));
|
||||
|
||||
startTimer(1000);
|
||||
}
|
||||
|
||||
NotificationDialog::~NotificationDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NotificationDialog::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
if (m_dontShowAgainTime > 0)
|
||||
{
|
||||
m_dontShowAgainTime--;
|
||||
if (m_dontShowAgainTime == 0)
|
||||
{
|
||||
ui->dontShowAgainBtn->setText(m_dontShowAgainText);
|
||||
ui->dontShowAgainBtn->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->dontShowAgainBtn->setText(m_dontShowAgainText + QString(" (%1)").arg(m_dontShowAgainTime));
|
||||
}
|
||||
}
|
||||
if (m_closeTime > 0)
|
||||
{
|
||||
m_closeTime--;
|
||||
if (m_closeTime == 0)
|
||||
{
|
||||
ui->closeBtn->setText(m_closeText);
|
||||
ui->closeBtn->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->closeBtn->setText(m_closeText + QString(" (%1)").arg(m_closeTime));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_closeTime == 0 && m_dontShowAgainTime == 0)
|
||||
{
|
||||
killTimer(event->timerId());
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationDialog::on_dontShowAgainBtn_clicked()
|
||||
{
|
||||
done(DontShowAgain);
|
||||
}
|
||||
void NotificationDialog::on_closeBtn_clicked()
|
||||
{
|
||||
done(Normal);
|
||||
}
|
44
application/dialogs/NotificationDialog.h
Normal file
44
application/dialogs/NotificationDialog.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef NOTIFICATIONDIALOG_H
|
||||
#define NOTIFICATIONDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "notifications/NotificationChecker.h"
|
||||
|
||||
namespace Ui {
|
||||
class NotificationDialog;
|
||||
}
|
||||
|
||||
class NotificationDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NotificationDialog(const NotificationChecker::NotificationEntry &entry, QWidget *parent = 0);
|
||||
~NotificationDialog();
|
||||
|
||||
enum ExitCode
|
||||
{
|
||||
Normal,
|
||||
DontShowAgain
|
||||
};
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *event);
|
||||
|
||||
private:
|
||||
Ui::NotificationDialog *ui;
|
||||
|
||||
int m_dontShowAgainTime = 10;
|
||||
int m_closeTime = 5;
|
||||
|
||||
QString m_dontShowAgainText;
|
||||
QString m_closeText;
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_dontShowAgainBtn_clicked();
|
||||
void on_closeBtn_clicked();
|
||||
};
|
||||
|
||||
#endif // NOTIFICATIONDIALOG_H
|
85
application/dialogs/NotificationDialog.ui
Normal file
85
application/dialogs/NotificationDialog.ui
Normal file
@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NotificationDialog</class>
|
||||
<widget class="QDialog" name="NotificationDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>320</width>
|
||||
<height>240</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,1">
|
||||
<item>
|
||||
<widget class="QLabel" name="iconLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="messageLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="dontShowAgainBtn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Don't show again</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="closeBtn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
125
application/dialogs/ProgressDialog.cpp
Normal file
125
application/dialogs/ProgressDialog.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
/* Copyright 2013-2015 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 "ProgressDialog.h"
|
||||
#include "ui_ProgressDialog.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "tasks/Task.h"
|
||||
#include "Platform.h"
|
||||
|
||||
ProgressDialog::ProgressDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ProgressDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setSkipButton(false);
|
||||
changeProgress(0, 100);
|
||||
}
|
||||
|
||||
void ProgressDialog::setSkipButton(bool present, QString label)
|
||||
{
|
||||
ui->skipButton->setEnabled(present);
|
||||
ui->skipButton->setVisible(present);
|
||||
ui->skipButton->setText(label);
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void ProgressDialog::on_skipButton_clicked(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked);
|
||||
task->abort();
|
||||
}
|
||||
|
||||
ProgressDialog::~ProgressDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ProgressDialog::updateSize()
|
||||
{
|
||||
resize(QSize(480, minimumSizeHint().height()));
|
||||
}
|
||||
|
||||
int ProgressDialog::exec(ProgressProvider *task)
|
||||
{
|
||||
this->task = task;
|
||||
|
||||
// Connect signals.
|
||||
connect(task, SIGNAL(started()), SLOT(onTaskStarted()));
|
||||
connect(task, SIGNAL(failed(QString)), SLOT(onTaskFailed(QString)));
|
||||
connect(task, SIGNAL(succeeded()), SLOT(onTaskSucceeded()));
|
||||
connect(task, SIGNAL(status(QString)), SLOT(changeStatus(const QString &)));
|
||||
connect(task, SIGNAL(progress(qint64, qint64)), SLOT(changeProgress(qint64, qint64)));
|
||||
|
||||
// if this didn't connect to an already running task, invoke start
|
||||
if(!task->isRunning())
|
||||
task->start();
|
||||
if(task->isRunning())
|
||||
return QDialog::exec();
|
||||
else
|
||||
return QDialog::Accepted;
|
||||
}
|
||||
|
||||
ProgressProvider *ProgressDialog::getTask()
|
||||
{
|
||||
return task;
|
||||
}
|
||||
|
||||
void ProgressDialog::onTaskStarted()
|
||||
{
|
||||
}
|
||||
|
||||
void ProgressDialog::onTaskFailed(QString failure)
|
||||
{
|
||||
reject();
|
||||
}
|
||||
|
||||
void ProgressDialog::onTaskSucceeded()
|
||||
{
|
||||
accept();
|
||||
}
|
||||
|
||||
void ProgressDialog::changeStatus(const QString &status)
|
||||
{
|
||||
ui->statusLabel->setText(status);
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void ProgressDialog::changeProgress(qint64 current, qint64 total)
|
||||
{
|
||||
ui->taskProgressBar->setMaximum(total);
|
||||
ui->taskProgressBar->setValue(current);
|
||||
}
|
||||
|
||||
void ProgressDialog::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
if (e->key() == Qt::Key_Escape)
|
||||
return;
|
||||
QDialog::keyPressEvent(e);
|
||||
}
|
||||
|
||||
void ProgressDialog::closeEvent(QCloseEvent *e)
|
||||
{
|
||||
if (task && task->isRunning())
|
||||
{
|
||||
e->ignore();
|
||||
}
|
||||
else
|
||||
{
|
||||
QDialog::closeEvent(e);
|
||||
}
|
||||
}
|
65
application/dialogs/ProgressDialog.h
Normal file
65
application/dialogs/ProgressDialog.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* Copyright 2013-2015 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>
|
||||
|
||||
class ProgressProvider;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ProgressDialog;
|
||||
}
|
||||
|
||||
class ProgressDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProgressDialog(QWidget *parent = 0);
|
||||
~ProgressDialog();
|
||||
|
||||
void updateSize();
|
||||
|
||||
int exec(ProgressProvider *task);
|
||||
|
||||
void setSkipButton(bool present, QString label = QString());
|
||||
|
||||
ProgressProvider *getTask();
|
||||
|
||||
public
|
||||
slots:
|
||||
void onTaskStarted();
|
||||
void onTaskFailed(QString failure);
|
||||
void onTaskSucceeded();
|
||||
|
||||
void changeStatus(const QString &status);
|
||||
void changeProgress(qint64 current, qint64 total);
|
||||
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_skipButton_clicked(bool checked);
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent(QKeyEvent *e);
|
||||
virtual void closeEvent(QCloseEvent *e);
|
||||
|
||||
private:
|
||||
Ui::ProgressDialog *ui;
|
||||
|
||||
ProgressProvider *task;
|
||||
};
|
66
application/dialogs/ProgressDialog.ui
Normal file
66
application/dialogs/ProgressDialog.ui
Normal file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ProgressDialog</class>
|
||||
<widget class="QDialog" name="ProgressDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>100</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Please wait...</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="statusLabel">
|
||||
<property name="text">
|
||||
<string>Task Status...</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QProgressBar" name="taskProgressBar">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="skipButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Skip</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
186
application/dialogs/UpdateDialog.cpp
Normal file
186
application/dialogs/UpdateDialog.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
#include "UpdateDialog.h"
|
||||
#include "ui_UpdateDialog.h"
|
||||
#include "Platform.h"
|
||||
#include <QDebug>
|
||||
#include "MultiMC.h"
|
||||
#include <settings/SettingsObject.h>
|
||||
|
||||
UpdateDialog::UpdateDialog(bool hasUpdate, QWidget *parent) : QDialog(parent), ui(new Ui::UpdateDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
auto channel = MMC->settings()->get("UpdateChannel").toString();
|
||||
if(hasUpdate)
|
||||
{
|
||||
ui->label->setText(tr("A new %1 update is available!").arg(channel));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->label->setText(tr("No %1 updates found. You are running the latest version.").arg(channel));
|
||||
ui->btnUpdateNow->setDisabled(true);
|
||||
ui->btnUpdateOnExit->setDisabled(true);
|
||||
}
|
||||
loadChangelog();
|
||||
}
|
||||
|
||||
UpdateDialog::~UpdateDialog()
|
||||
{
|
||||
}
|
||||
|
||||
void UpdateDialog::loadChangelog()
|
||||
{
|
||||
auto channel = MMC->settings()->get("UpdateChannel").toString();
|
||||
dljob.reset(new NetJob("Changelog"));
|
||||
auto url = QString("https://raw.githubusercontent.com/MultiMC/MultiMC5/%1/changelog.md").arg(channel);
|
||||
changelogDownload = ByteArrayDownload::make(QUrl(url));
|
||||
dljob->addNetAction(changelogDownload);
|
||||
connect(dljob.get(), &NetJob::succeeded, this, &UpdateDialog::changelogLoaded);
|
||||
connect(dljob.get(), &NetJob::failed, this, &UpdateDialog::changelogFailed);
|
||||
dljob->start();
|
||||
}
|
||||
|
||||
// TODO: this will be replaced.
|
||||
QString reprocessMarkdown(QString markdown)
|
||||
{
|
||||
QString htmlData;
|
||||
QTextStream html(&htmlData);
|
||||
auto lines = markdown.split(QRegExp("[\r]?[\n]"),QString::KeepEmptyParts);
|
||||
enum
|
||||
{
|
||||
BASE,
|
||||
LIST1,
|
||||
LIST2
|
||||
}state = BASE;
|
||||
html << "<html>";
|
||||
int i = 0;
|
||||
auto procLine = [&](QString line) -> QString
|
||||
{
|
||||
// [GitHub issues](https://github.com/MultiMC/MultiMC5/issues)
|
||||
line.replace(QRegExp("\\[([^\\]]+)\\]\\(([^\\)]+)\\)"), "<a href=\"\\2\">\\1</a>");
|
||||
return line;
|
||||
};
|
||||
for(auto line: lines)
|
||||
{
|
||||
if(line.isEmpty())
|
||||
{
|
||||
// html << "<br />\n";
|
||||
}
|
||||
else switch (state)
|
||||
{
|
||||
case BASE:
|
||||
if(line.startsWith("##"))
|
||||
{
|
||||
html << "<h2>" << procLine(line.mid(2)) << "</h2>\n";
|
||||
}
|
||||
else if(line.startsWith("#"))
|
||||
{
|
||||
html << "<h1>" << procLine(line.mid(1)) << "</h1>\n";
|
||||
}
|
||||
else if(line.startsWith("- "))
|
||||
{
|
||||
state = LIST1;
|
||||
html << "<ul>\n";
|
||||
html << "<li>" << procLine(line.mid(2)) << "</li>\n";
|
||||
}
|
||||
else qCritical() << "Invalid input on line " << i << ": " << line;
|
||||
break;
|
||||
case LIST1:
|
||||
if(line.startsWith("##"))
|
||||
{
|
||||
state = BASE;
|
||||
html << "</ul>\n";
|
||||
html << "<h2>" << procLine(line.mid(2)) << "</h2>\n";
|
||||
}
|
||||
else if(line.startsWith("#"))
|
||||
{
|
||||
state = BASE;
|
||||
html << "</ul>\n";
|
||||
html << "<h1>" << procLine(line.mid(1)) << "</h1>\n";
|
||||
}
|
||||
else if(line.startsWith("- "))
|
||||
{
|
||||
html << "<li>" << procLine(line.mid(2)) << "</li>\n";
|
||||
}
|
||||
else if(line.startsWith(" - "))
|
||||
{
|
||||
state = LIST2;
|
||||
html << "<ul>\n";
|
||||
html << "<li>" << procLine(line.mid(4)) << "</li>\n";
|
||||
}
|
||||
else qCritical() << "Invalid input on line " << i << ": " << line;
|
||||
break;
|
||||
case LIST2:
|
||||
if(line.startsWith("##"))
|
||||
{
|
||||
state = BASE;
|
||||
html << "</ul>\n";
|
||||
html << "</ul>\n";
|
||||
html << "<h2>" << procLine(line.mid(2)) << "</h2>\n";
|
||||
}
|
||||
else if(line.startsWith("#"))
|
||||
{
|
||||
state = BASE;
|
||||
html << "</ul>\n";
|
||||
html << "</ul>\n";
|
||||
html << "<h1>" << procLine(line.mid(1)) << "</h1>\n";
|
||||
}
|
||||
else if(line.startsWith("- "))
|
||||
{
|
||||
state = LIST1;
|
||||
html << "</ul>\n";
|
||||
html << "<li>" << procLine(line.mid(2)) << "</li>\n";
|
||||
}
|
||||
else if(line.startsWith(" - "))
|
||||
{
|
||||
html << "<li>" << procLine(line.mid(4)) << "</li>\n";
|
||||
}
|
||||
else qCritical() << "Invalid input on line " << i << ": " << line;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if(state == LIST2)
|
||||
{
|
||||
html << "</ul>\n";
|
||||
state = LIST1;
|
||||
}
|
||||
if(state == LIST1)
|
||||
{
|
||||
html << "</ul>\n";
|
||||
state = BASE;
|
||||
}
|
||||
if (state != BASE)
|
||||
{
|
||||
qCritical() << "Reprocessing markdown didn't end in a final state!";
|
||||
}
|
||||
html << "</html>\n";
|
||||
qDebug() << htmlData;
|
||||
return htmlData;
|
||||
}
|
||||
|
||||
void UpdateDialog::changelogLoaded()
|
||||
{
|
||||
auto rawMarkdown = QString::fromUtf8(changelogDownload->m_data);
|
||||
auto html = reprocessMarkdown(rawMarkdown);
|
||||
ui->changelogBrowser->setHtml(html);
|
||||
}
|
||||
|
||||
void UpdateDialog::changelogFailed()
|
||||
{
|
||||
ui->changelogBrowser->setHtml(tr("<p align=\"center\" <span style=\"font-size:22pt;\">Failed to fetch changelog...</span></p>"));
|
||||
}
|
||||
|
||||
void UpdateDialog::on_btnUpdateLater_clicked()
|
||||
{
|
||||
reject();
|
||||
}
|
||||
|
||||
void UpdateDialog::on_btnUpdateNow_clicked()
|
||||
{
|
||||
done(UPDATE_NOW);
|
||||
}
|
||||
|
||||
void UpdateDialog::on_btnUpdateOnExit_clicked()
|
||||
{
|
||||
done(UPDATE_ONEXIT);
|
||||
}
|
61
application/dialogs/UpdateDialog.h
Normal file
61
application/dialogs/UpdateDialog.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* Copyright 2013-2015 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 "net/ByteArrayDownload.h"
|
||||
#include "net/NetJob.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class UpdateDialog;
|
||||
}
|
||||
|
||||
enum UpdateAction
|
||||
{
|
||||
UPDATE_LATER = QDialog::Rejected,
|
||||
UPDATE_NOW = QDialog::Accepted,
|
||||
UPDATE_ONEXIT = 2
|
||||
};
|
||||
|
||||
class UpdateDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UpdateDialog(bool hasUpdate = true, QWidget *parent = 0);
|
||||
~UpdateDialog();
|
||||
|
||||
private:
|
||||
Ui::UpdateDialog *ui;
|
||||
public slots:
|
||||
void on_btnUpdateNow_clicked();
|
||||
void on_btnUpdateOnExit_clicked();
|
||||
void on_btnUpdateLater_clicked();
|
||||
|
||||
/// Starts loading the changelog
|
||||
void loadChangelog();
|
||||
|
||||
/// Slot for when the chengelog loads successfully.
|
||||
void changelogLoaded();
|
||||
|
||||
/// Slot for when the chengelog fails to load...
|
||||
void changelogFailed();
|
||||
|
||||
private:
|
||||
ByteArrayDownloadPtr changelogDownload;
|
||||
NetJobPtr dljob;
|
||||
};
|
106
application/dialogs/UpdateDialog.ui
Normal file
106
application/dialogs/UpdateDialog.ui
Normal file
@ -0,0 +1,106 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UpdateDialog</class>
|
||||
<widget class="QDialog" name="UpdateDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>657</width>
|
||||
<height>673</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MultiMC Update</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset>
|
||||
<normaloff>:/icons/toolbar/checkupdate</normaloff>:/icons/toolbar/checkupdate</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>changelogBrowser</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="changelogBrowser">
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:22pt;">Loading changelog...</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnUpdateNow">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update now</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnUpdateOnExit">
|
||||
<property name="text">
|
||||
<string>Update after MultiMC closes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnUpdateLater">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Don't update yet</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>changelogBrowser</tabstop>
|
||||
<tabstop>btnUpdateNow</tabstop>
|
||||
<tabstop>btnUpdateOnExit</tabstop>
|
||||
<tabstop>btnUpdateLater</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../resources/multimc/multimc.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
177
application/dialogs/VersionSelectDialog.cpp
Normal file
177
application/dialogs/VersionSelectDialog.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
/* Copyright 2013-2015 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 "VersionSelectDialog.h"
|
||||
#include "ui_VersionSelectDialog.h"
|
||||
|
||||
#include <QHeaderView>
|
||||
|
||||
#include <dialogs/ProgressDialog.h>
|
||||
#include "Platform.h"
|
||||
|
||||
#include <BaseVersion.h>
|
||||
#include <BaseVersionList.h>
|
||||
#include <tasks/Task.h>
|
||||
#include <modutils.h>
|
||||
#include <QDebug>
|
||||
|
||||
class VersionSelectProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VersionSelectProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
struct Filter
|
||||
{
|
||||
QString string;
|
||||
bool exact = false;
|
||||
};
|
||||
|
||||
QHash<int, Filter> filters() const
|
||||
{
|
||||
return m_filters;
|
||||
}
|
||||
void setFilter(const int column, const QString &filter, const bool exact)
|
||||
{
|
||||
Filter f;
|
||||
f.string = filter;
|
||||
f.exact = exact;
|
||||
m_filters[column] = f;
|
||||
invalidateFilter();
|
||||
}
|
||||
void clearFilters()
|
||||
{
|
||||
m_filters.clear();
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
for (auto it = m_filters.begin(); it != m_filters.end(); ++it)
|
||||
{
|
||||
const QString version =
|
||||
sourceModel()->index(source_row, it.key()).data().toString();
|
||||
|
||||
if (it.value().exact)
|
||||
{
|
||||
if (version != it.value().string)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Util::versionIsInInterval(version, it.value().string))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QHash<int, Filter> m_filters;
|
||||
};
|
||||
|
||||
VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent,
|
||||
bool cancelable)
|
||||
: QDialog(parent), ui(new Ui::VersionSelectDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
setWindowModality(Qt::WindowModal);
|
||||
setWindowTitle(title);
|
||||
|
||||
m_vlist = vlist;
|
||||
|
||||
m_proxyModel = new VersionSelectProxyModel(this);
|
||||
m_proxyModel->setSourceModel(vlist);
|
||||
|
||||
ui->listView->setModel(m_proxyModel);
|
||||
ui->listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch);
|
||||
|
||||
if (!cancelable)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setEmptyString(QString emptyString)
|
||||
{
|
||||
ui->listView->setEmptyString(emptyString);
|
||||
}
|
||||
|
||||
VersionSelectDialog::~VersionSelectDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setResizeOn(int column)
|
||||
{
|
||||
ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::ResizeToContents);
|
||||
resizeOnColumn = column;
|
||||
ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
int VersionSelectDialog::exec()
|
||||
{
|
||||
QDialog::open();
|
||||
if (!m_vlist->isLoaded())
|
||||
{
|
||||
loadList();
|
||||
}
|
||||
m_proxyModel->invalidate();
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
void VersionSelectDialog::loadList()
|
||||
{
|
||||
Task *loadTask = m_vlist->getLoadTask();
|
||||
if (!loadTask)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ProgressDialog *taskDlg = new ProgressDialog(this);
|
||||
loadTask->setParent(taskDlg);
|
||||
taskDlg->exec(loadTask);
|
||||
delete taskDlg;
|
||||
}
|
||||
|
||||
BaseVersionPtr VersionSelectDialog::selectedVersion() const
|
||||
{
|
||||
auto currentIndex = ui->listView->selectionModel()->currentIndex();
|
||||
auto variant = m_proxyModel->data(currentIndex, BaseVersionList::VersionPointerRole);
|
||||
return variant.value<BaseVersionPtr>();
|
||||
}
|
||||
|
||||
void VersionSelectDialog::on_refreshButton_clicked()
|
||||
{
|
||||
loadList();
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setExactFilter(int column, QString filter)
|
||||
{
|
||||
m_proxyModel->setFilter(column, filter, true);
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setFuzzyFilter(int column, QString filter)
|
||||
{
|
||||
m_proxyModel->setFilter(column, filter, false);
|
||||
}
|
||||
|
||||
#include "VersionSelectDialog.moc"
|
66
application/dialogs/VersionSelectDialog.h
Normal file
66
application/dialogs/VersionSelectDialog.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* Copyright 2013-2015 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 <QSortFilterProxyModel>
|
||||
|
||||
#include "BaseVersion.h"
|
||||
|
||||
class BaseVersionList;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class VersionSelectDialog;
|
||||
}
|
||||
|
||||
class VersionSelectProxyModel;
|
||||
|
||||
class VersionSelectDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent = 0,
|
||||
bool cancelable = true);
|
||||
~VersionSelectDialog();
|
||||
|
||||
virtual int exec();
|
||||
|
||||
//! Starts a task that loads the list.
|
||||
void loadList();
|
||||
|
||||
BaseVersionPtr selectedVersion() const;
|
||||
|
||||
void setFuzzyFilter(int column, QString filter);
|
||||
void setExactFilter(int column, QString filter);
|
||||
void setEmptyString(QString emptyString);
|
||||
void setResizeOn(int column);
|
||||
void setUseLatest(const bool useLatest);
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_refreshButton_clicked();
|
||||
|
||||
private:
|
||||
Ui::VersionSelectDialog *ui;
|
||||
|
||||
BaseVersionList *m_vlist;
|
||||
|
||||
VersionSelectProxyModel *m_proxyModel;
|
||||
|
||||
int resizeOnColumn = 0;
|
||||
};
|
110
application/dialogs/VersionSelectDialog.ui
Normal file
110
application/dialogs/VersionSelectDialog.ui
Normal file
@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>VersionSelectDialog</class>
|
||||
<widget class="QDialog" name="VersionSelectDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>347</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Choose Version</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="VersionListView" name="listView">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerCascadingSectionResizes">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="refreshButton">
|
||||
<property name="toolTip">
|
||||
<string>Reloads the version list.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Refresh</string>
|
||||
</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>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>VersionListView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>widgets/VersionListView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>VersionSelectDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>257</x>
|
||||
<y>290</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>VersionSelectDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>325</x>
|
||||
<y>290</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
1003
application/groupview/GroupView.cpp
Normal file
1003
application/groupview/GroupView.cpp
Normal file
File diff suppressed because it is too large
Load Diff
125
application/groupview/GroupView.h
Normal file
125
application/groupview/GroupView.h
Normal file
@ -0,0 +1,125 @@
|
||||
#pragma once
|
||||
|
||||
#include <QListView>
|
||||
#include <QLineEdit>
|
||||
#include <QScrollBar>
|
||||
#include <QCache>
|
||||
|
||||
struct GroupViewRoles
|
||||
{
|
||||
enum
|
||||
{
|
||||
GroupRole = Qt::UserRole,
|
||||
ProgressValueRole,
|
||||
ProgressMaximumRole
|
||||
};
|
||||
};
|
||||
|
||||
struct VisualGroup;
|
||||
|
||||
class GroupView : public QAbstractItemView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GroupView(QWidget *parent = 0);
|
||||
~GroupView();
|
||||
|
||||
void setModel(QAbstractItemModel *model) override;
|
||||
|
||||
/// return geometry rectangle occupied by the specified model item
|
||||
QRect geometryRect(const QModelIndex &index) const;
|
||||
/// return visual rectangle occupied by the specified model item
|
||||
virtual QRect visualRect(const QModelIndex &index) const override;
|
||||
/// get the model index at the specified visual point
|
||||
virtual QModelIndex indexAt(const QPoint &point) const override;
|
||||
void setSelection(const QRect &rect,
|
||||
const QItemSelectionModel::SelectionFlags commands) override;
|
||||
|
||||
virtual int horizontalOffset() const override;
|
||||
virtual int verticalOffset() const override;
|
||||
virtual void scrollContentsBy(int dx, int dy) override;
|
||||
virtual void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override;
|
||||
|
||||
virtual QModelIndex moveCursor(CursorAction cursorAction,
|
||||
Qt::KeyboardModifiers modifiers) override;
|
||||
|
||||
virtual QRegion visualRegionForSelection(const QItemSelection &selection) const override;
|
||||
|
||||
int spacing() const
|
||||
{
|
||||
return m_spacing;
|
||||
};
|
||||
protected
|
||||
slots:
|
||||
virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
||||
const QVector<int> &roles) override;
|
||||
virtual void rowsInserted(const QModelIndex &parent, int start, int end) override;
|
||||
virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override;
|
||||
virtual void updateGeometries() override;
|
||||
void modelReset();
|
||||
|
||||
protected:
|
||||
virtual bool isIndexHidden(const QModelIndex &index) const override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
void dragLeaveEvent(QDragLeaveEvent *event) override;
|
||||
void dropEvent(QDropEvent *event) override;
|
||||
|
||||
void startDrag(Qt::DropActions supportedActions) override;
|
||||
|
||||
private:
|
||||
friend struct VisualGroup;
|
||||
QList<VisualGroup *> m_groups;
|
||||
|
||||
// geometry
|
||||
int m_leftMargin = 5;
|
||||
int m_rightMargin = 5;
|
||||
int m_bottomMargin = 5;
|
||||
int m_categoryMargin = 5;
|
||||
int m_spacing = 5;
|
||||
int m_itemWidth = 100;
|
||||
int m_currentItemsPerRow = -1;
|
||||
int m_currentCursorColumn= -1;
|
||||
mutable QCache<int, QRect> geometryCache;
|
||||
|
||||
// point where the currently active mouse action started in geometry coordinates
|
||||
QPoint m_pressedPosition;
|
||||
QPersistentModelIndex m_pressedIndex;
|
||||
bool m_pressedAlreadySelected;
|
||||
VisualGroup *m_pressedCategory;
|
||||
QItemSelectionModel::SelectionFlag m_ctrlDragSelectionFlag;
|
||||
QPoint m_lastDragPosition;
|
||||
|
||||
VisualGroup *category(const QModelIndex &index) const;
|
||||
VisualGroup *category(const QString &cat) const;
|
||||
VisualGroup *categoryAt(const QPoint &pos) const;
|
||||
|
||||
int itemsPerRow() const
|
||||
{
|
||||
return m_currentItemsPerRow;
|
||||
};
|
||||
int contentWidth() const;
|
||||
|
||||
private: /* methods */
|
||||
int itemWidth() const;
|
||||
int calculateItemsPerRow() const;
|
||||
int verticalScrollToValue(const QModelIndex &index, const QRect &rect,
|
||||
QListView::ScrollHint hint) const;
|
||||
QPixmap renderToPixmap(const QModelIndexList &indices, QRect *r) const;
|
||||
QList<QPair<QRect, QModelIndex>> draggablePaintPairs(const QModelIndexList &indices,
|
||||
QRect *r) const;
|
||||
|
||||
bool isDragEventAccepted(QDropEvent *event);
|
||||
|
||||
QPair<VisualGroup *, int> rowDropPos(const QPoint &pos);
|
||||
|
||||
QPoint offset() const;
|
||||
};
|
42
application/groupview/GroupedProxyModel.cpp
Normal file
42
application/groupview/GroupedProxyModel.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "GroupedProxyModel.h"
|
||||
|
||||
#include "GroupView.h"
|
||||
#include <QDebug>
|
||||
|
||||
GroupedProxyModel::GroupedProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool GroupedProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
const QString leftCategory = left.data(GroupViewRoles::GroupRole).toString();
|
||||
const QString rightCategory = right.data(GroupViewRoles::GroupRole).toString();
|
||||
if (leftCategory == rightCategory)
|
||||
{
|
||||
return subSortLessThan(left, right);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: real group sorting happens in GroupView::updateGeometries(), see LocaleString
|
||||
auto result = leftCategory.localeAwareCompare(rightCategory);
|
||||
if(result < 0)
|
||||
{
|
||||
qDebug() << leftCategory << "<" << rightCategory;
|
||||
}
|
||||
if(result == 0)
|
||||
{
|
||||
qDebug() << leftCategory << "=" << rightCategory;
|
||||
return subSortLessThan(left, right);
|
||||
}
|
||||
if(result > 0)
|
||||
{
|
||||
qDebug() << leftCategory << ">" << rightCategory;
|
||||
}
|
||||
return result < 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool GroupedProxyModel::subSortLessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
return left.row() < right.row();
|
||||
}
|
15
application/groupview/GroupedProxyModel.h
Normal file
15
application/groupview/GroupedProxyModel.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class GroupedProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GroupedProxyModel(QObject *parent = 0);
|
||||
|
||||
protected:
|
||||
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||
};
|
362
application/groupview/InstanceDelegate.cpp
Normal file
362
application/groupview/InstanceDelegate.cpp
Normal file
@ -0,0 +1,362 @@
|
||||
/* Copyright 2013-2015 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 "InstanceDelegate.h"
|
||||
#include <QPainter>
|
||||
#include <QTextOption>
|
||||
#include <QTextLayout>
|
||||
#include <QApplication>
|
||||
#include <QtMath>
|
||||
|
||||
#include "GroupView.h"
|
||||
#include "BaseInstance.h"
|
||||
#include "InstanceList.h"
|
||||
|
||||
QCache<QString, QPixmap> ListViewDelegate::m_pixmapCache;
|
||||
|
||||
// Origin: Qt
|
||||
static void viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &height,
|
||||
qreal &widthUsed)
|
||||
{
|
||||
height = 0;
|
||||
widthUsed = 0;
|
||||
textLayout.beginLayout();
|
||||
QString str = textLayout.text();
|
||||
while (true)
|
||||
{
|
||||
QTextLine line = textLayout.createLine();
|
||||
if (!line.isValid())
|
||||
break;
|
||||
if (line.textLength() == 0)
|
||||
break;
|
||||
line.setLineWidth(lineWidth);
|
||||
line.setPosition(QPointF(0, height));
|
||||
height += line.height();
|
||||
widthUsed = qMax(widthUsed, line.naturalTextWidth());
|
||||
}
|
||||
textLayout.endLayout();
|
||||
}
|
||||
|
||||
ListViewDelegate::ListViewDelegate(QObject *parent) : QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void drawSelectionRect(QPainter *painter, const QStyleOptionViewItemV4 &option,
|
||||
const QRect &rect)
|
||||
{
|
||||
if ((option.state & QStyle::State_Selected))
|
||||
painter->fillRect(rect, option.palette.brush(QPalette::Highlight));
|
||||
else
|
||||
{
|
||||
QColor backgroundColor = option.palette.color(QPalette::Background);
|
||||
backgroundColor.setAlpha(160);
|
||||
painter->fillRect(rect, QBrush(backgroundColor));
|
||||
}
|
||||
}
|
||||
|
||||
void drawFocusRect(QPainter *painter, const QStyleOptionViewItemV4 &option, const QRect &rect)
|
||||
{
|
||||
if (!(option.state & QStyle::State_HasFocus))
|
||||
return;
|
||||
QStyleOptionFocusRect opt;
|
||||
opt.direction = option.direction;
|
||||
opt.fontMetrics = option.fontMetrics;
|
||||
opt.palette = option.palette;
|
||||
opt.rect = rect;
|
||||
// opt.state = option.state | QStyle::State_KeyboardFocusChange |
|
||||
// QStyle::State_Item;
|
||||
auto col = option.state & QStyle::State_Selected ? QPalette::Highlight : QPalette::Base;
|
||||
opt.backgroundColor = option.palette.color(col);
|
||||
// Apparently some widget styles expect this hint to not be set
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
QStyle *style = option.widget ? option.widget->style() : QApplication::style();
|
||||
|
||||
style->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, painter, option.widget);
|
||||
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
}
|
||||
|
||||
// TODO this can be made a lot prettier
|
||||
void drawProgressOverlay(QPainter *painter, const QStyleOptionViewItemV4 &option,
|
||||
const int value, const int maximum)
|
||||
{
|
||||
if (maximum == 0 || value == maximum)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
painter->save();
|
||||
|
||||
qreal percent = (qreal)value / (qreal)maximum;
|
||||
QColor color = option.palette.color(QPalette::Dark);
|
||||
color.setAlphaF(0.70f);
|
||||
painter->setBrush(color);
|
||||
painter->setPen(QPen(QBrush(), 0));
|
||||
painter->drawPie(option.rect, 90 * 16, -percent * 360 * 16);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void drawBadges(QPainter *painter, const QStyleOptionViewItemV4 &option, BaseInstance *instance)
|
||||
{
|
||||
QList<QString> pixmaps;
|
||||
const BaseInstance::InstanceFlags flags = instance->flags();
|
||||
if (flags & BaseInstance::VersionBrokenFlag)
|
||||
{
|
||||
pixmaps.append("broken");
|
||||
}
|
||||
if (flags & BaseInstance::UpdateAvailable)
|
||||
{
|
||||
pixmaps.append("updateavailable");
|
||||
}
|
||||
|
||||
// begin easter eggs
|
||||
if (instance->name().contains("btw", Qt::CaseInsensitive) ||
|
||||
instance->name().contains("better then wolves", Qt::CaseInsensitive) ||
|
||||
instance->name().contains("better than wolves", Qt::CaseInsensitive))
|
||||
{
|
||||
pixmaps.append("herobrine");
|
||||
}
|
||||
if (instance->name().contains("direwolf", Qt::CaseInsensitive))
|
||||
{
|
||||
pixmaps.append("enderman");
|
||||
}
|
||||
if (instance->name().contains("kitten", Qt::CaseInsensitive))
|
||||
{
|
||||
pixmaps.append("kitten");
|
||||
}
|
||||
if (instance->name().contains("derp", Qt::CaseInsensitive))
|
||||
{
|
||||
pixmaps.append("derp");
|
||||
}
|
||||
// end easter eggs
|
||||
|
||||
static const int itemSide = 24;
|
||||
static const int spacing = 1;
|
||||
const int itemsPerRow = qMax(1, qFloor(double(option.rect.width() + spacing) / double(itemSide + spacing)));
|
||||
const int rows = qCeil((double)pixmaps.size() / (double)itemsPerRow);
|
||||
QListIterator<QString> it(pixmaps);
|
||||
painter->translate(option.rect.topLeft());
|
||||
for (int y = 0; y < rows; ++y)
|
||||
{
|
||||
for (int x = 0; x < itemsPerRow; ++x)
|
||||
{
|
||||
if (!it.hasNext())
|
||||
{
|
||||
return;
|
||||
}
|
||||
const QPixmap pixmap = ListViewDelegate::requestBadgePixmap(it.next()).scaled(
|
||||
itemSide, itemSide, Qt::KeepAspectRatio, Qt::FastTransformation);
|
||||
painter->drawPixmap(option.rect.width() - x * itemSide + qMax(x - 1, 0) * spacing - itemSide,
|
||||
y * itemSide + qMax(y - 1, 0) * spacing, itemSide, itemSide,
|
||||
pixmap);
|
||||
}
|
||||
}
|
||||
painter->translate(-option.rect.topLeft());
|
||||
}
|
||||
|
||||
static QSize viewItemTextSize(const QStyleOptionViewItemV4 *option)
|
||||
{
|
||||
QStyle *style = option->widget ? option->widget->style() : QApplication::style();
|
||||
QTextOption textOption;
|
||||
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
||||
QTextLayout textLayout;
|
||||
textLayout.setTextOption(textOption);
|
||||
textLayout.setFont(option->font);
|
||||
textLayout.setText(option->text);
|
||||
const int textMargin =
|
||||
style->pixelMetric(QStyle::PM_FocusFrameHMargin, option, option->widget) + 1;
|
||||
QRect bounds(0, 0, 100 - 2 * textMargin, 600);
|
||||
qreal height = 0, widthUsed = 0;
|
||||
viewItemTextLayout(textLayout, bounds.width(), height, widthUsed);
|
||||
const QSize size(qCeil(widthUsed), qCeil(height));
|
||||
return QSize(size.width() + 2 * textMargin, size.height());
|
||||
}
|
||||
|
||||
void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
QStyleOptionViewItemV4 opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
painter->save();
|
||||
painter->setClipRect(opt.rect);
|
||||
|
||||
opt.features |= QStyleOptionViewItem::WrapText;
|
||||
opt.text = index.data().toString();
|
||||
opt.textElideMode = Qt::ElideRight;
|
||||
opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter;
|
||||
|
||||
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||
|
||||
// const int iconSize = style->pixelMetric(QStyle::PM_IconViewIconSize);
|
||||
const int iconSize = 48;
|
||||
QRect iconbox = opt.rect;
|
||||
const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, opt.widget) + 1;
|
||||
QRect textRect = opt.rect;
|
||||
QRect textHighlightRect = textRect;
|
||||
// clip the decoration on top, remove width padding
|
||||
textRect.adjust(textMargin, iconSize + textMargin + 5, -textMargin, 0);
|
||||
|
||||
textHighlightRect.adjust(0, iconSize + 5, 0, 0);
|
||||
|
||||
// draw background
|
||||
{
|
||||
// FIXME: unused
|
||||
// QSize textSize = viewItemTextSize ( &opt );
|
||||
QPalette::ColorGroup cg;
|
||||
QStyleOptionViewItemV4 opt2(opt);
|
||||
|
||||
if ((opt.widget && opt.widget->isEnabled()) || (opt.state & QStyle::State_Enabled))
|
||||
{
|
||||
if (!(opt.state & QStyle::State_Active))
|
||||
cg = QPalette::Inactive;
|
||||
else
|
||||
cg = QPalette::Normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
cg = QPalette::Disabled;
|
||||
}
|
||||
opt2.palette.setCurrentColorGroup(cg);
|
||||
|
||||
// fill in background, if any
|
||||
|
||||
if (opt.backgroundBrush.style() != Qt::NoBrush)
|
||||
{
|
||||
QPointF oldBO = painter->brushOrigin();
|
||||
painter->setBrushOrigin(opt.rect.topLeft());
|
||||
painter->fillRect(opt.rect, opt.backgroundBrush);
|
||||
painter->setBrushOrigin(oldBO);
|
||||
}
|
||||
|
||||
drawSelectionRect(painter, opt2, textHighlightRect);
|
||||
|
||||
/*
|
||||
if (opt.showDecorationSelected)
|
||||
{
|
||||
drawSelectionRect(painter, opt2, opt.rect);
|
||||
drawFocusRect(painter, opt2, opt.rect);
|
||||
// painter->fillRect ( opt.rect, opt.palette.brush ( cg, QPalette::Highlight ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// if ( opt.state & QStyle::State_Selected )
|
||||
{
|
||||
// QRect textRect = subElementRect ( QStyle::SE_ItemViewItemText, opt,
|
||||
// opt.widget );
|
||||
// painter->fillRect ( textHighlightRect, opt.palette.brush ( cg,
|
||||
// QPalette::Highlight ) );
|
||||
drawSelectionRect(painter, opt2, textHighlightRect);
|
||||
drawFocusRect(painter, opt2, textHighlightRect);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// draw the icon
|
||||
{
|
||||
QIcon::Mode mode = QIcon::Normal;
|
||||
if (!(opt.state & QStyle::State_Enabled))
|
||||
mode = QIcon::Disabled;
|
||||
else if (opt.state & QStyle::State_Selected)
|
||||
mode = QIcon::Selected;
|
||||
QIcon::State state = opt.state & QStyle::State_Open ? QIcon::On : QIcon::Off;
|
||||
|
||||
iconbox.setHeight(iconSize);
|
||||
opt.icon.paint(painter, iconbox, Qt::AlignCenter, mode, state);
|
||||
}
|
||||
// set the text colors
|
||||
QPalette::ColorGroup cg =
|
||||
opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
|
||||
if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active))
|
||||
cg = QPalette::Inactive;
|
||||
if (opt.state & QStyle::State_Selected)
|
||||
{
|
||||
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
||||
}
|
||||
|
||||
// draw the text
|
||||
QTextOption textOption;
|
||||
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
||||
textOption.setTextDirection(opt.direction);
|
||||
textOption.setAlignment(QStyle::visualAlignment(opt.direction, opt.displayAlignment));
|
||||
QTextLayout textLayout;
|
||||
textLayout.setTextOption(textOption);
|
||||
textLayout.setFont(opt.font);
|
||||
textLayout.setText(opt.text);
|
||||
|
||||
qreal width, height;
|
||||
viewItemTextLayout(textLayout, textRect.width(), height, width);
|
||||
|
||||
const int lineCount = textLayout.lineCount();
|
||||
|
||||
const QRect layoutRect = QStyle::alignedRect(
|
||||
opt.direction, opt.displayAlignment, QSize(textRect.width(), int(height)), textRect);
|
||||
const QPointF position = layoutRect.topLeft();
|
||||
for (int i = 0; i < lineCount; ++i)
|
||||
{
|
||||
const QTextLine line = textLayout.lineAt(i);
|
||||
line.draw(painter, position);
|
||||
}
|
||||
|
||||
// FIXME: this really has no business of being here. Make generic.
|
||||
auto instance = (BaseInstance*)index.data(InstanceList::InstancePointerRole)
|
||||
.value<void *>();
|
||||
if (instance)
|
||||
{
|
||||
drawBadges(painter, opt, instance);
|
||||
}
|
||||
|
||||
drawProgressOverlay(painter, opt, index.data(GroupViewRoles::ProgressValueRole).toInt(),
|
||||
index.data(GroupViewRoles::ProgressMaximumRole).toInt());
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
QStyleOptionViewItemV4 opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
opt.features |= QStyleOptionViewItem::WrapText;
|
||||
opt.text = index.data().toString();
|
||||
opt.textElideMode = Qt::ElideRight;
|
||||
opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter;
|
||||
|
||||
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||
const int textMargin =
|
||||
style->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, opt.widget) + 1;
|
||||
int height = 48 + textMargin * 2 + 5; // TODO: turn constants into variables
|
||||
QSize szz = viewItemTextSize(&opt);
|
||||
height += szz.height();
|
||||
// FIXME: maybe the icon items could scale and keep proportions?
|
||||
QSize sz(100, height);
|
||||
return sz;
|
||||
}
|
||||
|
||||
QPixmap ListViewDelegate::requestBadgePixmap(const QString &key)
|
||||
{
|
||||
if (!m_pixmapCache.contains(key))
|
||||
{
|
||||
m_pixmapCache.insert(key, new QPixmap(":/icons/badges/" + key + ".png"));
|
||||
}
|
||||
return *m_pixmapCache.object(key);
|
||||
}
|
35
application/groupview/InstanceDelegate.h
Normal file
35
application/groupview/InstanceDelegate.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* Copyright 2013-2015 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 <QStyledItemDelegate>
|
||||
#include <QCache>
|
||||
|
||||
class ListViewDelegate : public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
explicit ListViewDelegate(QObject *parent = 0);
|
||||
|
||||
static QPixmap requestBadgePixmap(const QString &key);
|
||||
|
||||
protected:
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
|
||||
private:
|
||||
static QCache<QString, QPixmap> m_pixmapCache;
|
||||
};
|
301
application/groupview/VisualGroup.cpp
Normal file
301
application/groupview/VisualGroup.cpp
Normal file
@ -0,0 +1,301 @@
|
||||
#include "VisualGroup.h"
|
||||
|
||||
#include <QModelIndex>
|
||||
#include <QPainter>
|
||||
#include <QtMath>
|
||||
#include <QApplication>
|
||||
|
||||
#include "GroupView.h"
|
||||
|
||||
VisualGroup::VisualGroup(const QString &text, GroupView *view) : view(view), text(text), collapsed(false)
|
||||
{
|
||||
}
|
||||
|
||||
VisualGroup::VisualGroup(const VisualGroup *other)
|
||||
: view(other->view), text(other->text), collapsed(other->collapsed)
|
||||
{
|
||||
}
|
||||
|
||||
void VisualGroup::update()
|
||||
{
|
||||
auto temp_items = items();
|
||||
auto itemsPerRow = view->itemsPerRow();
|
||||
|
||||
int numRows = qMax(1, qCeil((qreal)temp_items.size() / (qreal)itemsPerRow));
|
||||
rows = QVector<VisualRow>(numRows);
|
||||
|
||||
int maxRowHeight = 0;
|
||||
int positionInRow = 0;
|
||||
int currentRow = 0;
|
||||
int offsetFromTop = 0;
|
||||
for (auto item: temp_items)
|
||||
{
|
||||
if(positionInRow == itemsPerRow)
|
||||
{
|
||||
rows[currentRow].height = maxRowHeight;
|
||||
rows[currentRow].top = offsetFromTop;
|
||||
currentRow ++;
|
||||
offsetFromTop += maxRowHeight + 5;
|
||||
positionInRow = 0;
|
||||
maxRowHeight = 0;
|
||||
}
|
||||
auto itemHeight = view->itemDelegate()->sizeHint(view->viewOptions(), item).height();
|
||||
if(itemHeight > maxRowHeight)
|
||||
{
|
||||
maxRowHeight = itemHeight;
|
||||
}
|
||||
rows[currentRow].items.append(item);
|
||||
positionInRow++;
|
||||
}
|
||||
rows[currentRow].height = maxRowHeight;
|
||||
rows[currentRow].top = offsetFromTop;
|
||||
}
|
||||
|
||||
QPair<int, int> VisualGroup::positionOf(const QModelIndex &index) const
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
for (auto & row: rows)
|
||||
{
|
||||
for(auto x = 0; x < row.items.size(); x++)
|
||||
{
|
||||
if(row.items[x] == index)
|
||||
{
|
||||
return qMakePair(x,y);
|
||||
}
|
||||
}
|
||||
y++;
|
||||
}
|
||||
return qMakePair(x, y);
|
||||
}
|
||||
|
||||
int VisualGroup::rowTopOf(const QModelIndex &index) const
|
||||
{
|
||||
auto position = positionOf(index);
|
||||
return rows[position.second].top;
|
||||
}
|
||||
|
||||
int VisualGroup::rowHeightOf(const QModelIndex &index) const
|
||||
{
|
||||
auto position = positionOf(index);
|
||||
return rows[position.second].height;
|
||||
}
|
||||
|
||||
VisualGroup::HitResults VisualGroup::hitScan(const QPoint &pos) const
|
||||
{
|
||||
VisualGroup::HitResults results = VisualGroup::NoHit;
|
||||
int y_start = verticalPosition();
|
||||
int body_start = y_start + headerHeight();
|
||||
int body_end = body_start + contentHeight() + 5; // FIXME: wtf is this 5?
|
||||
int y = pos.y();
|
||||
// int x = pos.x();
|
||||
if (y < y_start)
|
||||
{
|
||||
results = VisualGroup::NoHit;
|
||||
}
|
||||
else if (y < body_start)
|
||||
{
|
||||
results = VisualGroup::HeaderHit;
|
||||
int collapseSize = headerHeight() - 4;
|
||||
|
||||
// the icon
|
||||
QRect iconRect = QRect(view->m_leftMargin + 2, 2 + y_start, collapseSize, collapseSize);
|
||||
if (iconRect.contains(pos))
|
||||
{
|
||||
results |= VisualGroup::CheckboxHit;
|
||||
}
|
||||
}
|
||||
else if (y < body_end)
|
||||
{
|
||||
results |= VisualGroup::BodyHit;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &option)
|
||||
{
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
const QRect optRect = option.rect;
|
||||
QFont font(QApplication::font());
|
||||
font.setBold(true);
|
||||
const QFontMetrics fontMetrics = QFontMetrics(font);
|
||||
|
||||
QColor outlineColor = option.palette.text().color();
|
||||
outlineColor.setAlphaF(0.35);
|
||||
|
||||
//BEGIN: top left corner
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen(outlineColor);
|
||||
const QPointF topLeft(optRect.topLeft());
|
||||
QRectF arc(topLeft, QSizeF(4, 4));
|
||||
arc.translate(0.5, 0.5);
|
||||
painter->drawArc(arc, 1440, 1440);
|
||||
painter->restore();
|
||||
}
|
||||
//END: top left corner
|
||||
|
||||
//BEGIN: left vertical line
|
||||
{
|
||||
QPoint start(optRect.topLeft());
|
||||
start.ry() += 3;
|
||||
QPoint verticalGradBottom(optRect.topLeft());
|
||||
verticalGradBottom.ry() += fontMetrics.height() + 5;
|
||||
QLinearGradient gradient(start, verticalGradBottom);
|
||||
gradient.setColorAt(0, outlineColor);
|
||||
gradient.setColorAt(1, Qt::transparent);
|
||||
painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient);
|
||||
}
|
||||
//END: left vertical line
|
||||
|
||||
//BEGIN: horizontal line
|
||||
{
|
||||
QPoint start(optRect.topLeft());
|
||||
start.rx() += 3;
|
||||
QPoint horizontalGradTop(optRect.topLeft());
|
||||
horizontalGradTop.rx() += optRect.width() - 6;
|
||||
painter->fillRect(QRect(start, QSize(optRect.width() - 6, 1)), outlineColor);
|
||||
}
|
||||
//END: horizontal line
|
||||
|
||||
//BEGIN: top right corner
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen(outlineColor);
|
||||
QPointF topRight(optRect.topRight());
|
||||
topRight.rx() -= 4;
|
||||
QRectF arc(topRight, QSizeF(4, 4));
|
||||
arc.translate(0.5, 0.5);
|
||||
painter->drawArc(arc, 0, 1440);
|
||||
painter->restore();
|
||||
}
|
||||
//END: top right corner
|
||||
|
||||
//BEGIN: right vertical line
|
||||
{
|
||||
QPoint start(optRect.topRight());
|
||||
start.ry() += 3;
|
||||
QPoint verticalGradBottom(optRect.topRight());
|
||||
verticalGradBottom.ry() += fontMetrics.height() + 5;
|
||||
QLinearGradient gradient(start, verticalGradBottom);
|
||||
gradient.setColorAt(0, outlineColor);
|
||||
gradient.setColorAt(1, Qt::transparent);
|
||||
painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient);
|
||||
}
|
||||
//END: right vertical line
|
||||
|
||||
//BEGIN: checkboxy thing
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
painter->setFont(font);
|
||||
QColor penColor(option.palette.text().color());
|
||||
penColor.setAlphaF(0.6);
|
||||
painter->setPen(penColor);
|
||||
QRect iconSubRect(option.rect);
|
||||
iconSubRect.setTop(iconSubRect.top() + 7);
|
||||
iconSubRect.setLeft(iconSubRect.left() + 7);
|
||||
|
||||
int sizing = fontMetrics.height();
|
||||
int even = ( (sizing - 1) % 2 );
|
||||
|
||||
iconSubRect.setHeight(sizing - even);
|
||||
iconSubRect.setWidth(sizing - even);
|
||||
painter->drawRect(iconSubRect);
|
||||
|
||||
|
||||
/*
|
||||
if(collapsed)
|
||||
painter->drawText(iconSubRect, Qt::AlignHCenter | Qt::AlignVCenter, "+");
|
||||
else
|
||||
painter->drawText(iconSubRect, Qt::AlignHCenter | Qt::AlignVCenter, "-");
|
||||
*/
|
||||
painter->setBrush(option.palette.text());
|
||||
painter->fillRect(iconSubRect.x(), iconSubRect.y() + iconSubRect.height() / 2,
|
||||
iconSubRect.width(), 2, penColor);
|
||||
if (collapsed)
|
||||
{
|
||||
painter->fillRect(iconSubRect.x() + iconSubRect.width() / 2, iconSubRect.y(), 2,
|
||||
iconSubRect.height(), penColor);
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
//END: checkboxy thing
|
||||
|
||||
//BEGIN: text
|
||||
{
|
||||
QRect textRect(option.rect);
|
||||
textRect.setTop(textRect.top() + 7);
|
||||
textRect.setLeft(textRect.left() + 7 + fontMetrics.height() + 7);
|
||||
textRect.setHeight(fontMetrics.height());
|
||||
textRect.setRight(textRect.right() - 7);
|
||||
|
||||
painter->save();
|
||||
painter->setFont(font);
|
||||
QColor penColor(option.palette.text().color());
|
||||
penColor.setAlphaF(0.6);
|
||||
painter->setPen(penColor);
|
||||
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text);
|
||||
painter->restore();
|
||||
}
|
||||
//END: text
|
||||
}
|
||||
|
||||
int VisualGroup::totalHeight() const
|
||||
{
|
||||
return headerHeight() + 5 + contentHeight(); // FIXME: wtf is that '5'?
|
||||
}
|
||||
|
||||
int VisualGroup::headerHeight() const
|
||||
{
|
||||
QFont font(QApplication::font());
|
||||
font.setBold(true);
|
||||
QFontMetrics fontMetrics(font);
|
||||
|
||||
const int height = fontMetrics.height() + 1 /* 1 pixel-width gradient */
|
||||
+ 11 /* top and bottom separation */;
|
||||
return height;
|
||||
/*
|
||||
int raw = view->viewport()->fontMetrics().height() + 4;
|
||||
// add english. maybe. depends on font height.
|
||||
if (raw % 2 == 0)
|
||||
raw++;
|
||||
return std::min(raw, 25);
|
||||
*/
|
||||
}
|
||||
|
||||
int VisualGroup::contentHeight() const
|
||||
{
|
||||
if (collapsed)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
auto last = rows[numRows() - 1];
|
||||
return last.top + last.height;
|
||||
}
|
||||
|
||||
int VisualGroup::numRows() const
|
||||
{
|
||||
return rows.size();
|
||||
}
|
||||
|
||||
int VisualGroup::verticalPosition() const
|
||||
{
|
||||
return m_verticalPosition;
|
||||
}
|
||||
|
||||
QList<QModelIndex> VisualGroup::items() const
|
||||
{
|
||||
QList<QModelIndex> indices;
|
||||
for (int i = 0; i < view->model()->rowCount(); ++i)
|
||||
{
|
||||
const QModelIndex index = view->model()->index(i, 0);
|
||||
if (index.data(GroupViewRoles::GroupRole).toString() == text)
|
||||
{
|
||||
indices.append(index);
|
||||
}
|
||||
}
|
||||
return indices;
|
||||
}
|
91
application/groupview/VisualGroup.h
Normal file
91
application/groupview/VisualGroup.h
Normal file
@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QRect>
|
||||
#include <QVector>
|
||||
#include <QStyleOption>
|
||||
|
||||
class GroupView;
|
||||
class QPainter;
|
||||
class QModelIndex;
|
||||
|
||||
struct VisualRow
|
||||
{
|
||||
QList<QModelIndex> items;
|
||||
int height = 0;
|
||||
int top = 0;
|
||||
inline int size() const
|
||||
{
|
||||
return items.size();
|
||||
}
|
||||
inline QModelIndex &operator[](int i)
|
||||
{
|
||||
return items[i];
|
||||
}
|
||||
};
|
||||
|
||||
struct VisualGroup
|
||||
{
|
||||
/* constructors */
|
||||
VisualGroup(const QString &text, GroupView *view);
|
||||
VisualGroup(const VisualGroup *other);
|
||||
|
||||
/* data */
|
||||
GroupView *view = nullptr;
|
||||
QString text;
|
||||
bool collapsed = false;
|
||||
QVector<VisualRow> rows;
|
||||
int firstItemIndex = 0;
|
||||
int m_verticalPosition = 0;
|
||||
|
||||
/* logic */
|
||||
/// update the internal list of items and flow them into the rows.
|
||||
void update();
|
||||
|
||||
/// draw the header at y-position.
|
||||
void drawHeader(QPainter *painter, const QStyleOptionViewItem &option);
|
||||
|
||||
/// height of the group, in total. includes a small bit of padding.
|
||||
int totalHeight() const;
|
||||
|
||||
/// height of the group header, in pixels
|
||||
int headerHeight() const;
|
||||
|
||||
/// height of the group content, in pixels
|
||||
int contentHeight() const;
|
||||
|
||||
/// the number of visual rows this group has
|
||||
int numRows() const;
|
||||
|
||||
/// actually calculate the above value
|
||||
int calculateNumRows() const;
|
||||
|
||||
/// the height at which this group starts, in pixels
|
||||
int verticalPosition() const;
|
||||
|
||||
/// relative geometry - top of the row of the given item
|
||||
int rowTopOf(const QModelIndex &index) const;
|
||||
|
||||
/// height of the row of the given item
|
||||
int rowHeightOf(const QModelIndex &index) const;
|
||||
|
||||
/// x/y position of the given item inside the group (in items!)
|
||||
QPair<int, int> positionOf(const QModelIndex &index) const;
|
||||
|
||||
enum HitResult
|
||||
{
|
||||
NoHit = 0x0,
|
||||
TextHit = 0x1,
|
||||
CheckboxHit = 0x2,
|
||||
HeaderHit = 0x4,
|
||||
BodyHit = 0x8
|
||||
};
|
||||
Q_DECLARE_FLAGS(HitResults, HitResult)
|
||||
|
||||
/// shoot! BANG! what did we hit?
|
||||
HitResults hitScan (const QPoint &pos) const;
|
||||
|
||||
QList<QModelIndex> items() const;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(VisualGroup::HitResults)
|
24
application/install_prereqs.cmake.in
Normal file
24
application/install_prereqs.cmake.in
Normal file
@ -0,0 +1,24 @@
|
||||
set(CMAKE_MODULE_PATH "@CMAKE_MODULE_PATH@")
|
||||
|
||||
file(GLOB_RECURSE QTPLUGINS "${CMAKE_INSTALL_PREFIX}/@PLUGIN_DEST_DIR@/*@CMAKE_SHARED_LIBRARY_SUFFIX@")
|
||||
function(gp_resolved_file_type_override resolved_file type_var)
|
||||
if(resolved_file MATCHES "^/usr/lib/libQt")
|
||||
message("resolving ${resolved_file} as other")
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
elseif(resolved_file MATCHES "^/usr/lib(.+)?/libxcb")
|
||||
message("resolving ${resolved_file} as other")
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
elseif(resolved_file MATCHES "^/usr/lib(.+)?/libicu")
|
||||
message("resolving ${resolved_file} as other")
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
set(gp_tool "@CMAKE_GP_TOOL@")
|
||||
set(gp_cmd_paths ${gp_cmd_paths}
|
||||
"@CMAKE_GP_CMD_PATHS@"
|
||||
)
|
||||
|
||||
include(BundleUtilities)
|
||||
fixup_bundle("@APPS@" "${QTPLUGINS}" "@DIRS@")
|
||||
|
43
application/main.cpp
Normal file
43
application/main.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "MultiMC.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
int main_gui(MultiMC &app)
|
||||
{
|
||||
// show main window
|
||||
app.setIconTheme(MMC->settings()->get("IconTheme").toString());
|
||||
MainWindow mainWin;
|
||||
mainWin.restoreState(QByteArray::fromBase64(MMC->settings()->get("MainWindowState").toByteArray()));
|
||||
mainWin.restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("MainWindowGeometry").toByteArray()));
|
||||
mainWin.show();
|
||||
mainWin.checkSetDefaultJava();
|
||||
mainWin.checkInstancePathForProblems();
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// initialize Qt
|
||||
MultiMC app(argc, argv);
|
||||
|
||||
Q_INIT_RESOURCE(instances);
|
||||
Q_INIT_RESOURCE(multimc);
|
||||
Q_INIT_RESOURCE(backgrounds);
|
||||
Q_INIT_RESOURCE(versions);
|
||||
|
||||
Q_INIT_RESOURCE(pe_dark);
|
||||
Q_INIT_RESOURCE(pe_light);
|
||||
Q_INIT_RESOURCE(pe_blue);
|
||||
Q_INIT_RESOURCE(pe_colored);
|
||||
Q_INIT_RESOURCE(OSX);
|
||||
Q_INIT_RESOURCE(iOS);
|
||||
|
||||
switch (app.status())
|
||||
{
|
||||
case MultiMC::Initialized:
|
||||
return main_gui(app);
|
||||
case MultiMC::Failed:
|
||||
return 1;
|
||||
case MultiMC::Succeeded:
|
||||
return 0;
|
||||
}
|
||||
}
|
80
application/package/linux/MultiMC
Executable file
80
application/package/linux/MultiMC
Executable file
@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
# Basic start script for running MultiMC with the libs packaged with it.
|
||||
|
||||
function printerror {
|
||||
printf "$1"
|
||||
if which zenity >/dev/null; then zenity --error --text="$1" &>/dev/null;
|
||||
elif which kdialog >/dev/null; then kdialog --error "$1" &>/dev/null;
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
printerror "This program should not be run using sudo or as the root user!\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
MMC_DIR="$(dirname "$(readlink -f "$0")")"
|
||||
echo "MultiMC Dir: ${MMC_DIR}"
|
||||
|
||||
# Set up env
|
||||
export LD_LIBRARY_PATH="${MMC_DIR}/bin":$LD_LIBRARY_PATH
|
||||
export QT_PLUGIN_PATH="${MMC_DIR}/plugins"
|
||||
export QT_FONTPATH="${MMC_DIR}/fonts"
|
||||
|
||||
# Detect missing dependencies...
|
||||
DEPS_LIST=`ldd "${MMC_DIR}"/plugins/*/*.so 2>/dev/null | grep "not found" | awk -vORS=", " '{ print $1 }'`
|
||||
if [ "x$DEPS_LIST" = "x" ]; then
|
||||
# We have all our dependencies. Run MultiMC.
|
||||
echo "No missing dependencies found."
|
||||
|
||||
# Just to be sure...
|
||||
chmod +x "${MMC_DIR}/bin/MultiMC"
|
||||
|
||||
# Run MultiMC
|
||||
"${MMC_DIR}/bin/MultiMC" -d "${MMC_DIR}" $@
|
||||
|
||||
# Run MultiMC in valgrind
|
||||
# valgrind --log-file="valgrind.log" --leak-check=full --track-origins=yes "${MMC_DIR}/bin/MultiMC" -d "${MMC_DIR}" $@
|
||||
|
||||
# Exit with MultiMC's exit code.
|
||||
exit $?
|
||||
else
|
||||
# apt
|
||||
if which apt-file &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*"`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do apt-file -l search $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo apt-get install $COMMAND_LIBS"
|
||||
# pacman
|
||||
elif which pkgfile &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*"`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do pkgfile $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo pacman -S $COMMAND_LIBS"
|
||||
# yum
|
||||
elif which yum &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*"`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do yum whatprovides $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo yum install $COMMAND_LIBS"
|
||||
# zypper
|
||||
elif which zypper &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*"`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do zypper wp $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo zypper install $COMMAND_LIBS"
|
||||
# emerge
|
||||
elif which pfl &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*"`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do pfl $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo emerge $COMMAND_LIBS"
|
||||
fi
|
||||
|
||||
MESSAGE="Error: MultiMC is missing the following libraries that it needs to work correctly:\n\t${DEPS_LIST}\nPlease install them from your distribution's package manager."
|
||||
MESSAGE="$MESSAGE\n\nHint: $INSTALL_CMD\n"
|
||||
|
||||
printerror "$MESSAGE"
|
||||
exit 1
|
||||
fi
|
62
application/pagedialog/PageDialog.cpp
Normal file
62
application/pagedialog/PageDialog.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
/* Copyright 2013-2015 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 "PageDialog.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "MultiMC.h"
|
||||
#include "settings/SettingsObject.h"
|
||||
#include "Platform.h"
|
||||
#include "widgets/IconLabel.h"
|
||||
#include "widgets/PageContainer.h"
|
||||
|
||||
PageDialog::PageDialog(BasePageProviderPtr pageProvider, QString defaultId, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
setWindowTitle(pageProvider->dialogTitle());
|
||||
m_container = new PageContainer(pageProvider, defaultId, this);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(m_container);
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(mainLayout);
|
||||
|
||||
QDialogButtonBox *buttons =
|
||||
new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Close);
|
||||
buttons->button(QDialogButtonBox::Close)->setDefault(true);
|
||||
m_container->addButtons(buttons);
|
||||
|
||||
connect(buttons->button(QDialogButtonBox::Close), SIGNAL(clicked()), this, SLOT(close()));
|
||||
connect(buttons->button(QDialogButtonBox::Help), SIGNAL(clicked()), m_container,
|
||||
SLOT(help()));
|
||||
|
||||
restoreGeometry(
|
||||
QByteArray::fromBase64(MMC->settings()->get("PagedGeometry").toByteArray()));
|
||||
}
|
||||
|
||||
void PageDialog::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if (m_container->requestClose(event))
|
||||
{
|
||||
MMC->settings()->set("PagedGeometry", saveGeometry().toBase64());
|
||||
QDialog::closeEvent(event);
|
||||
}
|
||||
}
|
36
application/pagedialog/PageDialog.h
Normal file
36
application/pagedialog/PageDialog.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* Copyright 2013-2015 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 "pages/BasePageProvider.h"
|
||||
|
||||
class PageContainer;
|
||||
class PageDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PageDialog(BasePageProviderPtr pageProvider, QString defaultId = QString(),
|
||||
QWidget *parent = 0);
|
||||
virtual ~PageDialog() {}
|
||||
|
||||
private
|
||||
slots:
|
||||
virtual void closeEvent(QCloseEvent *event);
|
||||
|
||||
private:
|
||||
PageContainer * m_container;
|
||||
};
|
38
application/pages/BasePage.h
Normal file
38
application/pages/BasePage.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* Copyright 2013-2015 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 <QString>
|
||||
#include <QIcon>
|
||||
#include <memory>
|
||||
|
||||
class BasePage
|
||||
{
|
||||
public:
|
||||
virtual ~BasePage() {}
|
||||
virtual QString id() const = 0;
|
||||
virtual QString displayName() const = 0;
|
||||
virtual QIcon icon() const = 0;
|
||||
virtual bool apply() { return true; }
|
||||
virtual bool shouldDisplay() const { return true; }
|
||||
virtual QString helpPage() const { return QString(); }
|
||||
virtual void opened() {}
|
||||
virtual void closed() {}
|
||||
int stackIndex = -1;
|
||||
int listIndex = -1;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<BasePage> BasePagePtr;
|
69
application/pages/BasePageProvider.h
Normal file
69
application/pages/BasePageProvider.h
Normal file
@ -0,0 +1,69 @@
|
||||
/* Copyright 2013-2015 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 "BasePage.h"
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
class BasePageProvider
|
||||
{
|
||||
public:
|
||||
virtual QList<BasePage *> getPages() = 0;
|
||||
virtual QString dialogTitle() = 0;
|
||||
};
|
||||
|
||||
class GenericPageProvider : public BasePageProvider
|
||||
{
|
||||
typedef std::function<BasePage *()> PageCreator;
|
||||
public:
|
||||
explicit GenericPageProvider(const QString &dialogTitle)
|
||||
: m_dialogTitle(dialogTitle)
|
||||
{
|
||||
}
|
||||
|
||||
QList<BasePage *> getPages() override
|
||||
{
|
||||
QList<BasePage *> pages;
|
||||
for (PageCreator creator : m_creators)
|
||||
{
|
||||
pages.append(creator());
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
QString dialogTitle() override { return m_dialogTitle; }
|
||||
|
||||
void setDialogTitle(const QString &title)
|
||||
{
|
||||
m_dialogTitle = title;
|
||||
}
|
||||
void addPageCreator(PageCreator page)
|
||||
{
|
||||
m_creators.append(page);
|
||||
}
|
||||
|
||||
template<typename PageClass>
|
||||
void addPage()
|
||||
{
|
||||
addPageCreator([](){return new PageClass();});
|
||||
}
|
||||
|
||||
private:
|
||||
QList<PageCreator> m_creators;
|
||||
QString m_dialogTitle;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<BasePageProvider> BasePageProviderPtr;
|
216
application/pages/InstanceSettingsPage.cpp
Normal file
216
application/pages/InstanceSettingsPage.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
#include "InstanceSettingsPage.h"
|
||||
#include "ui_InstanceSettingsPage.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "dialogs/VersionSelectDialog.h"
|
||||
#include "NagUtils.h"
|
||||
#include "java/JavaVersionList.h"
|
||||
#include "MultiMC.h"
|
||||
|
||||
InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::InstanceSettingsPage), m_instance(inst)
|
||||
{
|
||||
m_settings = &(inst->settings());
|
||||
ui->setupUi(this);
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
bool InstanceSettingsPage::shouldDisplay() const
|
||||
{
|
||||
return !m_instance->isRunning();
|
||||
}
|
||||
|
||||
InstanceSettingsPage::~InstanceSettingsPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool InstanceSettingsPage::apply()
|
||||
{
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::applySettings()
|
||||
{
|
||||
// Console
|
||||
bool console = ui->consoleSettingsBox->isChecked();
|
||||
m_settings->set("OverrideConsole", console);
|
||||
if (console)
|
||||
{
|
||||
m_settings->set("ShowConsole", ui->showConsoleCheck->isChecked());
|
||||
m_settings->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("ShowConsole");
|
||||
m_settings->reset("AutoCloseConsole");
|
||||
}
|
||||
|
||||
// Window Size
|
||||
bool window = ui->windowSizeGroupBox->isChecked();
|
||||
m_settings->set("OverrideWindow", window);
|
||||
if (window)
|
||||
{
|
||||
m_settings->set("LaunchMaximized", ui->maximizedCheckBox->isChecked());
|
||||
m_settings->set("MinecraftWinWidth", ui->windowWidthSpinBox->value());
|
||||
m_settings->set("MinecraftWinHeight", ui->windowHeightSpinBox->value());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("LaunchMaximized");
|
||||
m_settings->reset("MinecraftWinWidth");
|
||||
m_settings->reset("MinecraftWinHeight");
|
||||
}
|
||||
|
||||
// Memory
|
||||
bool memory = ui->memoryGroupBox->isChecked();
|
||||
m_settings->set("OverrideMemory", memory);
|
||||
if (memory)
|
||||
{
|
||||
m_settings->set("MinMemAlloc", ui->minMemSpinBox->value());
|
||||
m_settings->set("MaxMemAlloc", ui->maxMemSpinBox->value());
|
||||
m_settings->set("PermGen", ui->permGenSpinBox->value());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("MinMemAlloc");
|
||||
m_settings->reset("MaxMemAlloc");
|
||||
m_settings->reset("PermGen");
|
||||
}
|
||||
|
||||
// Java Install Settings
|
||||
bool javaInstall = ui->javaSettingsGroupBox->isChecked();
|
||||
m_settings->set("OverrideJavaLocation", javaInstall);
|
||||
if (javaInstall)
|
||||
{
|
||||
m_settings->set("JavaPath", ui->javaPathTextBox->text());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("JavaPath");
|
||||
}
|
||||
|
||||
// Java arguments
|
||||
bool javaArgs = ui->javaArgumentsGroupBox->isChecked();
|
||||
m_settings->set("OverrideJavaArgs", javaArgs);
|
||||
if(javaArgs)
|
||||
{
|
||||
m_settings->set("JvmArgs", ui->jvmArgsTextBox->toPlainText().replace("\n", " "));
|
||||
NagUtils::checkJVMArgs(m_settings->get("JvmArgs").toString(), this->parentWidget());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("JvmArgs");
|
||||
}
|
||||
|
||||
// old generic 'override both' is removed.
|
||||
m_settings->reset("OverrideJava");
|
||||
|
||||
// Custom Commands
|
||||
bool custcmd = ui->customCommandsGroupBox->isChecked();
|
||||
m_settings->set("OverrideCommands", custcmd);
|
||||
if (custcmd)
|
||||
{
|
||||
m_settings->set("PreLaunchCommand", ui->preLaunchCmdTextBox->text());
|
||||
m_settings->set("PostExitCommand", ui->postExitCmdTextBox->text());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("PreLaunchCommand");
|
||||
m_settings->reset("PostExitCommand");
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::loadSettings()
|
||||
{
|
||||
// Console
|
||||
ui->consoleSettingsBox->setChecked(m_settings->get("OverrideConsole").toBool());
|
||||
ui->showConsoleCheck->setChecked(m_settings->get("ShowConsole").toBool());
|
||||
ui->autoCloseConsoleCheck->setChecked(m_settings->get("AutoCloseConsole").toBool());
|
||||
|
||||
// Window Size
|
||||
ui->windowSizeGroupBox->setChecked(m_settings->get("OverrideWindow").toBool());
|
||||
ui->maximizedCheckBox->setChecked(m_settings->get("LaunchMaximized").toBool());
|
||||
ui->windowWidthSpinBox->setValue(m_settings->get("MinecraftWinWidth").toInt());
|
||||
ui->windowHeightSpinBox->setValue(m_settings->get("MinecraftWinHeight").toInt());
|
||||
|
||||
// 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());
|
||||
ui->permGenSpinBox->setValue(m_settings->get("PermGen").toInt());
|
||||
|
||||
// Java Settings
|
||||
bool overrideJava = m_settings->get("OverrideJava").toBool();
|
||||
bool overrideLocation = m_settings->get("OverrideJavaLocation").toBool() || overrideJava;
|
||||
bool overrideArgs = m_settings->get("OverrideJavaArgs").toBool() || overrideJava;
|
||||
|
||||
ui->javaSettingsGroupBox->setChecked(overrideLocation);
|
||||
ui->javaPathTextBox->setText(m_settings->get("JavaPath").toString());
|
||||
|
||||
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->postExitCmdTextBox->setText(m_settings->get("PostExitCommand").toString());
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::on_javaDetectBtn_clicked()
|
||||
{
|
||||
JavaVersionPtr java;
|
||||
|
||||
VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true);
|
||||
vselect.setResizeOn(2);
|
||||
vselect.exec();
|
||||
|
||||
if (vselect.result() == QDialog::Accepted && vselect.selectedVersion())
|
||||
{
|
||||
java = std::dynamic_pointer_cast<JavaVersion>(vselect.selectedVersion());
|
||||
ui->javaPathTextBox->setText(java->path);
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::on_javaBrowseBtn_clicked()
|
||||
{
|
||||
QString dir = QFileDialog::getOpenFileName(this, tr("Find Java executable"));
|
||||
if (!dir.isNull())
|
||||
{
|
||||
ui->javaPathTextBox->setText(dir);
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::on_javaTestBtn_clicked()
|
||||
{
|
||||
checker.reset(new JavaChecker());
|
||||
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
|
||||
SLOT(checkFinished(JavaCheckResult)));
|
||||
checker->path = ui->javaPathTextBox->text();
|
||||
checker->performCheck();
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::checkFinished(JavaCheckResult result)
|
||||
{
|
||||
if (result.valid)
|
||||
{
|
||||
QString text;
|
||||
text += "Java test succeeded!\n";
|
||||
if (result.is_64bit)
|
||||
text += "Using 64bit java.\n";
|
||||
text += "\n";
|
||||
text += "Platform reported: " + result.realPlatform;
|
||||
QMessageBox::information(this, tr("Java test success"), text);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(
|
||||
this, tr("Java test failure"),
|
||||
tr("The specified java binary didn't work. You should use the auto-detect feature, "
|
||||
"or set the path to the java executable."));
|
||||
}
|
||||
}
|
74
application/pages/InstanceSettingsPage.h
Normal file
74
application/pages/InstanceSettingsPage.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* Copyright 2013-2015 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 "java/JavaChecker.h"
|
||||
#include "BaseInstance.h"
|
||||
#include "BasePage.h"
|
||||
#include "MultiMC.h"
|
||||
|
||||
class JavaChecker;
|
||||
namespace Ui
|
||||
{
|
||||
class InstanceSettingsPage;
|
||||
}
|
||||
|
||||
class InstanceSettingsPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit InstanceSettingsPage(BaseInstance *inst, QWidget *parent = 0);
|
||||
virtual ~InstanceSettingsPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Settings");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("instance-settings");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "settings";
|
||||
}
|
||||
virtual bool apply();
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Instance-settings";
|
||||
}
|
||||
virtual bool shouldDisplay() const;
|
||||
private slots:
|
||||
void on_javaDetectBtn_clicked();
|
||||
|
||||
void on_javaTestBtn_clicked();
|
||||
|
||||
void on_javaBrowseBtn_clicked();
|
||||
|
||||
void checkFinished(JavaCheckResult result);
|
||||
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
|
||||
private:
|
||||
Ui::InstanceSettingsPage *ui;
|
||||
BaseInstance *m_instance;
|
||||
SettingsObject *m_settings;
|
||||
std::shared_ptr<JavaChecker> checker;
|
||||
};
|
453
application/pages/InstanceSettingsPage.ui
Normal file
453
application/pages/InstanceSettingsPage.ui
Normal file
@ -0,0 +1,453 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>InstanceSettingsPage</class>
|
||||
<widget class="QWidget" name="InstanceSettingsPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>458</width>
|
||||
<height>426</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="settingsTabs">
|
||||
<property name="tabShape">
|
||||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="minecraftTab">
|
||||
<attribute name="title">
|
||||
<string>Java</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="javaSettingsGroupBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Java installation</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="3">
|
||||
<widget class="QLineEdit" name="javaPathTextBox"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="javaDetectBtn">
|
||||
<property name="text">
|
||||
<string>Auto-detect...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="javaBrowseBtn">
|
||||
<property name="text">
|
||||
<string>Browse...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="javaTestBtn">
|
||||
<property name="text">
|
||||
<string>Test</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="memoryGroupBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Memory</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="maxMemSpinBox">
|
||||
<property name="toolTip">
|
||||
<string>The maximum amount of memory Minecraft is allowed to use.</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MB</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>512</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65536</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1024</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelMinMem">
|
||||
<property name="text">
|
||||
<string>Minimum memory allocation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelMaxMem">
|
||||
<property name="text">
|
||||
<string>Maximum memory allocation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="minMemSpinBox">
|
||||
<property name="toolTip">
|
||||
<string>The amount of memory Minecraft is started with.</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MB</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>256</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65536</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>256</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="permGenSpinBox">
|
||||
<property name="toolTip">
|
||||
<string>The amount of memory available to store loaded Java classes.</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MB</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>64</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>64</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelPermGen">
|
||||
<property name="text">
|
||||
<string>PermGen:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="javaArgumentsGroupBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Java arguments</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="1" column="1">
|
||||
<widget class="QPlainTextEdit" name="jvmArgsTextBox"/>
|
||||
</item>
|
||||
</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">
|
||||
<attribute name="title">
|
||||
<string>Game windows</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="windowSizeGroupBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Game Window</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="maximizedCheckBox">
|
||||
<property name="text">
|
||||
<string>Start Minecraft maximized?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayoutWindowSize">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelWindowHeight">
|
||||
<property name="text">
|
||||
<string>Window height:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelWindowWidth">
|
||||
<property name="text">
|
||||
<string>Window width:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="windowWidthSpinBox">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65536</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>854</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="windowHeightSpinBox">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65536</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>480</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="consoleSettingsBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Console Settings</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="showConsoleCheck">
|
||||
<property name="text">
|
||||
<string>Show console while the game is running?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="autoCloseConsoleCheck">
|
||||
<property name="text">
|
||||
<string>Automatically close console when the game quits?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacerMinecraft_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>88</width>
|
||||
<height>125</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Custom commands</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="customCommandsGroupBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Custom 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="0" column="1">
|
||||
<widget class="QLineEdit" name="preLaunchCmdTextBox"/>
|
||||
</item>
|
||||
<item row="1" 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="1" column="1">
|
||||
<widget class="QLineEdit" name="postExitCmdTextBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelCustomCmdsDescription">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Pre-launch command runs before the instance launches and post-exit command runs after it exits.</p><p>Both will be run in MultiMC's working directory with extra environment variables:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">INST_NAME - Name of the instance</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">INST_ID - ID of the instance</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">INST_DIR - absolute path of the instance</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">INST_MC_DIR - absolute path of minecraft</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">INST_JAVA - java binary used for launch</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">INST_JAVA_ARGS - command-line parameters used for launch</li></ul></body></html></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>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>settingsTabs</tabstop>
|
||||
<tabstop>javaSettingsGroupBox</tabstop>
|
||||
<tabstop>javaPathTextBox</tabstop>
|
||||
<tabstop>javaDetectBtn</tabstop>
|
||||
<tabstop>javaBrowseBtn</tabstop>
|
||||
<tabstop>javaTestBtn</tabstop>
|
||||
<tabstop>memoryGroupBox</tabstop>
|
||||
<tabstop>minMemSpinBox</tabstop>
|
||||
<tabstop>maxMemSpinBox</tabstop>
|
||||
<tabstop>permGenSpinBox</tabstop>
|
||||
<tabstop>javaArgumentsGroupBox</tabstop>
|
||||
<tabstop>jvmArgsTextBox</tabstop>
|
||||
<tabstop>windowSizeGroupBox</tabstop>
|
||||
<tabstop>maximizedCheckBox</tabstop>
|
||||
<tabstop>windowWidthSpinBox</tabstop>
|
||||
<tabstop>windowHeightSpinBox</tabstop>
|
||||
<tabstop>consoleSettingsBox</tabstop>
|
||||
<tabstop>showConsoleCheck</tabstop>
|
||||
<tabstop>autoCloseConsoleCheck</tabstop>
|
||||
<tabstop>customCommandsGroupBox</tabstop>
|
||||
<tabstop>preLaunchCmdTextBox</tabstop>
|
||||
<tabstop>postExitCmdTextBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
222
application/pages/LogPage.cpp
Normal file
222
application/pages/LogPage.cpp
Normal file
@ -0,0 +1,222 @@
|
||||
#include "LogPage.h"
|
||||
#include "ui_LogPage.h"
|
||||
|
||||
#include "MultiMC.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QScrollBar>
|
||||
#include <QShortcut>
|
||||
|
||||
#include "BaseProcess.h"
|
||||
#include "GuiUtil.h"
|
||||
|
||||
LogPage::LogPage(BaseProcess *proc, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::LogPage), m_process(proc)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
connect(m_process, SIGNAL(log(QString, MessageLevel::Enum)), this,
|
||||
SLOT(write(QString, MessageLevel::Enum)));
|
||||
|
||||
// create the format and set its font
|
||||
defaultFormat = new QTextCharFormat(ui->text->currentCharFormat());
|
||||
QString fontFamily = MMC->settings()->get("ConsoleFont").toString();
|
||||
bool conversionOk = false;
|
||||
int fontSize = MMC->settings()->get("ConsoleFontSize").toInt(&conversionOk);
|
||||
if(!conversionOk)
|
||||
{
|
||||
fontSize = 11;
|
||||
}
|
||||
defaultFormat->setFont(QFont(fontFamily, fontSize));
|
||||
|
||||
auto findShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this);
|
||||
connect(findShortcut, SIGNAL(activated()), SLOT(findActivated()));
|
||||
auto findNextShortcut = new QShortcut(QKeySequence(QKeySequence::FindNext), this);
|
||||
connect(findNextShortcut, SIGNAL(activated()), SLOT(findNextActivated()));
|
||||
connect(ui->searchBar, SIGNAL(returnPressed()), SLOT(on_findButton_clicked()));
|
||||
auto findPreviousShortcut = new QShortcut(QKeySequence(QKeySequence::FindPrevious), this);
|
||||
connect(findPreviousShortcut, SIGNAL(activated()), SLOT(findPreviousActivated()));
|
||||
}
|
||||
|
||||
LogPage::~LogPage()
|
||||
{
|
||||
delete ui;
|
||||
delete defaultFormat;
|
||||
}
|
||||
|
||||
bool LogPage::apply()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LogPage::shouldDisplay() const
|
||||
{
|
||||
return m_process->instance()->isRunning();
|
||||
}
|
||||
|
||||
void LogPage::on_btnPaste_clicked()
|
||||
{
|
||||
GuiUtil::uploadPaste(ui->text->toPlainText(), this);
|
||||
}
|
||||
|
||||
void LogPage::on_btnCopy_clicked()
|
||||
{
|
||||
GuiUtil::setClipboardText(ui->text->toPlainText());
|
||||
}
|
||||
|
||||
void LogPage::on_btnClear_clicked()
|
||||
{
|
||||
ui->text->clear();
|
||||
}
|
||||
|
||||
void LogPage::on_trackLogCheckbox_clicked(bool checked)
|
||||
{
|
||||
m_write_active = checked;
|
||||
}
|
||||
|
||||
void LogPage::on_findButton_clicked()
|
||||
{
|
||||
auto modifiers = QApplication::keyboardModifiers();
|
||||
if (modifiers & Qt::ShiftModifier)
|
||||
{
|
||||
findPreviousActivated();
|
||||
}
|
||||
else
|
||||
{
|
||||
findNextActivated();
|
||||
}
|
||||
}
|
||||
|
||||
void LogPage::findActivated()
|
||||
{
|
||||
// focus the search bar if it doesn't have focus
|
||||
if (!ui->searchBar->hasFocus())
|
||||
{
|
||||
auto searchForCursor = ui->text->textCursor();
|
||||
auto searchForString = searchForCursor.selectedText();
|
||||
if (searchForString.size())
|
||||
{
|
||||
ui->searchBar->setText(searchForString);
|
||||
}
|
||||
ui->searchBar->setFocus();
|
||||
ui->searchBar->selectAll();
|
||||
}
|
||||
}
|
||||
|
||||
void LogPage::findNextActivated()
|
||||
{
|
||||
auto toSearch = ui->searchBar->text();
|
||||
if (toSearch.size())
|
||||
{
|
||||
ui->text->find(toSearch);
|
||||
}
|
||||
}
|
||||
|
||||
void LogPage::findPreviousActivated()
|
||||
{
|
||||
auto toSearch = ui->searchBar->text();
|
||||
if (toSearch.size())
|
||||
{
|
||||
ui->text->find(toSearch, QTextDocument::FindBackward);
|
||||
}
|
||||
}
|
||||
|
||||
void LogPage::write(QString data, MessageLevel::Enum mode)
|
||||
{
|
||||
if (!m_write_active)
|
||||
{
|
||||
if (mode != MessageLevel::PrePost && mode != MessageLevel::MultiMC)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// save the cursor so it can be restored.
|
||||
auto savedCursor = ui->text->cursor();
|
||||
|
||||
QScrollBar *bar = ui->text->verticalScrollBar();
|
||||
int max_bar = bar->maximum();
|
||||
int val_bar = bar->value();
|
||||
if (isVisible())
|
||||
{
|
||||
if (m_scroll_active)
|
||||
{
|
||||
m_scroll_active = (max_bar - val_bar) <= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_scroll_active = val_bar == max_bar;
|
||||
}
|
||||
}
|
||||
if (data.endsWith('\n'))
|
||||
data = data.left(data.length() - 1);
|
||||
QStringList paragraphs = data.split('\n');
|
||||
QStringList filtered;
|
||||
for (QString ¶graph : paragraphs)
|
||||
{
|
||||
//TODO: implement filtering here.
|
||||
filtered.append(paragraph);
|
||||
}
|
||||
QListIterator<QString> iter(filtered);
|
||||
QTextCharFormat format(*defaultFormat);
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case MessageLevel::MultiMC:
|
||||
{
|
||||
format.setForeground(QColor("blue"));
|
||||
break;
|
||||
}
|
||||
case MessageLevel::Debug:
|
||||
{
|
||||
format.setForeground(QColor("green"));
|
||||
break;
|
||||
}
|
||||
case MessageLevel::Warning:
|
||||
{
|
||||
format.setForeground(QColor("orange"));
|
||||
break;
|
||||
}
|
||||
case MessageLevel::Error:
|
||||
{
|
||||
format.setForeground(QColor("red"));
|
||||
break;
|
||||
}
|
||||
case MessageLevel::Fatal:
|
||||
{
|
||||
format.setForeground(QColor("red"));
|
||||
format.setBackground(QColor("black"));
|
||||
break;
|
||||
}
|
||||
case MessageLevel::PrePost:
|
||||
{
|
||||
format.setForeground(QColor("grey"));
|
||||
break;
|
||||
}
|
||||
case MessageLevel::Info:
|
||||
case MessageLevel::Message:
|
||||
default:
|
||||
{
|
||||
// do nothing, keep original
|
||||
}
|
||||
}
|
||||
|
||||
while (iter.hasNext())
|
||||
{
|
||||
// append a paragraph/line
|
||||
auto workCursor = ui->text->textCursor();
|
||||
workCursor.movePosition(QTextCursor::End);
|
||||
workCursor.insertText(iter.next(), format);
|
||||
workCursor.insertBlock();
|
||||
}
|
||||
|
||||
if (isVisible())
|
||||
{
|
||||
if (m_scroll_active)
|
||||
{
|
||||
bar->setValue(bar->maximum());
|
||||
}
|
||||
m_last_scroll_value = bar->value();
|
||||
}
|
||||
ui->text->setCursor(savedCursor);
|
||||
}
|
86
application/pages/LogPage.h
Normal file
86
application/pages/LogPage.h
Normal file
@ -0,0 +1,86 @@
|
||||
/* Copyright 2013-2015 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 "BaseInstance.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "BaseProcess.h"
|
||||
#include "BasePage.h"
|
||||
#include <MultiMC.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class LogPage;
|
||||
}
|
||||
class QTextCharFormat;
|
||||
|
||||
class LogPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LogPage(BaseProcess *proc, QWidget *parent = 0);
|
||||
virtual ~LogPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Minecraft Log");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("log");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "console";
|
||||
}
|
||||
virtual bool apply();
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Minecraft-Logs";
|
||||
}
|
||||
virtual bool shouldDisplay() const;
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief write a string
|
||||
* @param data the string
|
||||
* @param mode the WriteMode
|
||||
* lines have to be put through this as a whole!
|
||||
*/
|
||||
void write(QString data, MessageLevel::Enum level = MessageLevel::MultiMC);
|
||||
void on_btnPaste_clicked();
|
||||
void on_btnCopy_clicked();
|
||||
void on_btnClear_clicked();
|
||||
|
||||
void on_trackLogCheckbox_clicked(bool checked);
|
||||
|
||||
void on_findButton_clicked();
|
||||
void findActivated();
|
||||
void findNextActivated();
|
||||
void findPreviousActivated();
|
||||
|
||||
private:
|
||||
Ui::LogPage *ui;
|
||||
BaseProcess *m_process;
|
||||
int m_last_scroll_value = 0;
|
||||
bool m_scroll_active = true;
|
||||
int m_saved_offset = 0;
|
||||
bool m_write_active = true;
|
||||
|
||||
QTextCharFormat * defaultFormat;
|
||||
};
|
140
application/pages/LogPage.ui
Normal file
140
application/pages/LogPage.ui
Normal file
@ -0,0 +1,140 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LogPage</class>
|
||||
<widget class="QWidget" name="LogPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>825</width>
|
||||
<height>782</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Log</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>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>Tab 1</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Search:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</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="3">
|
||||
<widget class="QPlainTextEdit" name="text">
|
||||
<property name="undoRedoEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="plainText">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
<property name="centerOnScroll">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="trackLogCheckbox">
|
||||
<property name="text">
|
||||
<string>Keep updating</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnCopy">
|
||||
<property name="toolTip">
|
||||
<string>Copy the whole log into the clipboard</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Copy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnPaste">
|
||||
<property name="toolTip">
|
||||
<string>Upload the log to paste.ee - it will stay online for a month</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Upload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnClear">
|
||||
<property name="toolTip">
|
||||
<string>Clear the log</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="searchBar"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
160
application/pages/ModFolderPage.cpp
Normal file
160
application/pages/ModFolderPage.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
/* Copyright 2013-2015 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 "ModFolderPage.h"
|
||||
#include "ui_ModFolderPage.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QDesktopServices>
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
#include <pathutils.h>
|
||||
|
||||
#include "MultiMC.h"
|
||||
#include "dialogs/CustomMessageBox.h"
|
||||
#include "dialogs/ModEditDialogCommon.h"
|
||||
#include "minecraft/ModList.h"
|
||||
#include "minecraft/Mod.h"
|
||||
#include "minecraft/VersionFilterData.h"
|
||||
|
||||
ModFolderPage::ModFolderPage(BaseInstance *inst, std::shared_ptr<ModList> mods, QString id,
|
||||
QString iconName, QString displayName, QString helpPage,
|
||||
QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::ModFolderPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
m_inst = inst;
|
||||
m_mods = mods;
|
||||
m_id = id;
|
||||
m_displayName = displayName;
|
||||
m_iconName = iconName;
|
||||
m_helpName = helpPage;
|
||||
ui->modTreeView->setModel(m_mods.get());
|
||||
ui->modTreeView->installEventFilter(this);
|
||||
m_mods->startWatching();
|
||||
auto smodel = ui->modTreeView->selectionModel();
|
||||
connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
|
||||
SLOT(modCurrent(QModelIndex, QModelIndex)));
|
||||
}
|
||||
|
||||
CoreModFolderPage::CoreModFolderPage(BaseInstance *inst, std::shared_ptr<ModList> mods,
|
||||
QString id, QString iconName, QString displayName,
|
||||
QString helpPage, QWidget *parent)
|
||||
: ModFolderPage(inst, mods, id, iconName, displayName, helpPage, parent)
|
||||
{
|
||||
}
|
||||
|
||||
ModFolderPage::~ModFolderPage()
|
||||
{
|
||||
m_mods->stopWatching();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool ModFolderPage::shouldDisplay() const
|
||||
{
|
||||
if (m_inst)
|
||||
return !m_inst->isRunning();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoreModFolderPage::shouldDisplay() const
|
||||
{
|
||||
if (ModFolderPage::shouldDisplay())
|
||||
{
|
||||
auto inst = dynamic_cast<OneSixInstance *>(m_inst);
|
||||
if (!inst)
|
||||
return true;
|
||||
auto version = inst->getMinecraftProfile();
|
||||
if (!version)
|
||||
return true;
|
||||
if (version->m_releaseTime < g_VersionFilterData.legacyCutoffDate)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ModFolderPage::modListFilter(QKeyEvent *keyEvent)
|
||||
{
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
on_rmModBtn_clicked();
|
||||
return true;
|
||||
case Qt::Key_Plus:
|
||||
on_addModBtn_clicked();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QWidget::eventFilter(ui->modTreeView, keyEvent);
|
||||
}
|
||||
|
||||
bool ModFolderPage::eventFilter(QObject *obj, QEvent *ev)
|
||||
{
|
||||
if (ev->type() != QEvent::KeyPress)
|
||||
{
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
}
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
|
||||
if (obj == ui->modTreeView)
|
||||
return modListFilter(keyEvent);
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
}
|
||||
|
||||
void ModFolderPage::on_addModBtn_clicked()
|
||||
{
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(
|
||||
this, QApplication::translate("ModFolderPage", "Select Loader Mods"));
|
||||
for (auto filename : fileNames)
|
||||
{
|
||||
m_mods->stopWatching();
|
||||
m_mods->installMod(QFileInfo(filename));
|
||||
m_mods->startWatching();
|
||||
}
|
||||
}
|
||||
void ModFolderPage::on_rmModBtn_clicked()
|
||||
{
|
||||
int first, last;
|
||||
auto list = ui->modTreeView->selectionModel()->selectedRows();
|
||||
|
||||
if (!lastfirst(list, first, last))
|
||||
return;
|
||||
m_mods->stopWatching();
|
||||
m_mods->deleteMods(first, last);
|
||||
m_mods->startWatching();
|
||||
}
|
||||
|
||||
void ModFolderPage::on_viewModBtn_clicked()
|
||||
{
|
||||
openDirInDefaultProgram(m_mods->dir().absolutePath(), true);
|
||||
}
|
||||
|
||||
void ModFolderPage::modCurrent(const QModelIndex ¤t, const QModelIndex &previous)
|
||||
{
|
||||
if (!current.isValid())
|
||||
{
|
||||
ui->frame->clear();
|
||||
return;
|
||||
}
|
||||
int row = current.row();
|
||||
Mod &m = m_mods->operator[](row);
|
||||
ui->frame->updateWithMod(m);
|
||||
}
|
94
application/pages/ModFolderPage.h
Normal file
94
application/pages/ModFolderPage.h
Normal file
@ -0,0 +1,94 @@
|
||||
/* Copyright 2013-2015 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 "minecraft/OneSixInstance.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "BasePage.h"
|
||||
#include <MultiMC.h>
|
||||
|
||||
class ModList;
|
||||
namespace Ui
|
||||
{
|
||||
class ModFolderPage;
|
||||
}
|
||||
|
||||
class ModFolderPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ModFolderPage(BaseInstance *inst, std::shared_ptr<ModList> mods, QString id,
|
||||
QString iconName, QString displayName, QString helpPage = "",
|
||||
QWidget *parent = 0);
|
||||
virtual ~ModFolderPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return m_displayName;
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon(m_iconName);
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return m_helpName;
|
||||
}
|
||||
virtual bool shouldDisplay() const;
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *ev);
|
||||
bool modListFilter(QKeyEvent *ev);
|
||||
|
||||
protected:
|
||||
BaseInstance *m_inst;
|
||||
|
||||
private:
|
||||
Ui::ModFolderPage *ui;
|
||||
std::shared_ptr<ModList> m_mods;
|
||||
QString m_iconName;
|
||||
QString m_id;
|
||||
QString m_displayName;
|
||||
QString m_helpName;
|
||||
|
||||
public
|
||||
slots:
|
||||
void modCurrent(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_addModBtn_clicked();
|
||||
void on_rmModBtn_clicked();
|
||||
void on_viewModBtn_clicked();
|
||||
};
|
||||
|
||||
class CoreModFolderPage : public ModFolderPage
|
||||
{
|
||||
public:
|
||||
explicit CoreModFolderPage(BaseInstance *inst, std::shared_ptr<ModList> mods, QString id,
|
||||
QString iconName, QString displayName, QString helpPage = "",
|
||||
QWidget *parent = 0);
|
||||
virtual ~CoreModFolderPage()
|
||||
{
|
||||
}
|
||||
virtual bool shouldDisplay() const;
|
||||
};
|
124
application/pages/ModFolderPage.ui
Normal file
124
application/pages/ModFolderPage.ui
Normal file
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ModFolderPage</class>
|
||||
<widget class="QWidget" name="ModFolderPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>723</width>
|
||||
<height>532</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Mods</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>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>Tab 1</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="ModListView" name="modTreeView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DropOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="addModBtn">
|
||||
<property name="text">
|
||||
<string>&Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="rmModBtn">
|
||||
<property name="text">
|
||||
<string>&Remove</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="viewModBtn">
|
||||
<property name="text">
|
||||
<string>&View Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="MCModInfoFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</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>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
21
application/pages/NotesPage.cpp
Normal file
21
application/pages/NotesPage.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "NotesPage.h"
|
||||
#include "ui_NotesPage.h"
|
||||
|
||||
NotesPage::NotesPage(BaseInstance *inst, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::NotesPage), m_inst(inst)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
ui->noteEditor->setText(m_inst->notes());
|
||||
}
|
||||
|
||||
NotesPage::~NotesPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool NotesPage::apply()
|
||||
{
|
||||
m_inst->setNotes(ui->noteEditor->toPlainText());
|
||||
return true;
|
||||
}
|
61
application/pages/NotesPage.h
Normal file
61
application/pages/NotesPage.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* Copyright 2013-2015 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 "BaseInstance.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "BasePage.h"
|
||||
#include <MultiMC.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class NotesPage;
|
||||
}
|
||||
|
||||
class NotesPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NotesPage(BaseInstance *inst, QWidget *parent = 0);
|
||||
virtual ~NotesPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Notes");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
auto icon = MMC->getThemedIcon("notes");
|
||||
if(icon.isNull())
|
||||
icon = MMC->getThemedIcon("news");
|
||||
return icon;
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "notes";
|
||||
}
|
||||
virtual bool apply();
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Notes";
|
||||
}
|
||||
|
||||
private:
|
||||
Ui::NotesPage *ui;
|
||||
BaseInstance *m_inst;
|
||||
};
|
60
application/pages/NotesPage.ui
Normal file
60
application/pages/NotesPage.ui
Normal file
@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NotesPage</class>
|
||||
<widget class="QWidget" name="NotesPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>731</width>
|
||||
<height>538</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</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>Tab 1</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="noteEditor">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="acceptRichText">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextEditable|Qt::TextEditorInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
150
application/pages/OtherLogsPage.cpp
Normal file
150
application/pages/OtherLogsPage.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
/* Copyright 2013-2015 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 "OtherLogsPage.h"
|
||||
#include "ui_OtherLogsPage.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "GuiUtil.h"
|
||||
#include "RecursiveFileSystemWatcher.h"
|
||||
#include <pathutils.h>
|
||||
|
||||
OtherLogsPage::OtherLogsPage(QString path, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::OtherLogsPage), m_path(path),
|
||||
m_watcher(new RecursiveFileSystemWatcher(this))
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
|
||||
m_watcher->setFileExpression("(.*\\.log(\\.[0-9]*)?$)|(crash-.*\\.txt)");
|
||||
m_watcher->setRootDir(QDir::current().absoluteFilePath(m_path));
|
||||
|
||||
connect(m_watcher, &RecursiveFileSystemWatcher::filesChanged, this,
|
||||
&OtherLogsPage::populateSelectLogBox);
|
||||
populateSelectLogBox();
|
||||
}
|
||||
|
||||
OtherLogsPage::~OtherLogsPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void OtherLogsPage::opened()
|
||||
{
|
||||
m_watcher->enable();
|
||||
}
|
||||
void OtherLogsPage::closed()
|
||||
{
|
||||
m_watcher->disable();
|
||||
}
|
||||
|
||||
void OtherLogsPage::populateSelectLogBox()
|
||||
{
|
||||
ui->selectLogBox->clear();
|
||||
ui->selectLogBox->addItems(m_watcher->files());
|
||||
if (m_currentFile.isNull())
|
||||
{
|
||||
ui->selectLogBox->setCurrentIndex(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int index = ui->selectLogBox->findText(m_currentFile);
|
||||
if (index != -1)
|
||||
ui->selectLogBox->setCurrentIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
void OtherLogsPage::on_selectLogBox_currentIndexChanged(const int index)
|
||||
{
|
||||
QString file;
|
||||
if (index != -1)
|
||||
{
|
||||
file = ui->selectLogBox->itemText(index);
|
||||
}
|
||||
|
||||
if (file.isEmpty() || !QFile::exists(PathCombine(m_path, file)))
|
||||
{
|
||||
m_currentFile = QString();
|
||||
ui->text->clear();
|
||||
setControlsEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_currentFile = file;
|
||||
on_btnReload_clicked();
|
||||
setControlsEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void OtherLogsPage::on_btnReload_clicked()
|
||||
{
|
||||
QFile file(PathCombine(m_path, m_currentFile));
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
{
|
||||
setControlsEnabled(false);
|
||||
ui->btnReload->setEnabled(true); // allow reload
|
||||
m_currentFile = QString();
|
||||
QMessageBox::critical(this, tr("Error"), tr("Unable to open %1 for reading: %2")
|
||||
.arg(m_currentFile, file.errorString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file.size() < 10000000ll)
|
||||
{
|
||||
ui->text->setPlainText(QString::fromUtf8(file.readAll()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->text->setPlainText(
|
||||
tr("The file (%1) is too big. You may want to open it in a viewer optimized "
|
||||
"for large files.").arg(file.fileName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OtherLogsPage::on_btnPaste_clicked()
|
||||
{
|
||||
GuiUtil::uploadPaste(ui->text->toPlainText(), this);
|
||||
}
|
||||
void OtherLogsPage::on_btnCopy_clicked()
|
||||
{
|
||||
GuiUtil::setClipboardText(ui->text->toPlainText());
|
||||
}
|
||||
void OtherLogsPage::on_btnDelete_clicked()
|
||||
{
|
||||
if (QMessageBox::question(this, tr("Delete"),
|
||||
tr("Do you really want to delete %1?").arg(m_currentFile),
|
||||
QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
|
||||
{
|
||||
return;
|
||||
}
|
||||
QFile file(PathCombine(m_path, m_currentFile));
|
||||
if (!file.remove())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Unable to delete %1: %2")
|
||||
.arg(m_currentFile, file.errorString()));
|
||||
}
|
||||
}
|
||||
|
||||
void OtherLogsPage::setControlsEnabled(const bool enabled)
|
||||
{
|
||||
ui->btnReload->setEnabled(enabled);
|
||||
ui->btnDelete->setEnabled(enabled);
|
||||
ui->btnCopy->setEnabled(enabled);
|
||||
ui->btnPaste->setEnabled(enabled);
|
||||
ui->text->setEnabled(enabled);
|
||||
}
|
72
application/pages/OtherLogsPage.h
Normal file
72
application/pages/OtherLogsPage.h
Normal file
@ -0,0 +1,72 @@
|
||||
/* Copyright 2013-2015 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 "BasePage.h"
|
||||
#include <MultiMC.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class OtherLogsPage;
|
||||
}
|
||||
|
||||
class RecursiveFileSystemWatcher;
|
||||
|
||||
class OtherLogsPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OtherLogsPage(QString path, QWidget *parent = 0);
|
||||
~OtherLogsPage();
|
||||
|
||||
QString id() const override
|
||||
{
|
||||
return "logs";
|
||||
}
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Other logs");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("log");
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Minecraft-Logs";
|
||||
}
|
||||
void opened() override;
|
||||
void closed() override;
|
||||
|
||||
private slots:
|
||||
void populateSelectLogBox();
|
||||
void on_selectLogBox_currentIndexChanged(const int index);
|
||||
void on_btnReload_clicked();
|
||||
void on_btnPaste_clicked();
|
||||
void on_btnCopy_clicked();
|
||||
void on_btnDelete_clicked();
|
||||
|
||||
private:
|
||||
Ui::OtherLogsPage *ui;
|
||||
QString m_path;
|
||||
RecursiveFileSystemWatcher *m_watcher;
|
||||
QString m_currentFile;
|
||||
|
||||
void setControlsEnabled(const bool enabled);
|
||||
};
|
117
application/pages/OtherLogsPage.ui
Normal file
117
application/pages/OtherLogsPage.ui
Normal file
@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>OtherLogsPage</class>
|
||||
<widget class="QWidget" name="OtherLogsPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>657</width>
|
||||
<height>538</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</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>Tab 1</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="selectLogBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnReload">
|
||||
<property name="text">
|
||||
<string>Reload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnCopy">
|
||||
<property name="toolTip">
|
||||
<string>Copy the whole log into the clipboard</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Copy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnPaste">
|
||||
<property name="toolTip">
|
||||
<string>Upload the log to paste.ee - it will stay online for a month</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Upload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnDelete">
|
||||
<property name="toolTip">
|
||||
<string>Clear the log</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Delete</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>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>text</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
19
application/pages/ResourcePackPage.h
Normal file
19
application/pages/ResourcePackPage.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "ModFolderPage.h"
|
||||
|
||||
class ResourcePackPage : public ModFolderPage
|
||||
{
|
||||
public:
|
||||
explicit ResourcePackPage(MinecraftInstance *instance, QWidget *parent = 0)
|
||||
: ModFolderPage(instance, instance->resourcePackList(), "resourcepacks",
|
||||
"resourcepacks", tr("Resource packs"), "Resource-packs", parent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ResourcePackPage() {}
|
||||
virtual bool shouldDisplay() const override
|
||||
{
|
||||
return !m_inst->traits().contains("no-texturepacks") &&
|
||||
!m_inst->traits().contains("texturepacks");
|
||||
}
|
||||
};
|
362
application/pages/ScreenshotsPage.cpp
Normal file
362
application/pages/ScreenshotsPage.cpp
Normal file
@ -0,0 +1,362 @@
|
||||
#include "ScreenshotsPage.h"
|
||||
#include "ui_ScreenshotsPage.h"
|
||||
|
||||
#include <QModelIndex>
|
||||
#include <QMutableListIterator>
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QFileIconProvider>
|
||||
#include <QFileSystemModel>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QLineEdit>
|
||||
#include <QEvent>
|
||||
#include <QPainter>
|
||||
#include <QClipboard>
|
||||
#include <QDesktopServices>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include <pathutils.h>
|
||||
#include <MultiMC.h>
|
||||
|
||||
#include "dialogs/ProgressDialog.h"
|
||||
#include "dialogs/CustomMessageBox.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "screenshots/ImgurUpload.h"
|
||||
#include "screenshots/ImgurAlbumCreation.h"
|
||||
#include "tasks/SequentialTask.h"
|
||||
|
||||
#include "RWStorage.h"
|
||||
|
||||
typedef RWStorage<QString, QIcon> SharedIconCache;
|
||||
typedef std::shared_ptr<SharedIconCache> SharedIconCachePtr;
|
||||
|
||||
class ThumbnailingResult : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public slots:
|
||||
inline void emitResultsReady(const QString &path) { emit resultsReady(path); }
|
||||
inline void emitResultsFailed(const QString &path) { emit resultsFailed(path); }
|
||||
signals:
|
||||
void resultsReady(const QString &path);
|
||||
void resultsFailed(const QString &path);
|
||||
};
|
||||
|
||||
class ThumbnailRunnable : public QRunnable
|
||||
{
|
||||
public:
|
||||
ThumbnailRunnable(QString path, SharedIconCachePtr cache)
|
||||
{
|
||||
m_path = path;
|
||||
m_cache = cache;
|
||||
}
|
||||
void run()
|
||||
{
|
||||
QFileInfo info(m_path);
|
||||
if (info.isDir())
|
||||
return;
|
||||
if ((info.suffix().compare("png", Qt::CaseInsensitive) != 0))
|
||||
return;
|
||||
int tries = 5;
|
||||
while (tries)
|
||||
{
|
||||
if (!m_cache->stale(m_path))
|
||||
return;
|
||||
QImage image(m_path);
|
||||
if (image.isNull())
|
||||
{
|
||||
QThread::msleep(500);
|
||||
tries--;
|
||||
continue;
|
||||
}
|
||||
QImage small;
|
||||
if (image.width() > image.height())
|
||||
small = image.scaledToWidth(512).scaledToWidth(256, Qt::SmoothTransformation);
|
||||
else
|
||||
small = image.scaledToHeight(512).scaledToHeight(256, Qt::SmoothTransformation);
|
||||
auto smallSize = small.size();
|
||||
QPoint offset((256 - small.width()) / 2, (256 - small.height()) / 2);
|
||||
QImage square(QSize(256, 256), QImage::Format_ARGB32);
|
||||
square.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&square);
|
||||
painter.drawImage(offset, small);
|
||||
painter.end();
|
||||
|
||||
QIcon icon(QPixmap::fromImage(square));
|
||||
m_cache->add(m_path, icon);
|
||||
m_resultEmitter.emitResultsReady(m_path);
|
||||
return;
|
||||
}
|
||||
m_resultEmitter.emitResultsFailed(m_path);
|
||||
}
|
||||
QString m_path;
|
||||
SharedIconCachePtr m_cache;
|
||||
ThumbnailingResult m_resultEmitter;
|
||||
};
|
||||
|
||||
// this is about as elegant and well written as a bag of bricks with scribbles done by insane
|
||||
// asylum patients.
|
||||
class FilterModel : public QIdentityProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FilterModel(QObject *parent = 0) : QIdentityProxyModel(parent)
|
||||
{
|
||||
m_thumbnailingPool.setMaxThreadCount(4);
|
||||
m_thumbnailCache = std::make_shared<SharedIconCache>();
|
||||
m_thumbnailCache->add("placeholder", MMC->getThemedIcon("screenshot-placeholder"));
|
||||
connect(&watcher, SIGNAL(fileChanged(QString)), SLOT(fileChanged(QString)));
|
||||
// FIXME: the watched file set is not updated when files are removed
|
||||
}
|
||||
virtual ~FilterModel() { m_thumbnailingPool.waitForDone(500); }
|
||||
virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const
|
||||
{
|
||||
auto model = sourceModel();
|
||||
if (!model)
|
||||
return QVariant();
|
||||
if (role == Qt::DisplayRole || role == Qt::EditRole)
|
||||
{
|
||||
QVariant result = sourceModel()->data(mapToSource(proxyIndex), role);
|
||||
return result.toString().remove(QRegExp("\\.png$"));
|
||||
}
|
||||
if (role == Qt::DecorationRole)
|
||||
{
|
||||
QVariant result =
|
||||
sourceModel()->data(mapToSource(proxyIndex), QFileSystemModel::FilePathRole);
|
||||
QString filePath = result.toString();
|
||||
QIcon temp;
|
||||
if (!watched.contains(filePath))
|
||||
{
|
||||
((QFileSystemWatcher &)watcher).addPath(filePath);
|
||||
((QSet<QString> &)watched).insert(filePath);
|
||||
}
|
||||
if (m_thumbnailCache->get(filePath, temp))
|
||||
{
|
||||
return temp;
|
||||
}
|
||||
if (!m_failed.contains(filePath))
|
||||
{
|
||||
((FilterModel *)this)->thumbnailImage(filePath);
|
||||
}
|
||||
return (m_thumbnailCache->get("placeholder"));
|
||||
}
|
||||
return sourceModel()->data(mapToSource(proxyIndex), role);
|
||||
}
|
||||
virtual bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole)
|
||||
{
|
||||
auto model = sourceModel();
|
||||
if (!model)
|
||||
return false;
|
||||
if (role != Qt::EditRole)
|
||||
return false;
|
||||
// FIXME: this is a workaround for a bug in QFileSystemModel, where it doesn't
|
||||
// sort after renames
|
||||
{
|
||||
((QFileSystemModel *)model)->setNameFilterDisables(true);
|
||||
((QFileSystemModel *)model)->setNameFilterDisables(false);
|
||||
}
|
||||
return model->setData(mapToSource(index), value.toString() + ".png", role);
|
||||
}
|
||||
|
||||
private:
|
||||
void thumbnailImage(QString path)
|
||||
{
|
||||
auto runnable = new ThumbnailRunnable(path, m_thumbnailCache);
|
||||
connect(&(runnable->m_resultEmitter), SIGNAL(resultsReady(QString)),
|
||||
SLOT(thumbnailReady(QString)));
|
||||
connect(&(runnable->m_resultEmitter), SIGNAL(resultsFailed(QString)),
|
||||
SLOT(thumbnailFailed(QString)));
|
||||
((QThreadPool &)m_thumbnailingPool).start(runnable);
|
||||
}
|
||||
private slots:
|
||||
void thumbnailReady(QString path) { emit layoutChanged(); }
|
||||
void thumbnailFailed(QString path) { m_failed.insert(path); }
|
||||
void fileChanged(QString filepath)
|
||||
{
|
||||
m_thumbnailCache->setStale(filepath);
|
||||
thumbnailImage(filepath);
|
||||
// reinsert the path...
|
||||
watcher.removePath(filepath);
|
||||
watcher.addPath(filepath);
|
||||
}
|
||||
|
||||
private:
|
||||
SharedIconCachePtr m_thumbnailCache;
|
||||
QThreadPool m_thumbnailingPool;
|
||||
QSet<QString> m_failed;
|
||||
QSet<QString> watched;
|
||||
QFileSystemWatcher watcher;
|
||||
};
|
||||
|
||||
class CenteredEditingDelegate : public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
explicit CenteredEditingDelegate(QObject *parent = 0) : QStyledItemDelegate(parent) {}
|
||||
virtual ~CenteredEditingDelegate() {}
|
||||
virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
auto widget = QStyledItemDelegate::createEditor(parent, option, index);
|
||||
auto foo = dynamic_cast<QLineEdit *>(widget);
|
||||
if (foo)
|
||||
{
|
||||
foo->setAlignment(Qt::AlignHCenter);
|
||||
foo->setFrame(true);
|
||||
foo->setMaximumWidth(192);
|
||||
}
|
||||
return widget;
|
||||
}
|
||||
};
|
||||
|
||||
ScreenshotsPage::ScreenshotsPage(QString path, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::ScreenshotsPage)
|
||||
{
|
||||
m_model.reset(new QFileSystemModel());
|
||||
m_filterModel.reset(new FilterModel());
|
||||
m_filterModel->setSourceModel(m_model.get());
|
||||
m_model->setFilter(QDir::Files | QDir::Writable | QDir::Readable);
|
||||
m_model->setReadOnly(false);
|
||||
m_model->setNameFilters({"*.png"});
|
||||
m_model->setNameFilterDisables(false);
|
||||
m_folder = path;
|
||||
m_valid = ensureFolderPathExists(m_folder);
|
||||
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
ui->listView->setModel(m_filterModel.get());
|
||||
ui->listView->setIconSize(QSize(128, 128));
|
||||
ui->listView->setGridSize(QSize(192, 160));
|
||||
ui->listView->setSpacing(9);
|
||||
// ui->listView->setUniformItemSizes(true);
|
||||
ui->listView->setLayoutMode(QListView::Batched);
|
||||
ui->listView->setViewMode(QListView::IconMode);
|
||||
ui->listView->setResizeMode(QListView::Adjust);
|
||||
ui->listView->installEventFilter(this);
|
||||
ui->listView->setEditTriggers(0);
|
||||
ui->listView->setItemDelegate(new CenteredEditingDelegate(this));
|
||||
connect(ui->listView, SIGNAL(activated(QModelIndex)), SLOT(onItemActivated(QModelIndex)));
|
||||
}
|
||||
|
||||
bool ScreenshotsPage::eventFilter(QObject *obj, QEvent *evt)
|
||||
{
|
||||
if (obj != ui->listView)
|
||||
return QWidget::eventFilter(obj, evt);
|
||||
if (evt->type() != QEvent::KeyPress)
|
||||
{
|
||||
return QWidget::eventFilter(obj, evt);
|
||||
}
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(evt);
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
on_deleteBtn_clicked();
|
||||
return true;
|
||||
case Qt::Key_F2:
|
||||
on_renameBtn_clicked();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QWidget::eventFilter(obj, evt);
|
||||
}
|
||||
|
||||
ScreenshotsPage::~ScreenshotsPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ScreenshotsPage::onItemActivated(QModelIndex index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return;
|
||||
auto info = m_model->fileInfo(index);
|
||||
QString fileName = info.absoluteFilePath();
|
||||
openFileInDefaultProgram(info.absoluteFilePath());
|
||||
}
|
||||
|
||||
void ScreenshotsPage::on_viewFolderBtn_clicked()
|
||||
{
|
||||
openDirInDefaultProgram(m_folder, true);
|
||||
}
|
||||
|
||||
void ScreenshotsPage::on_uploadBtn_clicked()
|
||||
{
|
||||
auto selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
if (selection.isEmpty())
|
||||
return;
|
||||
|
||||
QList<ScreenshotPtr> uploaded;
|
||||
auto job = std::make_shared<NetJob>("Screenshot Upload");
|
||||
for (auto item : selection)
|
||||
{
|
||||
auto info = m_model->fileInfo(item);
|
||||
auto screenshot = std::make_shared<ScreenShot>(info);
|
||||
uploaded.push_back(screenshot);
|
||||
job->addNetAction(ImgurUpload::make(screenshot));
|
||||
}
|
||||
SequentialTask task;
|
||||
auto albumTask = std::make_shared<NetJob>("Imgur Album Creation");
|
||||
auto imgurAlbum = ImgurAlbumCreation::make(uploaded);
|
||||
albumTask->addNetAction(imgurAlbum);
|
||||
task.addTask(job);
|
||||
task.addTask(albumTask);
|
||||
ProgressDialog prog(this);
|
||||
if (prog.exec(&task) != QDialog::Accepted)
|
||||
{
|
||||
CustomMessageBox::selectable(this, tr("Failed to upload screenshots!"),
|
||||
tr("Unknown error"), QMessageBox::Warning)->exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto link = QString("https://imgur.com/a/%1").arg(imgurAlbum->id());
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
clipboard->setText(link);
|
||||
QDesktopServices::openUrl(link);
|
||||
CustomMessageBox::selectable(
|
||||
this, tr("Upload finished"),
|
||||
tr("The <a href=\"%1\">link to the uploaded album</a> has been opened in the "
|
||||
"default browser and placed in your clipboard.<br/>Delete hash: %2 (save "
|
||||
"this if you want to be able to edit/delete the album)")
|
||||
.arg(link, imgurAlbum->deleteHash()),
|
||||
QMessageBox::Information)->exec();
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenshotsPage::on_deleteBtn_clicked()
|
||||
{
|
||||
auto mbox = CustomMessageBox::selectable(
|
||||
this, tr("Are you sure?"), tr("This will delete all selected screenshots."),
|
||||
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No);
|
||||
std::unique_ptr<QMessageBox> box(mbox);
|
||||
|
||||
if (box->exec() != QMessageBox::Yes)
|
||||
return;
|
||||
|
||||
auto selected = ui->listView->selectionModel()->selectedIndexes();
|
||||
for (auto item : selected)
|
||||
{
|
||||
m_model->remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenshotsPage::on_renameBtn_clicked()
|
||||
{
|
||||
auto selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
if (selection.isEmpty())
|
||||
return;
|
||||
ui->listView->edit(selection[0]);
|
||||
// TODO: mass renaming
|
||||
}
|
||||
|
||||
void ScreenshotsPage::opened()
|
||||
{
|
||||
if (m_valid)
|
||||
{
|
||||
QString path = QDir(m_folder).absolutePath();
|
||||
m_model->setRootPath(path);
|
||||
ui->listView->setRootIndex(m_filterModel->mapFromSource(m_model->index(path)));
|
||||
}
|
||||
}
|
||||
|
||||
#include "ScreenshotsPage.moc"
|
79
application/pages/ScreenshotsPage.h
Normal file
79
application/pages/ScreenshotsPage.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* Copyright 2013-2015 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 "BasePage.h"
|
||||
#include <MultiMC.h>
|
||||
|
||||
class QFileSystemModel;
|
||||
class QIdentityProxyModel;
|
||||
namespace Ui
|
||||
{
|
||||
class ScreenshotsPage;
|
||||
}
|
||||
|
||||
struct ScreenShot;
|
||||
class ScreenshotList;
|
||||
class ImgurAlbumCreation;
|
||||
|
||||
class ScreenshotsPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ScreenshotsPage(QString path, QWidget *parent = 0);
|
||||
virtual ~ScreenshotsPage();
|
||||
|
||||
virtual void opened() override;
|
||||
|
||||
enum
|
||||
{
|
||||
NothingDone = 0x42
|
||||
};
|
||||
|
||||
virtual bool eventFilter(QObject *, QEvent *);
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Screenshots");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("screenshots");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "screenshots";
|
||||
}
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Screenshots-management";
|
||||
}
|
||||
private slots:
|
||||
void on_uploadBtn_clicked();
|
||||
void on_deleteBtn_clicked();
|
||||
void on_renameBtn_clicked();
|
||||
void on_viewFolderBtn_clicked();
|
||||
void onItemActivated(QModelIndex);
|
||||
|
||||
private:
|
||||
Ui::ScreenshotsPage *ui;
|
||||
std::shared_ptr<QFileSystemModel> m_model;
|
||||
std::shared_ptr<QIdentityProxyModel> m_filterModel;
|
||||
QString m_folder;
|
||||
bool m_valid = false;
|
||||
};
|
109
application/pages/ScreenshotsPage.ui
Normal file
109
application/pages/ScreenshotsPage.ui
Normal file
@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ScreenshotsPage</class>
|
||||
<widget class="QWidget" name="ScreenshotsPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>723</width>
|
||||
<height>532</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Mods</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>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>Tab 1</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QListView" name="listView">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectItems</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="uploadBtn">
|
||||
<property name="text">
|
||||
<string>&Upload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteBtn">
|
||||
<property name="text">
|
||||
<string>&Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="renameBtn">
|
||||
<property name="text">
|
||||
<string>&Rename</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="viewFolderBtn">
|
||||
<property name="text">
|
||||
<string>&View Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>listView</tabstop>
|
||||
<tabstop>uploadBtn</tabstop>
|
||||
<tabstop>deleteBtn</tabstop>
|
||||
<tabstop>renameBtn</tabstop>
|
||||
<tabstop>viewFolderBtn</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
17
application/pages/TexturePackPage.h
Normal file
17
application/pages/TexturePackPage.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "ModFolderPage.h"
|
||||
|
||||
class TexturePackPage : public ModFolderPage
|
||||
{
|
||||
public:
|
||||
explicit TexturePackPage(MinecraftInstance *instance, QWidget *parent = 0)
|
||||
: ModFolderPage(instance, instance->texturePackList(), "texturepacks", "resourcepacks",
|
||||
tr("Texture packs"), "Texture-packs", parent)
|
||||
{
|
||||
}
|
||||
virtual ~TexturePackPage() {}
|
||||
virtual bool shouldDisplay() const override
|
||||
{
|
||||
return m_inst->traits().contains("texturepacks");
|
||||
}
|
||||
};
|
321
application/pages/VersionPage.cpp
Normal file
321
application/pages/VersionPage.cpp
Normal file
@ -0,0 +1,321 @@
|
||||
/* Copyright 2013-2015 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 <pathutils.h>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "VersionPage.h"
|
||||
#include "ui_VersionPage.h"
|
||||
|
||||
#include "Platform.h"
|
||||
#include "dialogs/CustomMessageBox.h"
|
||||
#include "dialogs/VersionSelectDialog.h"
|
||||
#include "dialogs/ModEditDialogCommon.h"
|
||||
|
||||
#include "dialogs/ProgressDialog.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QMessageBox>
|
||||
#include <QListView>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
#include "minecraft/MinecraftProfile.h"
|
||||
#include "forge/ForgeVersionList.h"
|
||||
#include "forge/ForgeInstaller.h"
|
||||
#include "liteloader/LiteLoaderVersionList.h"
|
||||
#include "liteloader/LiteLoaderInstaller.h"
|
||||
#include "minecraft/VersionBuilder.h"
|
||||
#include "auth/MojangAccountList.h"
|
||||
#include "minecraft/Mod.h"
|
||||
#include "icons/IconList.h"
|
||||
|
||||
|
||||
QIcon VersionPage::icon() const
|
||||
{
|
||||
return ENV.icons()->getIcon(m_inst->iconKey());
|
||||
}
|
||||
bool VersionPage::shouldDisplay() const
|
||||
{
|
||||
return !m_inst->isRunning();
|
||||
}
|
||||
|
||||
VersionPage::VersionPage(OneSixInstance *inst, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::VersionPage), m_inst(inst)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
|
||||
m_version = m_inst->getMinecraftProfile();
|
||||
if (m_version)
|
||||
{
|
||||
ui->libraryTreeView->setModel(m_version.get());
|
||||
ui->libraryTreeView->installEventFilter(this);
|
||||
ui->libraryTreeView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
connect(ui->libraryTreeView->selectionModel(), &QItemSelectionModel::currentChanged,
|
||||
this, &VersionPage::versionCurrent);
|
||||
updateVersionControls();
|
||||
// select first item.
|
||||
auto index = ui->libraryTreeView->model()->index(0,0);
|
||||
if(index.isValid())
|
||||
ui->libraryTreeView->setCurrentIndex(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
disableVersionControls();
|
||||
}
|
||||
connect(m_inst, &OneSixInstance::versionReloaded, this,
|
||||
&VersionPage::updateVersionControls);
|
||||
}
|
||||
|
||||
VersionPage::~VersionPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void VersionPage::updateVersionControls()
|
||||
{
|
||||
ui->forgeBtn->setEnabled(true);
|
||||
ui->liteloaderBtn->setEnabled(true);
|
||||
}
|
||||
|
||||
void VersionPage::disableVersionControls()
|
||||
{
|
||||
ui->forgeBtn->setEnabled(false);
|
||||
ui->liteloaderBtn->setEnabled(false);
|
||||
ui->reloadLibrariesBtn->setEnabled(false);
|
||||
ui->removeLibraryBtn->setEnabled(false);
|
||||
}
|
||||
|
||||
bool VersionPage::reloadMinecraftProfile()
|
||||
{
|
||||
try
|
||||
{
|
||||
m_inst->reloadProfile();
|
||||
return true;
|
||||
}
|
||||
catch (MMCError &e)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), e.cause());
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
QMessageBox::critical(
|
||||
this, tr("Error"),
|
||||
tr("Failed to load the version description file for reasons unknown."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void VersionPage::on_reloadLibrariesBtn_clicked()
|
||||
{
|
||||
reloadMinecraftProfile();
|
||||
}
|
||||
|
||||
void VersionPage::on_removeLibraryBtn_clicked()
|
||||
{
|
||||
if (ui->libraryTreeView->currentIndex().isValid())
|
||||
{
|
||||
// FIXME: use actual model, not reloading.
|
||||
if (!m_version->remove(ui->libraryTreeView->currentIndex().row()))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Couldn't remove file"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VersionPage::on_jarmodBtn_clicked()
|
||||
{
|
||||
QFileDialog w;
|
||||
QSet<QString> locations;
|
||||
QString modsFolder = MMC->settings()->get("CentralModsDir").toString();
|
||||
auto f = [&](QStandardPaths::StandardLocation l)
|
||||
{
|
||||
QString location = QStandardPaths::writableLocation(l);
|
||||
QFileInfo finfo(location);
|
||||
if (!finfo.exists())
|
||||
return;
|
||||
locations.insert(location);
|
||||
};
|
||||
f(QStandardPaths::DesktopLocation);
|
||||
f(QStandardPaths::DocumentsLocation);
|
||||
f(QStandardPaths::DownloadLocation);
|
||||
f(QStandardPaths::HomeLocation);
|
||||
QList<QUrl> urls;
|
||||
for (auto location : locations)
|
||||
{
|
||||
urls.append(QUrl::fromLocalFile(location));
|
||||
}
|
||||
urls.append(QUrl::fromLocalFile(modsFolder));
|
||||
|
||||
w.setFileMode(QFileDialog::ExistingFiles);
|
||||
w.setAcceptMode(QFileDialog::AcceptOpen);
|
||||
w.setNameFilter(tr("Minecraft jar mods (*.zip *.jar)"));
|
||||
w.setDirectory(modsFolder);
|
||||
w.setSidebarUrls(urls);
|
||||
|
||||
if (w.exec())
|
||||
m_version->installJarMods(w.selectedFiles());
|
||||
}
|
||||
|
||||
void VersionPage::on_resetLibraryOrderBtn_clicked()
|
||||
{
|
||||
try
|
||||
{
|
||||
m_version->resetOrder();
|
||||
}
|
||||
catch (MMCError &e)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), e.cause());
|
||||
}
|
||||
}
|
||||
|
||||
void VersionPage::on_moveLibraryUpBtn_clicked()
|
||||
{
|
||||
if (ui->libraryTreeView->selectionModel()->selectedRows().isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row();
|
||||
m_version->move(row, MinecraftProfile::MoveUp);
|
||||
}
|
||||
catch (MMCError &e)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), e.cause());
|
||||
}
|
||||
}
|
||||
|
||||
void VersionPage::on_moveLibraryDownBtn_clicked()
|
||||
{
|
||||
if (ui->libraryTreeView->selectionModel()->selectedRows().isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row();
|
||||
m_version->move(row, MinecraftProfile::MoveDown);
|
||||
}
|
||||
catch (MMCError &e)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), e.cause());
|
||||
}
|
||||
}
|
||||
|
||||
void VersionPage::on_changeMCVersionBtn_clicked()
|
||||
{
|
||||
VersionSelectDialog vselect(m_inst->versionList().get(), tr("Change Minecraft version"),
|
||||
this);
|
||||
if (!vselect.exec() || !vselect.selectedVersion())
|
||||
return;
|
||||
|
||||
if (!MMC->accounts()->anyAccountIsValid())
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
this, tr("Error"),
|
||||
tr("MultiMC cannot download Minecraft or update instances unless you have at least "
|
||||
"one account added.\nPlease add your Mojang or Minecraft account."),
|
||||
QMessageBox::Warning)->show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_version->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_version->revertToVanilla();
|
||||
reloadMinecraftProfile();
|
||||
}
|
||||
m_inst->setIntendedVersionId(vselect.selectedVersion()->descriptor());
|
||||
|
||||
auto updateTask = m_inst->doUpdate();
|
||||
if (!updateTask)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ProgressDialog tDialog(this);
|
||||
connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString)));
|
||||
tDialog.exec(updateTask.get());
|
||||
}
|
||||
|
||||
void VersionPage::on_forgeBtn_clicked()
|
||||
{
|
||||
VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this);
|
||||
vselect.setExactFilter(1, m_inst->currentVersionId());
|
||||
vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") +
|
||||
m_inst->currentVersionId());
|
||||
if (vselect.exec() && vselect.selectedVersion())
|
||||
{
|
||||
ProgressDialog dialog(this);
|
||||
dialog.exec(
|
||||
ForgeInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this));
|
||||
}
|
||||
}
|
||||
|
||||
void VersionPage::on_liteloaderBtn_clicked()
|
||||
{
|
||||
VersionSelectDialog vselect(MMC->liteloaderlist().get(), tr("Select LiteLoader version"),
|
||||
this);
|
||||
vselect.setExactFilter(1, m_inst->currentVersionId());
|
||||
vselect.setEmptyString(tr("No LiteLoader versions are currently available for Minecraft ") +
|
||||
m_inst->currentVersionId());
|
||||
if (vselect.exec() && vselect.selectedVersion())
|
||||
{
|
||||
ProgressDialog dialog(this);
|
||||
dialog.exec(
|
||||
LiteLoaderInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this));
|
||||
}
|
||||
}
|
||||
|
||||
void VersionPage::versionCurrent(const QModelIndex ¤t, const QModelIndex &previous)
|
||||
{
|
||||
if (!current.isValid())
|
||||
{
|
||||
ui->removeLibraryBtn->setDisabled(true);
|
||||
ui->moveLibraryDownBtn->setDisabled(true);
|
||||
ui->moveLibraryUpBtn->setDisabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool enabled = m_version->canRemove(current.row());
|
||||
ui->removeLibraryBtn->setEnabled(enabled);
|
||||
ui->moveLibraryDownBtn->setEnabled(enabled);
|
||||
ui->moveLibraryUpBtn->setEnabled(enabled);
|
||||
}
|
||||
QString selectedId = m_version->versionFileId(current.row());
|
||||
if (selectedId == "net.minecraft")
|
||||
{
|
||||
ui->changeMCVersionBtn->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->changeMCVersionBtn->setEnabled(false);
|
||||
}
|
||||
}
|
80
application/pages/VersionPage.h
Normal file
80
application/pages/VersionPage.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* Copyright 2013-2015 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 "minecraft/OneSixInstance.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "BasePage.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class VersionPage;
|
||||
}
|
||||
|
||||
class VersionPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VersionPage(OneSixInstance *inst, QWidget *parent = 0);
|
||||
virtual ~VersionPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Version");
|
||||
}
|
||||
virtual QIcon icon() const override;
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "version";
|
||||
}
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Instance-version";
|
||||
}
|
||||
virtual bool shouldDisplay() const;
|
||||
private
|
||||
slots:
|
||||
|
||||
// version tab
|
||||
void on_forgeBtn_clicked();
|
||||
void on_liteloaderBtn_clicked();
|
||||
void on_reloadLibrariesBtn_clicked();
|
||||
void on_removeLibraryBtn_clicked();
|
||||
void on_resetLibraryOrderBtn_clicked();
|
||||
void on_moveLibraryUpBtn_clicked();
|
||||
void on_moveLibraryDownBtn_clicked();
|
||||
void on_jarmodBtn_clicked();
|
||||
|
||||
void updateVersionControls();
|
||||
void disableVersionControls();
|
||||
void on_changeMCVersionBtn_clicked();
|
||||
|
||||
protected:
|
||||
/// FIXME: this shouldn't be necessary!
|
||||
bool reloadMinecraftProfile();
|
||||
|
||||
private:
|
||||
Ui::VersionPage *ui;
|
||||
std::shared_ptr<MinecraftProfile> m_version;
|
||||
OneSixInstance *m_inst;
|
||||
NetJobPtr forgeJob;
|
||||
|
||||
public
|
||||
slots:
|
||||
void versionCurrent(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
};
|
204
application/pages/VersionPage.ui
Normal file
204
application/pages/VersionPage.ui
Normal file
@ -0,0 +1,204 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>VersionPage</class>
|
||||
<widget class="QWidget" name="VersionPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>693</width>
|
||||
<height>575</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Version</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>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>Tab 1</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="ModListView" name="libraryTreeView">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<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="changeMCVersionBtn">
|
||||
<property name="text">
|
||||
<string>Change version</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="moveLibraryUpBtn">
|
||||
<property name="toolTip">
|
||||
<string>This isn't implemented yet.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Move up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="moveLibraryDownBtn">
|
||||
<property name="toolTip">
|
||||
<string>This isn't implemented yet.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Move down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removeLibraryBtn">
|
||||
<property name="text">
|
||||
<string>Remove</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="forgeBtn">
|
||||
<property name="toolTip">
|
||||
<string>Replace any current custom version with Minecraft Forge</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Install Forge</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="liteloaderBtn">
|
||||
<property name="text">
|
||||
<string>Install LiteLoader</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="jarmodBtn">
|
||||
<property name="text">
|
||||
<string>Add jar mod</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LineSeparator" name="widget" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>List</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="resetLibraryOrderBtn">
|
||||
<property name="toolTip">
|
||||
<string>This isn't implemented yet.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reset order</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="reloadLibrariesBtn">
|
||||
<property name="text">
|
||||
<string>Reload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_7">
|
||||
<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>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ModListView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>widgets/ModListView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LineSeparator</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/LineSeparator.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
142
application/pages/global/AccountListPage.cpp
Normal file
142
application/pages/global/AccountListPage.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
/* Copyright 2013-2015 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 "AccountListPage.h"
|
||||
#include "ui_AccountListPage.h"
|
||||
|
||||
#include <QItemSelectionModel>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "net/NetJob.h"
|
||||
#include "net/URLConstants.h"
|
||||
#include "Env.h"
|
||||
|
||||
#include "dialogs/EditAccountDialog.h"
|
||||
#include "dialogs/ProgressDialog.h"
|
||||
#include "dialogs/AccountSelectDialog.h"
|
||||
#include "dialogs/LoginDialog.h"
|
||||
#include "dialogs/CustomMessageBox.h"
|
||||
#include "tasks/Task.h"
|
||||
#include "auth/YggdrasilTask.h"
|
||||
|
||||
#include "MultiMC.h"
|
||||
|
||||
AccountListPage::AccountListPage(QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::AccountListPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
|
||||
m_accounts = MMC->accounts();
|
||||
|
||||
ui->listView->setModel(m_accounts.get());
|
||||
ui->listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
|
||||
// Expand the account column
|
||||
ui->listView->header()->setSectionResizeMode(1, QHeaderView::Stretch);
|
||||
|
||||
QItemSelectionModel *selectionModel = ui->listView->selectionModel();
|
||||
|
||||
connect(selectionModel, &QItemSelectionModel::selectionChanged,
|
||||
[this](const QItemSelection &sel, const QItemSelection &dsel)
|
||||
{ updateButtonStates(); });
|
||||
|
||||
connect(m_accounts.get(), SIGNAL(listChanged()), SLOT(listChanged()));
|
||||
connect(m_accounts.get(), SIGNAL(activeAccountChanged()), SLOT(listChanged()));
|
||||
|
||||
updateButtonStates();
|
||||
}
|
||||
|
||||
AccountListPage::~AccountListPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AccountListPage::listChanged()
|
||||
{
|
||||
updateButtonStates();
|
||||
}
|
||||
|
||||
void AccountListPage::on_addAccountBtn_clicked()
|
||||
{
|
||||
addAccount(tr("Please enter your Mojang or Minecraft account username and password to add "
|
||||
"your account."));
|
||||
}
|
||||
|
||||
void AccountListPage::on_rmAccountBtn_clicked()
|
||||
{
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
if (selection.size() > 0)
|
||||
{
|
||||
QModelIndex selected = selection.first();
|
||||
m_accounts->removeAccount(selected);
|
||||
}
|
||||
}
|
||||
|
||||
void AccountListPage::on_setDefaultBtn_clicked()
|
||||
{
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
if (selection.size() > 0)
|
||||
{
|
||||
QModelIndex selected = selection.first();
|
||||
MojangAccountPtr account =
|
||||
selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>();
|
||||
m_accounts->setActiveAccount(account->username());
|
||||
}
|
||||
}
|
||||
|
||||
void AccountListPage::on_noDefaultBtn_clicked()
|
||||
{
|
||||
m_accounts->setActiveAccount("");
|
||||
}
|
||||
|
||||
void AccountListPage::updateButtonStates()
|
||||
{
|
||||
// If there is no selection, disable buttons that require something selected.
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
|
||||
ui->rmAccountBtn->setEnabled(selection.size() > 0);
|
||||
ui->setDefaultBtn->setEnabled(selection.size() > 0);
|
||||
|
||||
ui->noDefaultBtn->setDown(m_accounts->activeAccount().get() == nullptr);
|
||||
}
|
||||
|
||||
void AccountListPage::addAccount(const QString &errMsg)
|
||||
{
|
||||
// TODO: The login dialog isn't quite done yet
|
||||
MojangAccountPtr account = LoginDialog::newAccount(this, errMsg);
|
||||
|
||||
if (account != nullptr)
|
||||
{
|
||||
m_accounts->addAccount(account);
|
||||
if (m_accounts->count() == 1)
|
||||
m_accounts->setActiveAccount(account->username());
|
||||
|
||||
// Grab associated player skins
|
||||
auto job = new NetJob("Player skins: " + account->username());
|
||||
|
||||
for (AccountProfile profile : account->profiles())
|
||||
{
|
||||
auto meta = Env::getInstance().metacache()->resolveEntry("skins", profile.name + ".png");
|
||||
auto action = CacheDownload::make(
|
||||
QUrl("http://" + URLConstants::SKINS_BASE + profile.name + ".png"), meta);
|
||||
job->addNetAction(action);
|
||||
meta->stale = true;
|
||||
}
|
||||
|
||||
job->start();
|
||||
}
|
||||
}
|
86
application/pages/global/AccountListPage.h
Normal file
86
application/pages/global/AccountListPage.h
Normal file
@ -0,0 +1,86 @@
|
||||
/* Copyright 2013-2015 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 <memory>
|
||||
|
||||
#include "pages/BasePage.h"
|
||||
|
||||
#include "auth/MojangAccountList.h"
|
||||
#include <MultiMC.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class AccountListPage;
|
||||
}
|
||||
|
||||
class AuthenticateTask;
|
||||
|
||||
class AccountListPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AccountListPage(QWidget *parent = 0);
|
||||
~AccountListPage();
|
||||
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Accounts");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
auto icon = MMC->getThemedIcon("accounts");
|
||||
if(icon.isNull())
|
||||
{
|
||||
icon = MMC->getThemedIcon("noaccount");
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "accounts";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Accounts";
|
||||
}
|
||||
|
||||
public
|
||||
slots:
|
||||
void on_addAccountBtn_clicked();
|
||||
|
||||
void on_rmAccountBtn_clicked();
|
||||
|
||||
void on_setDefaultBtn_clicked();
|
||||
|
||||
void on_noDefaultBtn_clicked();
|
||||
|
||||
void listChanged();
|
||||
|
||||
//! Updates the states of the dialog's buttons.
|
||||
void updateButtonStates();
|
||||
|
||||
protected:
|
||||
std::shared_ptr<MojangAccountList> m_accounts;
|
||||
|
||||
protected
|
||||
slots:
|
||||
void addAccount(const QString& errMsg="");
|
||||
|
||||
private:
|
||||
Ui::AccountListPage *ui;
|
||||
};
|
115
application/pages/global/AccountListPage.ui
Normal file
115
application/pages/global/AccountListPage.ui
Normal file
@ -0,0 +1,115 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AccountListPage</class>
|
||||
<widget class="QWidget" name="AccountListPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>694</width>
|
||||
<height>609</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Manage Accounts</string>
|
||||
</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>Tab 1</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="welcomeLabel">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Welcome! If you're new here, you can click the &quot;Add&quot; button to add your Mojang or Minecraft account.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QTreeView" name="listView"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="manageAcctsBtnBox">
|
||||
<item>
|
||||
<widget class="QPushButton" name="addAccountBtn">
|
||||
<property name="text">
|
||||
<string>&Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="rmAccountBtn">
|
||||
<property name="text">
|
||||
<string>&Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="buttonSpacer">
|
||||
<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="setDefaultBtn">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Set the currently selected account as the active account. The active account is the account that is used to log in (unless it is overridden in an instance-specific setting).</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Set Default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="noDefaultBtn">
|
||||
<property name="toolTip">
|
||||
<string>Set no default account. This will cause MultiMC to prompt you to select an account every time you launch an instance that doesn't have its own default set.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&No Default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user