summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt304
-rw-r--r--gui/ConsoleWindow.cpp3
-rw-r--r--gui/ConsoleWindow.h1
-rw-r--r--gui/ConsoleWindow.ui7
-rw-r--r--gui/MainWindow.cpp27
-rw-r--r--gui/MainWindow.h10
-rw-r--r--gui/MainWindow.ui10
-rw-r--r--gui/dialogs/CustomMessageBox.cpp1
-rw-r--r--gui/dialogs/ScreenshotDialog.cpp78
-rw-r--r--gui/dialogs/ScreenshotDialog.h40
-rw-r--r--gui/dialogs/ScreenshotDialog.ui110
-rw-r--r--logic/net/URLConstants.cpp19
-rw-r--r--logic/net/URLConstants.h30
-rw-r--r--logic/screenshots/ImgurAlbumCreation.cpp90
-rw-r--r--logic/screenshots/ImgurAlbumCreation.h42
-rw-r--r--logic/screenshots/ImgurUpload.cpp106
-rw-r--r--logic/screenshots/ImgurUpload.h30
-rw-r--r--logic/screenshots/Screenshot.cpp14
-rw-r--r--logic/screenshots/Screenshot.h19
-rw-r--r--logic/screenshots/ScreenshotList.cpp113
-rw-r--r--logic/screenshots/ScreenshotList.h70
-rw-r--r--logic/tasks/SequentialTask.cpp15
-rw-r--r--logic/tasks/SequentialTask.h4
23 files changed, 971 insertions, 172 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0045a41b..54a4be19 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,8 +1,8 @@
cmake_minimum_required(VERSION 2.8.9)
IF(WIN32)
- # In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows
- cmake_policy(SET CMP0020 OLD)
+ # In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows
+ cmake_policy(SET CMP0020 OLD)
ENDIF()
project(MultiMC)
@@ -22,22 +22,22 @@ SET(MMC_BIN "${PROJECT_BINARY_DIR}")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
IF(UNIX)
- SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
+ SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
ENDIF()
set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/jars)
######## Set compiler flags ########
IF(APPLE)
- message(STATUS "Using APPLE CMAKE_CXX_FLAGS")
- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
+ message(STATUS "Using APPLE CMAKE_CXX_FLAGS")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
ELSEIF(UNIX)
- # assume GCC, add C++0x/C++11 stuff
- MESSAGE(STATUS "Using UNIX CMAKE_CXX_FLAGS")
- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
+ # assume GCC, add C++0x/C++11 stuff
+ MESSAGE(STATUS "Using UNIX CMAKE_CXX_FLAGS")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
ELSEIF(MINGW)
- MESSAGE(STATUS "Using MINGW CMAKE_CXX_FLAGS")
- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall")
+ MESSAGE(STATUS "Using MINGW CMAKE_CXX_FLAGS")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall")
ENDIF()
################################ 3rd Party Libs ################################
@@ -51,21 +51,21 @@ find_package(Qt5Concurrent REQUIRED)
find_package(Qt5LinguistTools REQUIRED)
include_directories(
- ${Qt5Core_INCLUDE_DIRS}
- ${Qt5Widgets_INCLUDE_DIRS}
- ${Qt5Concurrent_INCLUDE_DIRS}
- ${Qt5Network_INCLUDE_DIRS}
- ${Qt5Test_INCLUDE_DIRS}
+ ${Qt5Core_INCLUDE_DIRS}
+ ${Qt5Widgets_INCLUDE_DIRS}
+ ${Qt5Concurrent_INCLUDE_DIRS}
+ ${Qt5Network_INCLUDE_DIRS}
+ ${Qt5Test_INCLUDE_DIRS}
)
# The Qt5 cmake files don't provide its install paths, so ask qmake.
get_target_property(QMAKE_EXECUTABLE Qt5::qmake LOCATION)
function(QUERY_QMAKE VAR RESULT)
- exec_program(${QMAKE_EXECUTABLE} ARGS "-query ${VAR}" RETURN_VALUE return_code OUTPUT_VARIABLE output )
- if(NOT return_code)
- file(TO_CMAKE_PATH "${output}" output)
- set(${RESULT} ${output} PARENT_SCOPE)
- endif(NOT return_code)
+ exec_program(${QMAKE_EXECUTABLE} ARGS "-query ${VAR}" RETURN_VALUE return_code OUTPUT_VARIABLE output )
+ if(NOT return_code)
+ file(TO_CMAKE_PATH "${output}" output)
+ set(${RESULT} ${output} PARENT_SCOPE)
+ endif(NOT return_code)
endfunction(QUERY_QMAKE)
query_qmake(QT_INSTALL_PLUGINS QT_PLUGINS_DIR)
@@ -81,7 +81,7 @@ set(QT_MKSPECS_DIR ${QT_DATA_DIR}/mkspecs)
INCLUDE(TestBigEndian)
TEST_BIG_ENDIAN(BIGENDIAN)
IF(${BIGENDIAN})
- ADD_DEFINITIONS(-DMULTIMC_BIG_ENDIAN)
+ ADD_DEFINITIONS(-DMULTIMC_BIG_ENDIAN)
ENDIF(${BIGENDIAN})
@@ -118,44 +118,44 @@ 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}")
+ 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}")
+ 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}")
+ MESSAGE(STATUS "Version Type: Stable Release")
+ SET(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}")
ELSEIF (MultiMC_VERSION_TYPE STREQUAL "ReleaseCandidate")
- MESSAGE(STATUS "Version Type: Release Candidate")
- SET(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}-rc${MultiMC_VERSION_BUILD}")
+ MESSAGE(STATUS "Version Type: Release Candidate")
+ SET(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}-rc${MultiMC_VERSION_BUILD}")
ELSEIF (MultiMC_VERSION_TYPE STREQUAL "Development")
- MESSAGE(STATUS "Version Type: Development")
- SET(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}-dev${MultiMC_VERSION_BUILD}")
+ MESSAGE(STATUS "Version Type: Development")
+ SET(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}-dev${MultiMC_VERSION_BUILD}")
ELSE ()
- MESSAGE(ERROR "Invalid build type.")
+ 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}")
+ 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 ()
#### Custom target to just print the version.
@@ -163,18 +163,18 @@ ADD_CUSTOM_TARGET(version echo "Version: ${MultiMC_VERSION_STRING}")
#### Check the current Git commit
execute_process(COMMAND git rev-parse HEAD
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
- RESULT_VARIABLE GIT_COMMIT_CHECK_RESULTVAR
- OUTPUT_VARIABLE GIT_COMMIT_CHECK_OUTVAR
- OUTPUT_STRIP_TRAILING_WHITESPACE
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ RESULT_VARIABLE GIT_COMMIT_CHECK_RESULTVAR
+ OUTPUT_VARIABLE GIT_COMMIT_CHECK_OUTVAR
+ OUTPUT_STRIP_TRAILING_WHITESPACE
)
IF(GIT_COMMIT_CHECK_RESULTVAR EQUAL 0)
- SET(MultiMC_GIT_COMMIT "${GIT_COMMIT_CHECK_OUTVAR}")
- MESSAGE(STATUS "Git commit: ${MultiMC_GIT_COMMIT}")
+ SET(MultiMC_GIT_COMMIT "${GIT_COMMIT_CHECK_OUTVAR}")
+ MESSAGE(STATUS "Git commit: ${MultiMC_GIT_COMMIT}")
ELSE()
- SET(MultiMC_GIT_COMMIT "Unknown")
- MESSAGE(STATUS "Failed to check Git commit. ${GIT_COMMIT_CHECK_RESULTVAR}")
+ SET(MultiMC_GIT_COMMIT "Unknown")
+ MESSAGE(STATUS "Failed to check Git commit. ${GIT_COMMIT_CHECK_RESULTVAR}")
ENDIF()
######## Configure header ########
@@ -190,29 +190,29 @@ ADD_DEFINITIONS(-DLIBUTIL_STATIC)
######## Packaging/install paths setup ########
IF(UNIX AND APPLE)
- SET(BINARY_DEST_DIR MultiMC.app/Contents/MacOS)
- SET(PLUGIN_DEST_DIR MultiMC.app/Contents/MacOS)
- SET(QTCONF_DEST_DIR MultiMC.app/Contents/Resources)
- SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app")
-
- SET(MACOSX_BUNDLE_BUNDLE_NAME "MultiMC")
- SET(MACOSX_BUNDLE_INFO_STRING "MultiMC Minecraft launcher and management utility.")
- SET(MACOSX_BUNDLE_GUI_IDENTIFIER "org.multimc.MultiMC5")
- SET(MACOSX_BUNDLE_BUNDLE_VERSION "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
- SET(MACOSX_BUNDLE_SHORT_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
- SET(MACOSX_BUNDLE_LONG_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
- SET(MACOSX_BUNDLE_ICON_FILE MultiMC.icns)
- SET(MACOSX_BUNDLE_COPYRIGHT "Copyright 2013 MultiMC Contributors")
+ SET(BINARY_DEST_DIR MultiMC.app/Contents/MacOS)
+ SET(PLUGIN_DEST_DIR MultiMC.app/Contents/MacOS)
+ SET(QTCONF_DEST_DIR MultiMC.app/Contents/Resources)
+ SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app")
+
+ SET(MACOSX_BUNDLE_BUNDLE_NAME "MultiMC")
+ SET(MACOSX_BUNDLE_INFO_STRING "MultiMC Minecraft launcher and management utility.")
+ SET(MACOSX_BUNDLE_GUI_IDENTIFIER "org.multimc.MultiMC5")
+ SET(MACOSX_BUNDLE_BUNDLE_VERSION "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
+ SET(MACOSX_BUNDLE_SHORT_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
+ SET(MACOSX_BUNDLE_LONG_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
+ SET(MACOSX_BUNDLE_ICON_FILE MultiMC.icns)
+ SET(MACOSX_BUNDLE_COPYRIGHT "Copyright 2013 MultiMC Contributors")
ELSEIF(UNIX)
- SET(BINARY_DEST_DIR bin)
- SET(PLUGIN_DEST_DIR plugins)
- SET(QTCONF_DEST_DIR .)
- SET(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC")
+ 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")
+ 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
@@ -308,6 +308,8 @@ gui/dialogs/AccountSelectDialog.h
gui/dialogs/AccountSelectDialog.cpp
gui/dialogs/UpdateDialog.h
gui/dialogs/UpdateDialog.cpp
+gui/dialogs/ScreenshotDialog.h
+gui/dialogs/ScreenshotDialog.cpp
# GUI - widgets
gui/widgets/Common.h
@@ -370,6 +372,7 @@ logic/net/HttpMetaCache.cpp
logic/net/PasteUpload.h
logic/net/PasteUpload.cpp
logic/net/URLConstants.h
+logic/net/URLConstants.cpp
# Yggdrasil login stuff
logic/auth/AuthSession.h
@@ -463,6 +466,16 @@ logic/lists/JavaVersionList.cpp
logic/lists/LiteLoaderVersionList.h
logic/lists/LiteLoaderVersionList.cpp
+# the screenshots feature
+logic/screenshots/Screenshot.h
+logic/screenshots/Screenshot.cpp
+logic/screenshots/ScreenshotList.h
+logic/screenshots/ScreenshotList.cpp
+logic/screenshots/ImgurUpload.h
+logic/screenshots/ImgurUpload.cpp
+logic/screenshots/ImgurAlbumCreation.h
+logic/screenshots/ImgurAlbumCreation.cpp
+
# Icons
logic/icons/MMCIcon.h
logic/icons/MMCIcon.cpp
@@ -539,6 +552,7 @@ gui/dialogs/AccountListDialog.ui
gui/dialogs/AccountSelectDialog.ui
gui/dialogs/EditAccountDialog.ui
gui/dialogs/UpdateDialog.ui
+gui/dialogs/ScreenshotDialog.ui
# Widgets/other
gui/widgets/MCModInfoFrame.ui
@@ -560,11 +574,11 @@ ENDIF()
####### X11 Stuff #######
IF(UNIX AND NOT APPLE)
- SET(MultiMC_QT_ADDITIONAL_MODULES ${MultiMC_QT_ADDITIONAL_MODULES} X11Extras)
- SET(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS} xcb)
- LIST(APPEND MULTIMC_SOURCES gui/Platform_X11.cpp)
+ SET(MultiMC_QT_ADDITIONAL_MODULES ${MultiMC_QT_ADDITIONAL_MODULES} X11Extras)
+ SET(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS} xcb)
+ LIST(APPEND MULTIMC_SOURCES gui/Platform_X11.cpp)
ELSE()
- LIST(APPEND MULTIMC_SOURCES gui/Platform_Other.cpp)
+ LIST(APPEND MULTIMC_SOURCES gui/Platform_Other.cpp)
ENDIF()
@@ -572,9 +586,9 @@ ENDIF()
# Link additional libraries
IF(WIN32)
- SET(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS}
- Qt5::WinMain # Link WinMain
- )
+ SET(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS}
+ Qt5::WinMain # Link WinMain
+ )
ENDIF(WIN32)
OPTION(MultiMC_UPDATER_DRY_RUN "Enable updater dry-run mode -- for updater development." OFF)
@@ -582,11 +596,11 @@ OPTION(MultiMC_UPDATER_FORCE_LOCAL "Do not download updated updater -- for updat
OPTION(MultiMC_CODE_COVERAGE "Compiles for code coverage" OFF)
IF(MultiMC_CODE_COVERAGE)
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 --coverage")
- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 --coverage")
- SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0 --coverage")
- SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g -O0 --coverage")
- SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -O0 --coverage")
+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 --coverage")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 --coverage")
+ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0 --coverage")
+ SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g -O0 --coverage")
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -O0 --coverage")
ENDIF(MultiMC_CODE_COVERAGE)
# Tell CMake that MultiMCLauncher.jar is generated.
@@ -615,24 +629,24 @@ QT5_USE_MODULES(MultiMC_common Core Widgets Network Xml Concurrent ${MultiMC_QT_
#### Executable ####
IF(APPLE AND UNIX) ## OSX
- INSTALL(TARGETS MultiMC
- BUNDLE DESTINATION . COMPONENT Runtime
- RUNTIME DESTINATION MultiMC.app/Contents/MacOS COMPONENT Runtime
- )
+ 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 .)
+ 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
- )
+ INSTALL(TARGETS MultiMC
+ BUNDLE DESTINATION . COMPONENT Runtime
+ LIBRARY DESTINATION . COMPONENT Runtime
+ RUNTIME DESTINATION . COMPONENT Runtime
+ )
ENDIF()
#### Dist package logic ####
@@ -640,70 +654,70 @@ ENDIF()
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|svg|tiff|mng" EXCLUDE
+ DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "tga|svg|tiff|mng" EXCLUDE
)
# Platform plugins
INSTALL(
- DIRECTORY "${QT_PLUGINS_DIR}/platforms"
- DESTINATION ${PLUGIN_DEST_DIR}
- COMPONENT Runtime
- REGEX "minimal|linuxfb|offscreen" EXCLUDE
+ 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|svg|tiff|mng" EXCLUDE
- REGEX "d\\." EXCLUDE
- REGEX "_debug\\." EXCLUDE
+ DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "tga|svg|tiff|mng" 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
+ 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
- )
+ # 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 "
+ CODE "
FILE(WRITE \"\${CMAKE_INSTALL_PREFIX}/${QTCONF_DEST_DIR}/qt.conf\" \"\")
"
- COMPONENT Runtime
+ COMPONENT Runtime
)
# ICNS file for OS X
IF(APPLE)
- INSTALL(FILES resources/MultiMC.icns DESTINATION MultiMC.app/Contents/Resources)
+ 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)
+ "${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)
@@ -712,13 +726,13 @@ INSTALL(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/install_prereqs.cmake" COMPONENT Run
# Package with CPack
IF(UNIX)
- if(APPLE)
- SET(CPACK_GENERATOR "ZIP")
- else()
- SET(CPACK_GENERATOR "TGZ")
- endif()
+ if(APPLE)
+ SET(CPACK_GENERATOR "ZIP")
+ else()
+ SET(CPACK_GENERATOR "TGZ")
+ endif()
ELSEIF(WIN32)
- SET(CPACK_GENERATOR "ZIP")
+ SET(CPACK_GENERATOR "ZIP")
ENDIF()
SET(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0)
@@ -750,16 +764,16 @@ file (GLOB TRANSLATIONS_FILES translations/*.ts)
option (UPDATE_TRANSLATIONS "Update source translation translations/*.ts files (WARNING: make clean will delete the source .ts files! Danger!)")
IF(UPDATE_TRANSLATIONS)
- qt5_create_translation(QM_FILES ${FILES_TO_TRANSLATE} ${TRANSLATIONS_FILES})
+ qt5_create_translation(QM_FILES ${FILES_TO_TRANSLATE} ${TRANSLATIONS_FILES})
ELSE()
- qt5_add_translation(QM_FILES ${TRANSLATIONS_FILES})
+ qt5_add_translation(QM_FILES ${TRANSLATIONS_FILES})
ENDIF()
add_custom_target (translations DEPENDS ${QM_FILES})
IF(APPLE AND UNIX) ## OSX
- install(FILES ${QM_FILES} DESTINATION MultiMC.app/Contents/MacOS/translations)
+ install(FILES ${QM_FILES} DESTINATION MultiMC.app/Contents/MacOS/translations)
ELSE()
- install(FILES ${QM_FILES} DESTINATION translations)
+ install(FILES ${QM_FILES} DESTINATION translations)
ENDIF()
diff --git a/gui/ConsoleWindow.cpp b/gui/ConsoleWindow.cpp
index ccc037f2..d11e8aff 100644
--- a/gui/ConsoleWindow.cpp
+++ b/gui/ConsoleWindow.cpp
@@ -42,6 +42,8 @@ ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent)
connect(mcproc, SIGNAL(launch_failed(BaseInstance *)), this,
SLOT(onLaunchFailed(BaseInstance *)));
+ connect(ui->btnScreenshots, &QPushButton::clicked, this, &ConsoleWindow::uploadScreenshots);
+
restoreState(
QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowState").toByteArray()));
restoreGeometry(
@@ -52,6 +54,7 @@ ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent)
auto icon = MMC->icons()->getIcon(iconKey);
setWindowIcon(icon);
m_trayIcon = new QSystemTrayIcon(icon, this);
+ // TODO add screenshot upload as a menu item in the tray icon
QString consoleTitle = tr("Console window for ") + name;
m_trayIcon->setToolTip(consoleTitle);
setWindowTitle(consoleTitle);
diff --git a/gui/ConsoleWindow.h b/gui/ConsoleWindow.h
index 7fe90c52..e21da33c 100644
--- a/gui/ConsoleWindow.h
+++ b/gui/ConsoleWindow.h
@@ -51,6 +51,7 @@ private:
signals:
void isClosing();
+ void uploadScreenshots();
public
slots:
diff --git a/gui/ConsoleWindow.ui b/gui/ConsoleWindow.ui
index c2307ecc..344cf74d 100644
--- a/gui/ConsoleWindow.ui
+++ b/gui/ConsoleWindow.ui
@@ -50,6 +50,13 @@
</widget>
</item>
<item>
+ <widget class="QPushButton" name="btnScreenshots">
+ <property name="text">
+ <string>Manage Screenshots</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp
index 121c2a73..17d4630b 100644
--- a/gui/MainWindow.cpp
+++ b/gui/MainWindow.cpp
@@ -44,7 +44,6 @@
#include "gui/Platform.h"
-
#include "gui/widgets/LabeledToolButton.h"
#include "gui/dialogs/SettingsDialog.h"
@@ -62,6 +61,7 @@
#include "gui/dialogs/AccountSelectDialog.h"
#include "gui/dialogs/UpdateDialog.h"
#include "gui/dialogs/EditAccountDialog.h"
+#include "gui/dialogs/ScreenshotDialog.h"
#include "gui/ConsoleWindow.h"
@@ -81,6 +81,7 @@
#include "logic/status/StatusChecker.h"
#include "logic/net/URLConstants.h"
+#include "logic/net/NetJob.h"
#include "logic/BaseInstance.h"
#include "logic/InstanceFactory.h"
@@ -146,7 +147,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
{
view = new GroupView(ui->centralWidget);
-
view->setSelectionMode(QAbstractItemView::SingleSelection);
// view->setCategoryDrawer(drawer);
// view->setCollapsibleBlocks(true);
@@ -1284,6 +1284,7 @@ void MainWindow::launchInstance(BaseInstance *instance, AuthSessionPtr session,
console = new ConsoleWindow(proc);
connect(console, SIGNAL(isClosing()), this, SLOT(instanceEnded()));
+ connect(console, &ConsoleWindow::uploadScreenshots, this, &MainWindow::on_actionScreenshots_triggered);
proc->setLogin(session);
proc->arm();
@@ -1600,3 +1601,25 @@ void MainWindow::checkSetDefaultJava()
MMC->settings()->set("JavaPath", QString("java"));
}
}
+
+void MainWindow::on_actionScreenshots_triggered()
+{
+ if (!m_selectedInstance)
+ return;
+ ScreenshotList *list = new ScreenshotList(m_selectedInstance);
+ Task *task = list->load();
+ ProgressDialog prog(this);
+ prog.exec(task);
+ if (!task->successful())
+ {
+ CustomMessageBox::selectable(this, tr("Failed to load screenshots!"),
+ task->failReason(), QMessageBox::Warning)->exec();
+ return;
+ }
+ ScreenshotDialog dialog(list, this);
+ if (dialog.exec() == ScreenshotDialog::Accepted)
+ {
+ CustomMessageBox::selectable(this, tr("Done uploading!"), dialog.message(),
+ QMessageBox::Information)->exec();
+ }
+}
diff --git a/gui/MainWindow.h b/gui/MainWindow.h
index 7a29977d..3a2843f8 100644
--- a/gui/MainWindow.h
+++ b/gui/MainWindow.h
@@ -139,7 +139,9 @@ slots:
// called when an icon is changed in the icon model.
void iconUpdated(QString);
- void showInstanceContextMenu(const QPoint&);
+ void showInstanceContextMenu(const QPoint &);
+
+ void on_actionScreenshots_triggered();
void updateToolsMenu();
@@ -170,11 +172,11 @@ slots:
void updateStatusFailedUI();
void reloadStatus();
-
+
/*!
* Runs the DownloadUpdateTask and installs updates.
*/
- void downloadUpdates(QString repo, int versionId, bool installOnExit=false);
+ void downloadUpdates(QString repo, int versionId, bool installOnExit = false);
protected:
bool eventFilter(QObject *obj, QEvent *ev);
@@ -191,7 +193,7 @@ private:
ConsoleWindow *console;
LabeledToolButton *renameButton;
QToolButton *changeIconButton;
- QToolButton* newsLabel;
+ QToolButton *newsLabel;
BaseInstance *m_selectedInstance;
QString m_currentInstIcon;
diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui
index 90c86075..2bd8ec22 100644
--- a/gui/MainWindow.ui
+++ b/gui/MainWindow.ui
@@ -112,6 +112,8 @@
<addaction name="actionEditInstNotes"/>
<addaction name="actionChangeInstGroup"/>
<addaction name="separator"/>
+ <addaction name="actionScreenshots"/>
+ <addaction name="separator"/>
<addaction name="actionInstanceSettings"/>
<addaction name="actionChangeInstMCVersion"/>
<addaction name="actionChangeInstLWJGLVersion"/>
@@ -528,6 +530,14 @@
<string>Launch the selected instance.</string>
</property>
</action>
+ <action name="actionScreenshots">
+ <property name="text">
+ <string>Manage Screenshots</string>
+ </property>
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;View and upload screenshots for this instance&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
diff --git a/gui/dialogs/CustomMessageBox.cpp b/gui/dialogs/CustomMessageBox.cpp
index 1d2ab58a..4013db60 100644
--- a/gui/dialogs/CustomMessageBox.cpp
+++ b/gui/dialogs/CustomMessageBox.cpp
@@ -28,6 +28,7 @@ QMessageBox *selectable(QWidget *parent, const QString &title, const QString &te
messageBox->setDefaultButton(defaultButton);
messageBox->setTextInteractionFlags(Qt::TextSelectableByMouse);
messageBox->setIcon(icon);
+ messageBox->setTextInteractionFlags(Qt::TextBrowserInteraction);
return messageBox;
}
diff --git a/gui/dialogs/ScreenshotDialog.cpp b/gui/dialogs/ScreenshotDialog.cpp
new file mode 100644
index 00000000..a88c8dfd
--- /dev/null
+++ b/gui/dialogs/ScreenshotDialog.cpp
@@ -0,0 +1,78 @@
+#include "ScreenshotDialog.h"
+#include "ui_ScreenshotDialog.h"
+
+#include <QModelIndex>
+#include <QMutableListIterator>
+
+#include "ProgressDialog.h"
+#include "CustomMessageBox.h"
+#include "logic/net/NetJob.h"
+#include "logic/screenshots/ImgurUpload.h"
+#include "logic/screenshots/ImgurAlbumCreation.h"
+#include "logic/tasks/SequentialTask.h"
+
+ScreenshotDialog::ScreenshotDialog(ScreenshotList *list, QWidget *parent)
+ : QDialog(parent), ui(new Ui::ScreenshotDialog), m_list(list)
+{
+ ui->setupUi(this);
+ ui->listView->setModel(m_list);
+}
+
+ScreenshotDialog::~ScreenshotDialog()
+{
+ delete ui;
+}
+
+QString ScreenshotDialog::message() const
+{
+ return tr("<a href=\"https://imgur.com/a/%1\">Visit album</a><br/>Delete hash: %2 (save "
+ "this if you want to be able to edit/delete the album)")
+ .arg(m_imgurAlbum->id(), m_imgurAlbum->deleteHash());
+}
+
+QList<ScreenshotPtr> ScreenshotDialog::selected() const
+{
+ QList<ScreenshotPtr> list;
+ QList<ScreenshotPtr> first = m_list->screenshots();
+ for (QModelIndex index : ui->listView->selectionModel()->selectedRows())
+ {
+ list.append(first.at(index.row()));
+ }
+ return list;
+}
+
+void ScreenshotDialog::on_uploadBtn_clicked()
+{
+ m_uploaded = selected();
+ if (m_uploaded.isEmpty())
+ {
+ done(NothingDone);
+ return;
+ }
+ SequentialTask *task = new SequentialTask(this);
+ NetJob *job = new NetJob("Screenshot Upload");
+ for (auto shot : m_uploaded)
+ {
+ job->addNetAction(ImgurUpload::make(shot));
+ }
+ NetJob *albumTask = new NetJob("Imgur Album Creation");
+ albumTask->addNetAction(m_imgurAlbum = ImgurAlbumCreation::make(m_uploaded));
+ task->addTask(NetJobPtr(job));
+ task->addTask(NetJobPtr(albumTask));
+ ProgressDialog prog(this);
+ if (prog.exec(task) == QDialog::Accepted)
+ {
+ accept();
+ }
+ else
+ {
+ CustomMessageBox::selectable(this, tr("Failed to upload screenshots!"),
+ tr("Unknown error"), QMessageBox::Warning)->exec();
+ reject();
+ }
+}
+
+void ScreenshotDialog::on_deleteBtn_clicked()
+{
+ m_list->deleteSelected(this);
+}
diff --git a/gui/dialogs/ScreenshotDialog.h b/gui/dialogs/ScreenshotDialog.h
new file mode 100644
index 00000000..29dd6765
--- /dev/null
+++ b/gui/dialogs/ScreenshotDialog.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <QDialog>
+#include "logic/screenshots/ScreenshotList.h"
+
+class ImgurAlbumCreation;
+
+namespace Ui
+{
+class ScreenshotDialog;
+}
+
+class ScreenshotDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit ScreenshotDialog(ScreenshotList *list, QWidget *parent = 0);
+ ~ScreenshotDialog();
+
+ enum
+ {
+ NothingDone = 0x42
+ };
+
+ QString message() const;
+ QList<ScreenshotPtr> selected() const;
+
+private
+slots:
+ void on_uploadBtn_clicked();
+
+ void on_deleteBtn_clicked();
+
+private:
+ Ui::ScreenshotDialog *ui;
+ ScreenshotList *m_list;
+ QList<ScreenshotPtr> m_uploaded;
+ std::shared_ptr<ImgurAlbumCreation> m_imgurAlbum;
+};
diff --git a/gui/dialogs/ScreenshotDialog.ui b/gui/dialogs/ScreenshotDialog.ui
new file mode 100644
index 00000000..eb3dafba
--- /dev/null
+++ b/gui/dialogs/ScreenshotDialog.ui
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ScreenshotDialog</class>
+ <widget class="QDialog" name="ScreenshotDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>470</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Screenshot Manager</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="../../resources/multimc/multimc.qrc">
+ <normaloff>:/icons/multimc/scalable/apps/multimc.svg</normaloff>:/icons/multimc/scalable/apps/multimc.svg</iconset>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QListView" name="listView">
+ <property name="selectionMode">
+ <enum>QAbstractItemView::ExtendedSelection</enum>
+ </property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectItems</enum>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>120</width>
+ <height>90</height>
+ </size>
+ </property>
+ <property name="flow">
+ <enum>QListView::LeftToRight</enum>
+ </property>
+ <property name="isWrapping" stdset="0">
+ <bool>true</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>QListView::Adjust</enum>
+ </property>
+ <property name="viewMode">
+ <enum>QListView::IconMode</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <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>
+ <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="closeBtn">
+ <property name="text">
+ <string>Close</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../resources/multimc/multimc.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>closeBtn</sender>
+ <signal>clicked()</signal>
+ <receiver>ScreenshotDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>315</x>
+ <y>272</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>271</x>
+ <y>258</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/logic/net/URLConstants.cpp b/logic/net/URLConstants.cpp
new file mode 100644
index 00000000..14b28085
--- /dev/null
+++ b/logic/net/URLConstants.cpp
@@ -0,0 +1,19 @@
+#include "URLConstants.h"
+namespace URLConstants
+{
+const QString AWS_DOWNLOAD_BASE("s3.amazonaws.com/Minecraft.Download/");
+const QString AWS_DOWNLOAD_VERSIONS(AWS_DOWNLOAD_BASE + "versions/");
+const QString AWS_DOWNLOAD_LIBRARIES(AWS_DOWNLOAD_BASE + "libraries/");
+const QString AWS_DOWNLOAD_INDEXES(AWS_DOWNLOAD_BASE + "indexes/");
+const QString ASSETS_BASE("assets.minecraft.net/");
+const QString RESOURCE_BASE("resources.download.minecraft.net/");
+const QString LIBRARY_BASE("libraries.minecraft.net/");
+const QString SKINS_BASE("skins.minecraft.net/MinecraftSkins/");
+const QString AUTH_BASE("authserver.mojang.com/");
+const QString FORGE_LEGACY_URL("http://files.minecraftforge.net/minecraftforge/json");
+const QString FORGE_GRADLE_URL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/json");
+const QString MOJANG_STATUS_URL("http://status.mojang.com/check");
+const QString MOJANG_STATUS_NEWS_URL("http://status.mojang.com/news");
+const QString LITELOADER_URL("http://dl.liteloader.com/versions/versions.json");
+const QString IMGUR_BASE_URL("https://api.imgur.com/3/");
+} \ No newline at end of file
diff --git a/logic/net/URLConstants.h b/logic/net/URLConstants.h
index 07b35c4f..c1064115 100644
--- a/logic/net/URLConstants.h
+++ b/logic/net/URLConstants.h
@@ -19,19 +19,19 @@
namespace URLConstants
{
-const QString AWS_DOWNLOAD_BASE("s3.amazonaws.com/Minecraft.Download/");
-const QString AWS_DOWNLOAD_VERSIONS(AWS_DOWNLOAD_BASE + "versions/");
-const QString AWS_DOWNLOAD_LIBRARIES(AWS_DOWNLOAD_BASE + "libraries/");
-const QString AWS_DOWNLOAD_INDEXES(AWS_DOWNLOAD_BASE + "indexes/");
-const QString ASSETS_BASE("assets.minecraft.net/");
-//const QString MCN_BASE("sonicrules.org/mcnweb.py");
-const QString RESOURCE_BASE("resources.download.minecraft.net/");
-const QString LIBRARY_BASE("libraries.minecraft.net/");
-const QString SKINS_BASE("skins.minecraft.net/MinecraftSkins/");
-const QString AUTH_BASE("authserver.mojang.com/");
-const QString FORGE_LEGACY_URL("http://files.minecraftforge.net/minecraftforge/json");
-const QString FORGE_GRADLE_URL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/json");
-const QString MOJANG_STATUS_URL("http://status.mojang.com/check");
-const QString MOJANG_STATUS_NEWS_URL("http://status.mojang.com/news");
-const QString LITELOADER_URL("http://dl.liteloader.com/versions/versions.json");
+extern const QString AWS_DOWNLOAD_BASE;
+extern const QString AWS_DOWNLOAD_VERSIONS;
+extern const QString AWS_DOWNLOAD_LIBRARIES;
+extern const QString AWS_DOWNLOAD_INDEXES;
+extern const QString ASSETS_BASE;
+extern const QString RESOURCE_BASE;
+extern const QString LIBRARY_BASE;
+extern const QString SKINS_BASE;
+extern const QString AUTH_BASE;
+extern const QString FORGE_LEGACY_URL;
+extern const QString FORGE_GRADLE_URL;
+extern const QString MOJANG_STATUS_URL;
+extern const QString MOJANG_STATUS_NEWS_URL;
+extern const QString LITELOADER_URL;
+extern const QString IMGUR_BASE_URL;
}
diff --git a/logic/screenshots/ImgurAlbumCreation.cpp b/logic/screenshots/ImgurAlbumCreation.cpp
new file mode 100644
index 00000000..e473952e
--- /dev/null
+++ b/logic/screenshots/ImgurAlbumCreation.cpp
@@ -0,0 +1,90 @@
+#include "ImgurAlbumCreation.h"
+
+#include <QNetworkRequest>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QUrl>
+
+#include "logic/screenshots//ScreenshotList.h"
+#include "logic/net/URLConstants.h"
+#include "MultiMC.h"
+#include "logger/QsLog.h"
+
+ImgurAlbumCreation::ImgurAlbumCreation(QList<ScreenshotPtr> screenshots) : NetAction(), m_screenshots(screenshots)
+{
+ m_url = URLConstants::IMGUR_BASE_URL + "album.json";
+ m_status = Job_NotStarted;
+}
+
+void ImgurAlbumCreation::start()
+{
+ m_status = Job_InProgress;
+ QNetworkRequest request(m_url);
+ request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)");
+ request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
+ request.setRawHeader("Authorization", "Client-ID 5b97b0713fba4a3");
+ request.setRawHeader("Accept", "application/json");
+
+ QStringList ids;
+ for (auto shot : m_screenshots)
+ {
+ ids.append(shot->imgurId);
+ }
+
+ const QByteArray data = "ids=" + ids.join(',').toUtf8() + "&title=Minecraft%20Screenshots&privacy=hidden";
+
+ auto worker = MMC->qnam();
+ QNetworkReply *rep = worker->post(request, data);
+
+ m_reply = std::shared_ptr<QNetworkReply>(rep);
+ connect(rep, &QNetworkReply::uploadProgress, this, &ImgurAlbumCreation::downloadProgress);
+ connect(rep, &QNetworkReply::finished, this, &ImgurAlbumCreation::downloadFinished);
+ connect(rep, SIGNAL(error(QNetworkReply::NetworkError)),
+ SLOT(downloadError(QNetworkReply::NetworkError)));
+}
+void ImgurAlbumCreation::downloadError(QNetworkReply::NetworkError error)
+{
+ QLOG_DEBUG() << m_reply->errorString();
+ m_status = Job_Failed;
+}
+void ImgurAlbumCreation::downloadFinished()
+{
+ if (m_status != Job_Failed)
+ {
+ QByteArray data = m_reply->readAll();
+ m_reply.reset();
+ QJsonParseError jsonError;
+ QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
+ if (jsonError.error != QJsonParseError::NoError)
+ {
+ QLOG_DEBUG() << jsonError.errorString();
+ emit failed(m_index_within_job);
+ return;
+ }
+ auto object = doc.object();
+ if (!object.value("success").toBool())
+ {
+ QLOG_DEBUG() << doc.toJson();
+ emit failed(m_index_within_job);
+ return;
+ }
+ m_deleteHash = object.value("data").toObject().value("deletehash").toString();
+ m_id = object.value("data").toObject().value("id").toString();
+ m_status = Job_Finished;
+ emit succeeded(m_index_within_job);
+ return;
+ }
+ else
+ {
+ QLOG_DEBUG() << m_reply->readAll();
+ m_reply.reset();
+ emit failed(m_index_within_job);
+ return;
+ }
+}
+void ImgurAlbumCreation::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
+{
+ m_total_progress = bytesTotal;
+ m_progress = bytesReceived;
+ emit progress(m_index_within_job, bytesReceived, bytesTotal);
+}
diff --git a/logic/screenshots/ImgurAlbumCreation.h b/logic/screenshots/ImgurAlbumCreation.h
new file mode 100644
index 00000000..6e8fbe94
--- /dev/null
+++ b/logic/screenshots/ImgurAlbumCreation.h
@@ -0,0 +1,42 @@
+#pragma once
+#include "logic/net/NetAction.h"
+#include "Screenshot.h"
+
+typedef std::shared_ptr<class ImgurAlbumCreation> ImgurAlbumCreationPtr;
+class ImgurAlbumCreation : public NetAction
+{
+public:
+ explicit ImgurAlbumCreation(QList<ScreenshotPtr> screenshots);
+ static ImgurAlbumCreationPtr make(QList<ScreenshotPtr> screenshots)
+ {
+ return ImgurAlbumCreationPtr(new ImgurAlbumCreation(screenshots));
+ }
+
+ QString deleteHash() const
+ {
+ return m_deleteHash;
+ }
+ QString id() const
+ {
+ return m_id;
+ }
+
+protected
+slots:
+ virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
+ virtual void downloadError(QNetworkReply::NetworkError error);
+ virtual void downloadFinished();
+ virtual void downloadReadyRead()
+ {
+ }
+
+public
+slots:
+ virtual void start();
+
+private:
+ QList<ScreenshotPtr> m_screenshots;
+
+ QString m_deleteHash;
+ QString m_id;
+};
diff --git a/logic/screenshots/ImgurUpload.cpp b/logic/screenshots/ImgurUpload.cpp
new file mode 100644
index 00000000..62033ef5
--- /dev/null
+++ b/logic/screenshots/ImgurUpload.cpp
@@ -0,0 +1,106 @@
+#include "ImgurUpload.h"
+
+#include <QNetworkRequest>
+#include <QHttpMultiPart>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QHttpPart>
+#include <QFile>
+#include <QUrl>
+
+#include "logic/screenshots/ScreenshotList.h"
+#include "logic/net/URLConstants.h"
+#include "MultiMC.h"
+#include "logger/QsLog.h"
+
+ImgurUpload::ImgurUpload(ScreenshotPtr shot) : NetAction(), m_shot(shot)
+{
+ m_url = URLConstants::IMGUR_BASE_URL + "upload.json";
+ m_status = Job_NotStarted;
+}
+
+void ImgurUpload::start()
+{
+ m_status = Job_InProgress;
+ QNetworkRequest request(m_url);
+ request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)");
+ request.setRawHeader("Authorization", "Client-ID 5b97b0713fba4a3");
+ request.setRawHeader("Accept", "application/json");
+
+ QFile f(m_shot->file);
+ if (!f.open(QFile::ReadOnly))
+ {
+ emit failed(m_index_within_job);
+ return;
+ }
+
+ QHttpMultiPart *multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
+ QHttpPart filePart;
+ filePart.setBody(f.readAll().toBase64());
+ filePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/png");
+ filePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"image\"");
+ multipart->append(filePart);
+ QHttpPart typePart;
+ typePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"type\"");
+ typePart.setBody("base64");
+ multipart->append(typePart);
+ QHttpPart namePart;
+ namePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"name\"");
+ namePart.setBody(m_shot->timestamp.toString(Qt::ISODate).toUtf8());
+ multipart->append(namePart);
+
+ auto worker = MMC->qnam();
+ QNetworkReply *rep = worker->post(request, multipart);
+
+ m_reply = std::shared_ptr<QNetworkReply>(rep);
+ connect(rep, &QNetworkReply::uploadProgress, this, &ImgurUpload::downloadProgress);
+ connect(rep, &QNetworkReply::finished, this, &ImgurUpload::downloadFinished);
+ connect(rep, SIGNAL(error(QNetworkReply::NetworkError)),
+ SLOT(downloadError(QNetworkReply::NetworkError)));
+}
+void ImgurUpload::downloadError(QNetworkReply::NetworkError error)
+{
+ QLOG_DEBUG() << m_reply->errorString();
+ m_status = Job_Failed;
+}
+void ImgurUpload::downloadFinished()
+{
+ if (m_status != Job_Failed)
+ {
+ QByteArray data = m_reply->readAll();
+ m_reply.reset();
+ QJsonParseError jsonError;
+ QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
+ if (jsonError.error != QJsonParseError::NoError)
+ {
+ QLOG_DEBUG() << jsonError.errorString();
+ emit failed(m_index_within_job);
+ return;
+ }
+ auto object = doc.object();
+ if (!object.value("success").toBool())
+ {
+ QLOG_DEBUG() << doc.toJson();
+ emit failed(m_index_within_job);
+ return;
+ }
+ m_shot->imgurId = object.value("data").toObject().value("id").toString();
+ m_shot->url = object.value("data").toObject().value("link").toString();
+ m_status = Job_Finished;
+ emit succeeded(m_index_within_job);
+ return;
+ }
+ else
+ {
+ QLOG_DEBUG() << m_reply->readAll();
+ m_reply.reset();
+ emit failed(m_index_within_job);
+ return;
+ }
+}
+void ImgurUpload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
+{
+ m_total_progress = bytesTotal;
+ m_progress = bytesReceived;
+ emit progress(m_index_within_job, bytesReceived, bytesTotal);
+}
diff --git a/logic/screenshots/ImgurUpload.h b/logic/screenshots/ImgurUpload.h
new file mode 100644
index 00000000..1111a8d0
--- /dev/null
+++ b/logic/screenshots/ImgurUpload.h
@@ -0,0 +1,30 @@
+#pragma once
+#include "logic/net/NetAction.h"
+#include "Screenshot.h"
+
+typedef std::shared_ptr<class ImgurUpload> ImgurUploadPtr;
+class ImgurUpload : public NetAction
+{
+public:
+ explicit ImgurUpload(ScreenshotPtr shot);
+ static ImgurUploadPtr make(ScreenshotPtr shot)
+ {
+ return ImgurUploadPtr(new ImgurUpload(shot));
+ }
+
+protected
+slots:
+ virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
+ virtual void downloadError(QNetworkReply::NetworkError error);
+ virtual void downloadFinished();
+ virtual void downloadReadyRead()
+ {
+ }
+
+public
+slots:
+ virtual void start();
+
+private:
+ ScreenshotPtr m_shot;
+};
diff --git a/logic/screenshots/Screenshot.cpp b/logic/screenshots/Screenshot.cpp
new file mode 100644
index 00000000..882e491f
--- /dev/null
+++ b/logic/screenshots/Screenshot.cpp
@@ -0,0 +1,14 @@
+#include "Screenshot.h"
+#include <QImage>
+#include <QIcon>
+QIcon ScreenShot::getImage()
+{
+ if(!imageloaded)
+ {
+ QImage image(file);
+ QImage thumbnail = image.scaledToWidth(256, Qt::SmoothTransformation);
+ m_image = QIcon(QPixmap::fromImage(thumbnail));
+ imageloaded = true;
+ }
+ return m_image;
+}
diff --git a/logic/screenshots/Screenshot.h b/logic/screenshots/Screenshot.h
new file mode 100644
index 00000000..815c0d47
--- /dev/null
+++ b/logic/screenshots/Screenshot.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <QDateTime>
+#include <QString>
+#include <memory>
+#include <QIcon>
+
+struct ScreenShot
+{
+ QIcon getImage();
+ QIcon m_image;
+ bool imageloaded = false;
+ QDateTime timestamp;
+ QString file;
+ QString url;
+ QString imgurId;
+};
+
+typedef std::shared_ptr<ScreenShot> ScreenshotPtr;
diff --git a/logic/screenshots/ScreenshotList.cpp b/logic/screenshots/ScreenshotList.cpp
new file mode 100644
index 00000000..8a64dc36
--- /dev/null
+++ b/logic/screenshots/ScreenshotList.cpp
@@ -0,0 +1,113 @@
+#include "ScreenshotList.h"
+#include "gui/dialogs/ScreenshotDialog.h"
+
+#include <QDir>
+#include <QIcon>
+#include <QList>
+#include "gui/dialogs/ProgressDialog.h"
+#include "gui/dialogs/CustomMessageBox.h"
+
+ScreenshotList::ScreenshotList(BaseInstance *instance, QObject *parent)
+ : QAbstractListModel(parent), m_instance(instance)
+{
+}
+
+int ScreenshotList::rowCount(const QModelIndex &) const
+{
+ return m_screenshots.size();
+}
+
+QVariant ScreenshotList::data(const QModelIndex &index, int role) const
+{
+ if (index.row() >= m_screenshots.size() || index.row() < 0)
+ return QVariant();
+
+ switch (role)
+ {
+ case Qt::DecorationRole:
+ return m_screenshots.at(index.row())->getImage();
+ case Qt::DisplayRole:
+ return m_screenshots.at(index.row())->timestamp.toString("yyyy-MM-dd HH:mm:ss");
+ case Qt::ToolTipRole:
+ return m_screenshots.at(index.row())->timestamp.toString("yyyy-MM-dd HH:mm:ss");
+ case Qt::TextAlignmentRole:
+ return (int)(Qt::AlignHCenter | Qt::AlignVCenter);
+ default:
+ return QVariant();
+ }
+}
+
+QVariant ScreenshotList::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ return QVariant();
+}
+
+Qt::ItemFlags ScreenshotList::flags(const QModelIndex &index) const
+{
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+}
+
+Task *ScreenshotList::load()
+{
+ return new ScreenshotLoadTask(this);
+}
+
+ScreenshotLoadTask::ScreenshotLoadTask(ScreenshotList *list) : m_list(list)
+{
+}
+
+ScreenshotLoadTask::~ScreenshotLoadTask()
+{
+}
+
+void ScreenshotLoadTask::executeTask()
+{
+ auto dir = QDir(m_list->instance()->minecraftRoot());
+ if (!dir.cd("screenshots"))
+ {
+ emitFailed("Selected instance does not have any screenshots!");
+ return;
+ }
+ dir.setNameFilters(QStringList() << "*.png");
+ this->m_results.clear();
+ for (auto file : dir.entryList())
+ {
+ ScreenShot *shot = new ScreenShot();
+ shot->timestamp = QDateTime::fromString(file, "yyyy-MM-dd_HH.mm.ss.png");
+ shot->file = dir.absoluteFilePath(file);
+ m_results.append(ScreenshotPtr(shot));
+ }
+ m_list->loadShots(m_results);
+ emitSucceeded();
+}
+
+void ScreenshotList::deleteSelected(ScreenshotDialog *dialog)
+{
+ auto screens = dialog->selected();
+ if (screens.isEmpty())
+ {
+ return;
+ }
+ beginResetModel();
+ QList<std::shared_ptr<ScreenShot>>::const_iterator it;
+ for (it = screens.cbegin(); it != screens.cend(); it++)
+ {
+ auto shot = *it;
+ if (!QFile(shot->file).remove())
+ {
+ CustomMessageBox::selectable(dialog, tr("Error!"),
+ tr("Failed to delete screenshots!"),
+ QMessageBox::Warning)->exec();
+ break;
+ }
+ }
+ ProgressDialog refresh(dialog);
+ Task *t = load();
+ if (refresh.exec(t) != QDialog::Accepted)
+ {
+ CustomMessageBox::selectable(dialog, tr("Error!"),
+ tr("Unable to refresh list: %1").arg(t->failReason()),
+ QMessageBox::Warning)->exec();
+ }
+ endResetModel();
+}
diff --git a/logic/screenshots/ScreenshotList.h b/logic/screenshots/ScreenshotList.h
new file mode 100644
index 00000000..ca6314e9
--- /dev/null
+++ b/logic/screenshots/ScreenshotList.h
@@ -0,0 +1,70 @@
+#pragma once
+
+#include <QAbstractListModel>
+#include "logic/BaseInstance.h"
+#include "logic/tasks/Task.h"
+
+#include "Screenshot.h"
+
+class ScreenshotList : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ ScreenshotList(BaseInstance *instance, QObject *parent = 0);
+
+ QVariant data(const QModelIndex &index, int role) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+
+ int rowCount(const QModelIndex &parent) const;
+
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ Task *load();
+
+ void loadShots(QList<ScreenshotPtr> shots)
+ {
+ m_screenshots = shots;
+ }
+
+ QList<ScreenshotPtr> screenshots() const
+ {
+ return m_screenshots;
+ }
+
+ BaseInstance *instance() const
+ {
+ return m_instance;
+ }
+
+ void deleteSelected(class ScreenshotDialog *dialog);
+
+signals:
+
+public
+slots:
+
+private:
+ QList<ScreenshotPtr> m_screenshots;
+ BaseInstance *m_instance;
+};
+
+class ScreenshotLoadTask : public Task
+{
+ Q_OBJECT
+
+public:
+ explicit ScreenshotLoadTask(ScreenshotList *list);
+ ~ScreenshotLoadTask();
+
+ QList<ScreenshotPtr> screenShots() const
+ {
+ return m_results;
+ }
+
+protected:
+ virtual void executeTask();
+
+private:
+ ScreenshotList *m_list;
+ QList<ScreenshotPtr> m_results;
+};
diff --git a/logic/tasks/SequentialTask.cpp b/logic/tasks/SequentialTask.cpp
index 63025eee..e0f8fcdd 100644
--- a/logic/tasks/SequentialTask.cpp
+++ b/logic/tasks/SequentialTask.cpp
@@ -28,7 +28,7 @@ void SequentialTask::getProgress(qint64 &current, qint64 &total)
}
}
-void SequentialTask::addTask(std::shared_ptr<Task> task)
+void SequentialTask::addTask(std::shared_ptr<ProgressProvider> task)
{
m_queue.append(task);
}
@@ -43,7 +43,7 @@ void SequentialTask::startNext()
{
if (m_currentIndex != -1)
{
- std::shared_ptr<Task> previous = m_queue[m_currentIndex];
+ std::shared_ptr<ProgressProvider> previous = m_queue[m_currentIndex];
disconnect(previous.get(), 0, this, 0);
}
m_currentIndex++;
@@ -52,7 +52,7 @@ void SequentialTask::startNext()
emitSucceeded();
return;
}
- std::shared_ptr<Task> next = m_queue[m_currentIndex];
+ std::shared_ptr<ProgressProvider> next = m_queue[m_currentIndex];
connect(next.get(), SIGNAL(failed(QString)), this, SLOT(subTaskFailed(QString)));
connect(next.get(), SIGNAL(status(QString)), this, SLOT(subTaskStatus(QString)));
connect(next.get(), SIGNAL(progress(qint64,qint64)), this, SLOT(subTaskProgress()));
@@ -73,5 +73,12 @@ void SequentialTask::subTaskProgress()
{
qint64 current, total;
getProgress(current, total);
- setProgress(100 * current / total);
+ if (total == 0)
+ {
+ setProgress(0);
+ }
+ else
+ {
+ setProgress(100 * current / total);
+ }
}
diff --git a/logic/tasks/SequentialTask.h b/logic/tasks/SequentialTask.h
index 7f046928..c405dca3 100644
--- a/logic/tasks/SequentialTask.h
+++ b/logic/tasks/SequentialTask.h
@@ -14,7 +14,7 @@ public:
virtual QString getStatus() const;
virtual void getProgress(qint64 &current, qint64 &total);
- void addTask(std::shared_ptr<Task> task);
+ void addTask(std::shared_ptr<ProgressProvider> task);
protected:
void executeTask();
@@ -27,6 +27,6 @@ slots:
void subTaskProgress();
private:
- QQueue<std::shared_ptr<Task> > m_queue;
+ QQueue<std::shared_ptr<ProgressProvider> > m_queue;
int m_currentIndex;
};