aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml7
-rw-r--r--.gitignore2
-rw-r--r--CMakeLists.txt6
-rw-r--r--buildconfig/BuildConfig.cpp.in1
-rw-r--r--buildconfig/BuildConfig.h12
-rw-r--r--cmake/BundleUtilities.cmake786
-rw-r--r--cmake/GetPrerequisites.cmake902
-rw-r--r--cmake/MacOSXBundleInfo.plist.in8
-rw-r--r--cmake/UseJava.cmake881
-rw-r--r--cmake/UseJavaClassFilelist.cmake52
-rw-r--r--cmake/UseJavaSymlinks.cmake32
-rw-r--r--launcher/InstanceList.cpp11
-rw-r--r--launcher/LaunchController.cpp2
-rw-r--r--launcher/icons/IconList.cpp24
-rw-r--r--launcher/minecraft/MinecraftInstance.cpp7
-rw-r--r--launcher/minecraft/launch/LauncherPartLaunch.cpp6
-rw-r--r--launcher/modplatform/flame/FileResolvingTask.cpp34
-rw-r--r--launcher/modplatform/flame/FlameAPI.h32
-rw-r--r--launcher/modplatform/flame/FlameModIndex.cpp52
-rw-r--r--launcher/modplatform/flame/FlamePackIndex.cpp52
-rw-r--r--launcher/modplatform/flame/PackManifest.cpp87
-rw-r--r--launcher/net/Download.cpp112
-rw-r--r--launcher/ui/MainWindow.cpp48
-rw-r--r--launcher/ui/dialogs/SkinUploadDialog.cpp3
-rw-r--r--launcher/ui/pages/instance/InstanceSettingsPage.cpp19
-rw-r--r--launcher/ui/pages/instance/InstanceSettingsPage.ui29
-rw-r--r--launcher/ui/pages/instance/ScreenshotsPage.cpp27
-rw-r--r--launcher/ui/pages/instance/ScreenshotsPage.h1
-rw-r--r--launcher/ui/pages/modplatform/ImportPage.cpp3
-rw-r--r--launcher/ui/pages/modplatform/ModModel.cpp49
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModModel.cpp4
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModel.cpp129
-rw-r--r--launcher/ui/pages/modplatform/flame/FlamePage.cpp71
-rw-r--r--program_info/App.entitlements14
34 files changed, 437 insertions, 3068 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 1ede3f74..b387f46a 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -25,6 +25,13 @@ body:
- Other
- type: textarea
attributes:
+ label: Version of PolyMC
+ description: The version of PolyMC used in the bug report.
+ placeholder: PolyMC 1.2.2
+ validations:
+ required: true
+- type: textarea
+ attributes:
label: Description of bug
description: What did you expect to happen, what happened, and why is it incorrect?
placeholder: The cat button should show a cat, but it showed a dog instead!
diff --git a/.gitignore b/.gitignore
index c9a762f5..2a715656 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,8 @@ CMakeLists.txt.user.*
/.project
/.settings
/.idea
+/.vscode
+.clang-format
cmake-build-*/
Debug
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a7824a99..4d3683d7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -69,7 +69,7 @@ set(Launcher_HELP_URL "https://polymc.org/wiki/help-pages/%1" CACHE STRING "URL
######## Set version numbers ########
set(Launcher_VERSION_MAJOR 1)
set(Launcher_VERSION_MINOR 2)
-set(Launcher_VERSION_HOTFIX 1)
+set(Launcher_VERSION_HOTFIX 2)
# Build number
set(Launcher_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
@@ -89,6 +89,10 @@ set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can g
# MSA Client ID
set(Launcher_MSA_CLIENT_ID "549033b2-1532-4d4e-ae77-1bbaa46f9d74" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application")
+# CurseForge API Key
+# CHANGE THIS IF YOU FORK THIS PROJECT!
+set(Launcher_CURSEFORGE_API_KEY "$2a$10$1Oqr2MX3O4n/ilhFGc597u8tfI3L2Hyr9/rtWDAMRjghSQV2QUuxq" CACHE STRING "CurseForge API Key")
+
# Bug tracker URL
set(Launcher_BUG_TRACKER_URL "https://github.com/PolyMC/PolyMC/issues" CACHE STRING "URL for the bug tracker.")
diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in
index 7360d964..70f8f7f0 100644
--- a/buildconfig/BuildConfig.cpp.in
+++ b/buildconfig/BuildConfig.cpp.in
@@ -90,6 +90,7 @@ Config::Config()
HELP_URL = "@Launcher_HELP_URL@";
IMGUR_CLIENT_ID = "@Launcher_IMGUR_CLIENT_ID@";
MSA_CLIENT_ID = "@Launcher_MSA_CLIENT_ID@";
+ CURSEFORGE_API_KEY = "@Launcher_CURSEFORGE_API_KEY@";
META_URL = "@Launcher_META_URL@";
BUG_TRACKER_URL = "@Launcher_BUG_TRACKER_URL@";
diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h
index c1d34708..a920a3d4 100644
--- a/buildconfig/BuildConfig.h
+++ b/buildconfig/BuildConfig.h
@@ -40,9 +40,8 @@
/**
* \brief The Config class holds all the build-time information passed from the build system.
*/
-class Config
-{
-public:
+class Config {
+ public:
Config();
QString LAUNCHER_NAME;
QString LAUNCHER_DISPLAYNAME;
@@ -75,7 +74,6 @@ public:
/// URL for the updater's channel
QString UPDATER_BASE;
-
/// User-Agent to use.
QString USER_AGENT;
@@ -118,6 +116,11 @@ public:
QString MSA_CLIENT_ID;
/**
+ * Client API key for CurseForge
+ */
+ QString CURSEFORGE_API_KEY;
+
+ /**
* Metadata repository URL prefix
*/
QString META_URL;
@@ -156,4 +159,3 @@ public:
};
extern const Config BuildConfig;
-
diff --git a/cmake/BundleUtilities.cmake b/cmake/BundleUtilities.cmake
deleted file mode 100644
index e3f50b94..00000000
--- a/cmake/BundleUtilities.cmake
+++ /dev/null
@@ -1,786 +0,0 @@
-# - Functions to help assemble a standalone bundle application.
-# A collection of CMake utility functions useful for dealing with .app
-# bundles on the Mac and bundle-like directories on any OS.
-#
-# The following functions are provided by this module:
-# fixup_bundle
-# copy_and_fixup_bundle
-# verify_app
-# get_bundle_main_executable
-# get_dotapp_dir
-# get_bundle_and_executable
-# get_bundle_all_executables
-# get_item_key
-# clear_bundle_keys
-# set_bundle_key_values
-# get_bundle_keys
-# copy_resolved_item_into_bundle
-# copy_resolved_framework_into_bundle
-# fixup_bundle_item
-# verify_bundle_prerequisites
-# verify_bundle_symlinks
-# Requires CMake 2.6 or greater because it uses function, break and
-# PARENT_SCOPE. Also depends on GetPrerequisites.cmake.
-#
-# FIXUP_BUNDLE(<app> <libs> <dirs>)
-# Fix up a bundle in-place and make it standalone, such that it can be
-# drag-n-drop copied to another machine and run on that machine as long as all
-# of the system libraries are compatible.
-#
-# If you pass plugins to fixup_bundle as the libs parameter, you should install
-# them or copy them into the bundle before calling fixup_bundle. The "libs"
-# parameter is a list of libraries that must be fixed up, but that cannot be
-# determined by otool output analysis. (i.e., plugins)
-#
-# Gather all the keys for all the executables and libraries in a bundle, and
-# then, for each key, copy each prerequisite into the bundle. Then fix each one
-# up according to its own list of prerequisites.
-#
-# Then clear all the keys and call verify_app on the final bundle to ensure
-# that it is truly standalone.
-#
-# COPY_AND_FIXUP_BUNDLE(<src> <dst> <libs> <dirs>)
-# Makes a copy of the bundle <src> at location <dst> and then fixes up the
-# new copied bundle in-place at <dst>...
-#
-# VERIFY_APP(<app>)
-# Verifies that an application <app> appears valid based on running analysis
-# tools on it. Calls "message(FATAL_ERROR" if the application is not verified.
-#
-# GET_BUNDLE_MAIN_EXECUTABLE(<bundle> <result_var>)
-# The result will be the full path name of the bundle's main executable file
-# or an "error:" prefixed string if it could not be determined.
-#
-# GET_DOTAPP_DIR(<exe> <dotapp_dir_var>)
-# Returns the nearest parent dir whose name ends with ".app" given the full
-# path to an executable. If there is no such parent dir, then simply return
-# the dir containing the executable.
-#
-# The returned directory may or may not exist.
-#
-# GET_BUNDLE_AND_EXECUTABLE(<app> <bundle_var> <executable_var> <valid_var>)
-# Takes either a ".app" directory name or the name of an executable
-# nested inside a ".app" directory and returns the path to the ".app"
-# directory in <bundle_var> and the path to its main executable in
-# <executable_var>
-#
-# GET_BUNDLE_ALL_EXECUTABLES(<bundle> <exes_var>)
-# Scans the given bundle recursively for all executable files and accumulates
-# them into a variable.
-#
-# GET_ITEM_KEY(<item> <key_var>)
-# Given a file (item) name, generate a key that should be unique considering
-# the set of libraries that need copying or fixing up to make a bundle
-# standalone. This is essentially the file name including extension with "."
-# replaced by "_"
-#
-# This key is used as a prefix for CMake variables so that we can associate a
-# set of variables with a given item based on its key.
-#
-# CLEAR_BUNDLE_KEYS(<keys_var>)
-# Loop over the list of keys, clearing all the variables associated with each
-# key. After the loop, clear the list of keys itself.
-#
-# Caller of get_bundle_keys should call clear_bundle_keys when done with list
-# of keys.
-#
-# SET_BUNDLE_KEY_VALUES(<keys_var> <context> <item> <exepath> <dirs>
-# <copyflag>)
-# Add a key to the list (if necessary) for the given item. If added,
-# also set all the variables associated with that key.
-#
-# GET_BUNDLE_KEYS(<app> <libs> <dirs> <keys_var>)
-# Loop over all the executable and library files within the bundle (and given
-# as extra <libs>) and accumulate a list of keys representing them. Set
-# values associated with each key such that we can loop over all of them and
-# copy prerequisite libs into the bundle and then do appropriate
-# install_name_tool fixups.
-#
-# COPY_RESOLVED_ITEM_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
-# Copy a resolved item into the bundle if necessary. Copy is not necessary if
-# the resolved_item is "the same as" the resolved_embedded_item.
-#
-# COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
-# Copy a resolved framework into the bundle if necessary. Copy is not necessary
-# if the resolved_item is "the same as" the resolved_embedded_item.
-#
-# By default, BU_COPY_FULL_FRAMEWORK_CONTENTS is not set. If you want full
-# frameworks embedded in your bundles, set BU_COPY_FULL_FRAMEWORK_CONTENTS to
-# ON before calling fixup_bundle. By default,
-# COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE copies the framework dylib itself plus
-# the framework Resources directory.
-#
-# FIXUP_BUNDLE_ITEM(<resolved_embedded_item> <exepath> <dirs>)
-# Get the direct/non-system prerequisites of the resolved embedded item. For
-# each prerequisite, change the way it is referenced to the value of the
-# _EMBEDDED_ITEM keyed variable for that prerequisite. (Most likely changing to
-# an "@executable_path" style reference.)
-#
-# This function requires that the resolved_embedded_item be "inside" the bundle
-# already. In other words, if you pass plugins to fixup_bundle as the libs
-# parameter, you should install them or copy them into the bundle before
-# calling fixup_bundle. The "libs" parameter is a list of libraries that must
-# be fixed up, but that cannot be determined by otool output analysis. (i.e.,
-# plugins)
-#
-# Also, change the id of the item being fixed up to its own _EMBEDDED_ITEM
-# value.
-#
-# Accumulate changes in a local variable and make *one* call to
-# install_name_tool at the end of the function with all the changes at once.
-#
-# If the BU_CHMOD_BUNDLE_ITEMS variable is set then bundle items will be
-# marked writable before install_name_tool tries to change them.
-#
-# VERIFY_BUNDLE_PREREQUISITES(<bundle> <result_var> <info_var>)
-# Verifies that the sum of all prerequisites of all files inside the bundle
-# are contained within the bundle or are "system" libraries, presumed to exist
-# everywhere.
-#
-# VERIFY_BUNDLE_SYMLINKS(<bundle> <result_var> <info_var>)
-# Verifies that any symlinks found in the bundle point to other files that are
-# already also in the bundle... Anything that points to an external file causes
-# this function to fail the verification.
-
-#=============================================================================
-# Copyright 2008-2009 Kitware, Inc.
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distribute this file outside of CMake, substitute the full
-# License text for the above reference.)
-
-# The functions defined in this file depend on the get_prerequisites function
-# (and possibly others) found in:
-#
-get_filename_component(BundleUtilities_cmake_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
-include("${BundleUtilities_cmake_dir}/GetPrerequisites.cmake")
-
-
-function(get_bundle_main_executable bundle result_var)
- set(result "error: '${bundle}/Contents/Info.plist' file does not exist")
-
- if(EXISTS "${bundle}/Contents/Info.plist")
- set(result "error: no CFBundleExecutable in '${bundle}/Contents/Info.plist' file")
- set(line_is_main_executable 0)
- set(bundle_executable "")
-
- # Read Info.plist as a list of lines:
- #
- set(eol_char "E")
- file(READ "${bundle}/Contents/Info.plist" info_plist)
- string(REGEX REPLACE ";" "\\\\;" info_plist "${info_plist}")
- string(REGEX REPLACE "\n" "${eol_char};" info_plist "${info_plist}")
-
- # Scan the lines for "<key>CFBundleExecutable</key>" - the line after that
- # is the name of the main executable.
- #
- foreach(line ${info_plist})
- if(line_is_main_executable)
- string(REGEX REPLACE "^.*<string>(.*)</string>.*$" "\\1" bundle_executable "${line}")
- break()
- endif()
-
- if(line MATCHES "^.*<key>CFBundleExecutable</key>.*$")
- set(line_is_main_executable 1)
- endif()
- endforeach()
-
- if(NOT "${bundle_executable}" STREQUAL "")
- if(EXISTS "${bundle}/Contents/MacOS/${bundle_executable}")
- set(result "${bundle}/Contents/MacOS/${bundle_executable}")
- else()
-
- # Ultimate goal:
- # If not in "Contents/MacOS" then scan the bundle for matching files. If
- # there is only one executable file that matches, then use it, otherwise
- # it's an error...
- #
- #file(GLOB_RECURSE file_list "${bundle}/${bundle_executable}")
-
- # But for now, pragmatically, it's an error. Expect the main executable
- # for the bundle to be in Contents/MacOS, it's an error if it's not:
- #
- set(result "error: '${bundle}/Contents/MacOS/${bundle_executable}' does not exist")
- endif()
- endif()
- else()
- #
- # More inclusive technique... (This one would work on Windows and Linux
- # too, if a developer followed the typical Mac bundle naming convention...)
- #
- # If there is no Info.plist file, try to find an executable with the same
- # base name as the .app directory:
- #
- endif()
-
- set(${result_var} "${result}" PARENT_SCOPE)
-endfunction()
-
-
-function(get_dotapp_dir exe dotapp_dir_var)
- set(s "${exe}")
-
- if(s MATCHES "^.*/.*\\.app/.*$")
- # If there is a ".app" parent directory,
- # ascend until we hit it:
- # (typical of a Mac bundle executable)
- #
- set(done 0)
- while(NOT ${done})
- get_filename_component(snamewe "${s}" NAME_WE)
- get_filename_component(sname "${s}" NAME)
- get_filename_component(sdir "${s}" PATH)
- set(s "${sdir}")
- if(sname MATCHES "\\.app$")
- set(done 1)
- set(dotapp_dir "${sdir}/${sname}")
- endif()
- endwhile()
- else()
- # Otherwise use a directory containing the exe
- # (typical of a non-bundle executable on Mac, Windows or Linux)
- #
- is_file_executable("${s}" is_executable)
- if(is_executable)
- get_filename_component(sdir "${s}" PATH)
- set(dotapp_dir "${sdir}")
- else()
- set(dotapp_dir "${s}")
- endif()
- endif()
-
-
- set(${dotapp_dir_var} "${dotapp_dir}" PARENT_SCOPE)
-endfunction()
-
-
-function(get_bundle_and_executable app bundle_var executable_var valid_var)
- set(valid 0)
-
- if(EXISTS "${app}")
- # Is it a directory ending in .app?
- if(IS_DIRECTORY "${app}")
- if(app MATCHES "\\.app$")
- get_bundle_main_executable("${app}" executable)
- if(EXISTS "${app}" AND EXISTS "${executable}")
- set(${bundle_var} "${app}" PARENT_SCOPE)
- set(${executable_var} "${executable}" PARENT_SCOPE)
- set(valid 1)
- #message(STATUS "info: handled .app directory case...")
- else()
- message(STATUS "warning: *NOT* handled - .app directory case...")
- endif()
- else()
- message(STATUS "warning: *NOT* handled - directory but not .app case...")
- endif()
- else()
- # Is it an executable file?
- is_file_executable("${app}" is_executable)
- if(is_executable)
- get_dotapp_dir("${app}" dotapp_dir)
- if(EXISTS "${dotapp_dir}")
- set(${bundle_var} "${dotapp_dir}" PARENT_SCOPE)
- set(${executable_var} "${app}" PARENT_SCOPE)
- set(valid 1)
- #message(STATUS "info: handled executable file in .app dir case...")
- else()
- get_filename_component(app_dir "${app}" PATH)
- set(${bundle_var} "${app_dir}" PARENT_SCOPE)
- set(${executable_var} "${app}" PARENT_SCOPE)
- set(valid 1)
- #message(STATUS "info: handled executable file in any dir case...")
- endif()
- else()
- message(STATUS "warning: *NOT* handled - not .app dir, not executable file...")
- endif()
- endif()
- else()
- message(STATUS "warning: *NOT* handled - directory/file ${app} does not exist...")
- endif()
-
- if(NOT valid)
- set(${bundle_var} "error: not a bundle" PARENT_SCOPE)
- set(${executable_var} "error: not a bundle" PARENT_SCOPE)
- endif()
-
- set(${valid_var} ${valid} PARENT_SCOPE)
-endfunction()
-
-
-function(get_bundle_all_executables bundle exes_var)
- set(exes "")
-
- file(GLOB_RECURSE file_list "${bundle}/*")
- foreach(f ${file_list})
- is_file_executable("${f}" is_executable)
- if(is_executable)
- set(exes ${exes} "${f}")
- endif()
- endforeach()
-
- set(${exes_var} "${exes}" PARENT_SCOPE)
-endfunction()
-
-
-function(get_item_key item key_var)
- get_filename_component(item_name "${item}" NAME)
- if(WIN32)
- string(TOLOWER "${item_name}" item_name)
- endif()
- string(REGEX REPLACE "\\." "_" ${key_var} "${item_name}")
- set(${key_var} ${${key_var}} PARENT_SCOPE)
-endfunction()
-
-
-function(clear_bundle_keys keys_var)
- foreach(key ${${keys_var}})
- set(${key}_ITEM PARENT_SCOPE)
- set(${key}_RESOLVED_ITEM PARENT_SCOPE)
- set(${key}_DEFAULT_EMBEDDED_PATH PARENT_SCOPE)
- set(${key}_EMBEDDED_ITEM PARENT_SCOPE)
- set(${key}_RESOLVED_EMBEDDED_ITEM PARENT_SCOPE)
- set(${key}_COPYFLAG PARENT_SCOPE)
- endforeach()
- set(${keys_var} PARENT_SCOPE)
-endfunction()
-
-
-function(set_bundle_key_values keys_var context item exepath dirs copyflag)
- get_filename_component(item_name "${item}" NAME)
-
- get_item_key("${item}" key)
-
- list(LENGTH ${keys_var} length_before)
- gp_append_unique(${keys_var} "${key}")
- list(LENGTH ${keys_var} length_after)
-
- if(NOT length_before EQUAL length_after)
- gp_resolve_item("${context}" "${item}" "${exepath}" "${dirs}" resolved_item)
-
- gp_item_default_embedded_path("${item}" default_embedded_path)
-
- if(item MATCHES "[^/]+\\.framework/")
- # For frameworks, construct the name under the embedded path from the
- # opening "${item_name}.framework/" to the closing "/${item_name}":
- #
- string(REGEX REPLACE "^.*(${item_name}.framework/.*/?${item_name}).*$" "${default_embedded_path}/\\1" embedded_item "${item}")
- else()
- # For other items, just use the same name as the original, but in the
- # embedded path:
- #
- set(embedded_item "${default_embedded_path}/${item_name}")
- endif()
-
- # Replace @executable_path and resolve ".." references:
- #
- string(REPLACE "@executable_path" "${exepath}" resolved_embedded_item "${embedded_item}")
- get_filename_component(resolved_embedded_item "${resolved_embedded_item}" ABSOLUTE)
-
- # *But* -- if we are not copying, then force resolved_embedded_item to be
- # the same as resolved_item. In the case of multiple executables in the
- # original bundle, using the default_embedded_path results in looking for
- # the resolved executable next to the main bundle executable. This is here
- # so that exes in the other sibling directories (like "bin") get fixed up
- # properly...
- #
- if(NOT copyflag)
- set(resolved_embedded_item "${resolved_item}")
- endif()
-
- set(${keys_var} ${${keys_var}} PARENT_SCOPE)
- set(${key}_ITEM "${item}" PARENT_SCOPE)
- set(${key}_RESOLVED_ITEM "${resolved_item}" PARENT_SCOPE)
- set(${key}_DEFAULT_EMBEDDED_PATH "${default_embedded_path}" PARENT_SCOPE)
- set(${key}_EMBEDDED_ITEM "${embedded_item}" PARENT_SCOPE)
- set(${key}_RESOLVED_EMBEDDED_ITEM "${resolved_embedded_item}" PARENT_SCOPE)
- set(${key}_COPYFLAG "${copyflag}" PARENT_SCOPE)
- else()
- #message("warning: item key '${key}' already in the list, subsequent references assumed identical to first")
- endif()
-endfunction()
-
-
-function(get_bundle_keys app libs dirs keys_var)
- set(${keys_var} PARENT_SCOPE)
-
- get_bundle_and_executable("${app}" bundle executable valid)
- if(valid)
- # Always use the exepath of the main bundle executable for @executable_path
- # replacements:
- #
- get_filename_component(exepath "${executable}" PATH)
-
- # But do fixups on all executables in the bundle:
- #
- get_bundle_all_executables("${bundle}" exes)
-
- # For each extra lib, accumulate a key as well and then also accumulate
- # any of its prerequisites. (Extra libs are typically dynamically loaded
- # plugins: libraries that are prerequisites for full runtime functionality
- # but that do not show up in otool -L output...)
- #
- foreach(lib ${libs})
- set_bundle_key_values(${keys_var} "${lib}" "${lib}" "${exepath}" "${dirs}" 0)
-
- set(prereqs "")
- get_prerequisites("${lib}" prereqs 1 1 "${exepath}" "${dirs}")
- foreach(pr ${prereqs})
- set_bundle_key_values(${keys_var} "${lib}" "${pr}" "${exepath}" "${dirs}" 1)
- endforeach()
- endforeach()
-
- # For each executable found in the bundle, accumulate keys as we go.
- # The list of keys should be complete when all prerequisites of all
- # binaries in the bundle have been analyzed.
- #
- foreach(exe ${exes})
- # Add the exe itself to the keys:
- #
- set_bundle_key_values(${keys_var} "${exe}" "${exe}" "${exepath}" "${dirs}" 0)
-
- # Add each prerequisite to the keys:
- #
- set(prereqs "")
- get_prerequisites("${exe}" prereqs 1 1 "${exepath}" "${dirs}")
- foreach(pr ${prereqs})
- set_bundle_key_values(${keys_var} "${exe}" "${pr}" "${exepath}" "${dirs}" 1)
- endforeach()
- endforeach()
-
- # Propagate values to caller's scope:
- #
- set(${keys_var} ${${keys_var}} PARENT_SCOPE)
- foreach(key ${${keys_var}})
- set(${key}_ITEM "${${key}_ITEM}" PARENT_SCOPE)
- set(${key}_RESOLVED_ITEM "${${key}_RESOLVED_ITEM}" PARENT_SCOPE)
- set(${key}_DEFAULT_EMBEDDED_PATH "${${key}_DEFAULT_EMBEDDED_PATH}" PARENT_SCOPE)
- set(${key}_EMBEDDED_ITEM "${${key}_EMBEDDED_ITEM}" PARENT_SCOPE)
- set(${key}_RESOLVED_EMBEDDED_ITEM "${${key}_RESOLVED_EMBEDDED_ITEM}" PARENT_SCOPE)
- set(${key}_COPYFLAG "${${key}_COPYFLAG}" PARENT_SCOPE)
- endforeach()
- endif()
-endfunction()
-
-
-function(copy_resolved_item_into_bundle resolved_item resolved_embedded_item)
- if(WIN32)
- # ignore case on Windows
- string(TOLOWER "${resolved_item}" resolved_item_compare)
- string(TOLOWER "${resolved_embedded_item}" resolved_embedded_item_compare)
- else()
- set(resolved_item_compare "${resolved_item}")
- set(resolved_embedded_item_compare "${resolved_embedded_item}")
- endif()
-
- if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}")
- message(STATUS "warning: resolved_item == resolved_embedded_item - not copying...")
- else()
- #message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy ${resolved_item} ${resolved_embedded_item}")
- execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${resolved_item}" "${resolved_embedded_item}")
- if(UNIX AND NOT APPLE)
- file(RPATH_REMOVE FILE "${resolved_embedded_item}")
- endif()
- endif()
-
-endfunction()
-
-
-function(copy_resolved_framework_into_bundle resolved_item resolved_embedded_item)
- if(WIN32)
- # ignore case on Windows
- string(TOLOWER "${resolved_item}" resolved_item_compare)
- string(TOLOWER "${resolved_embedded_item}" resolved_embedded_item_compare)
- else()
- set(resolved_item_compare "${resolved_item}")
- set(resolved_embedded_item_compare "${resolved_embedded_item}")
- endif()
-
- if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}")
- message(STATUS "warning: resolved_item == resolved_embedded_item - not copying...")
- else()
- if(BU_COPY_FULL_FRAMEWORK_CONTENTS)
- # Full Framework (everything):
- get_filename_component(resolved_dir "${resolved_item}" PATH)
- get_filename_component(resolved_dir "${resolved_dir}/../.." ABSOLUTE)
- get_filename_component(resolved_embedded_dir "${resolved_embedded_item}" PATH)
- get_filename_component(resolved_embedded_dir "${resolved_embedded_dir}/../.." ABSOLUTE)
- #message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy_directory '${resolved_dir}' '${resolved_embedded_dir}'")
- execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory "${resolved_dir}" "${resolved_embedded_dir}")
- else()
- # Framework lib itself:
- #message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy ${resolved_item} ${resolved_embedded_item}")
- execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${resolved_item}" "${resolved_embedded_item}")
-
- # Plus Resources, if they exist:
- string(REGEX REPLACE "^(.*)/[^/]+/[^/]+/[^/]+$" "\\1/Resources" resolved_resources "${resolved_item}")
- string(REGEX REPLACE "^(.*)/[^/]+/[^/]+/[^/]+$" "\\1/Resources" resolved_embedded_resources "${resolved_embedded_item}")
- if(EXISTS "${resolved_resources}")
- #message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy_directory '${resolved_resources}' '${resolved_embedded_resources}'")
- execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory "${resolved_resources}" "${resolved_embedded_resources}")
- endif()
- endif()
- if(UNIX AND NOT APPLE)
- file(RPATH_REMOVE FILE "${resolved_embedded_item}")
- endif()
- endif()
-
-endfunction()
-
-
-function(fixup_bundle_item resolved_embedded_item exepath dirs)
- # This item's key is "ikey":
- #
- get_item_key("${resolved_embedded_item}" ikey)
-
- # Ensure the item is "inside the .app bundle" -- it should not be fixed up if
- # it is not in the .app bundle... Otherwise, we'll modify files in the build
- # tree, or in other varied locations around the file system, with our call to
- # install_name_tool. Make sure that doesn't happen here:
- #
- get_dotapp_dir("${exepath}" exe_dotapp_dir)
- string(LENGTH "${exe_dotapp_dir}/" exe_dotapp_dir_length)
- string(LENGTH "${resolved_embedded_item}" resolved_embedded_item_length)
- set(path_too_short 0)
- set(is_embedded 0)
- if(${resolved_embedded_item_length} LESS ${exe_dotapp_dir_length})
- set(path_too_short 1)
- endif()
- if(NOT path_too_short)
- string(SUBSTRING "${resolved_embedded_item}" 0 ${exe_dotapp_dir_length} item_substring)
- if("${exe_dotapp_dir}/" STREQUAL "${item_substring}")
- set(is_embedded 1)
- endif()
- endif()
- if(NOT is_embedded)
- message(" exe_dotapp_dir/='${exe_dotapp_dir}/'")
- message(" item_substring='${item_substring}'")
- message(" resolved_embedded_item='${resolved_embedded_item}'")
- message("")
- message("Install or copy the item into the bundle before calling fixup_bundle.")
- message("Or maybe there's a typo or incorrect path in one of the args to fixup_bundle?")
- message("")
- message(FATAL_ERROR "cannot fixup an item that is not in the bundle...")
- endif()
-
- set(prereqs "")
- get_prerequisites("${resolved_embedded_item}" prereqs 1 0 "${exepath}" "${dirs}")
-
- set(changes "")
-
- foreach(pr ${prereqs})
- # Each referenced item's key is "rkey" in the loop:
- #
- get_item_key("${pr}" rkey)
-
- if(NOT "${${rkey}_EMBEDDED_ITEM}" STREQUAL "")
- set(changes ${changes} "-change" "${pr}" "${${rkey}_EMBEDDED_ITEM}")
- else()
- message("warning: unexpected reference to '${pr}'")
- endif()
- endforeach()
-
- if(BU_CHMOD_BUNDLE_ITEMS)
- execute_process(COMMAND chmod u+w "${resolved_embedded_item}")
- endif()
-
- # Change this item's id and all of its references in one call
- # to install_name_tool:
- #
- execute_process(COMMAND install_name_tool
- ${changes} -id "${${ikey}_EMBEDDED_ITEM}" "${resolved_embedded_item}"
- )
-endfunction()
-
-
-function(fixup_bundle app libs dirs)
- message(STATUS "fixup_bundle")
- message(STATUS " app='${app}'")
- message(STATUS " libs='${libs}'")
- message(STATUS " dirs='${dirs}'")
-
- get_bundle_and_executable("${app}" bundle executable valid)
- if(valid)
- get_filename_component(exepath "${executable}" PATH)
-
- message(STATUS "fixup_bundle: preparing...")
- get_bundle_keys("${app}" "${libs}" "${dirs}" keys)
-
- message(STATUS "fixup_bundle: copying...")
- list(LENGTH keys n)
- math(EXPR n ${n}*2)
-
- set(i 0)
- foreach(key ${keys})
- math(EXPR i ${i}+1)
- if(${${key}_COPYFLAG})
- message(STATUS "${i}/${n}: copying '${${key}_RESOLVED_ITEM}'")
- else()
- message(STATUS "${i}/${n}: *NOT* copying '${${key}_RESOLVED_ITEM}'")
- endif()
-
- set(show_status 0)
- if(show_status)
- message(STATUS "key='${key}'")
- message(STATUS "item='${${key}_ITEM}'")
- message(STATUS "resolved_item='${${key}_RESOLVED_ITEM}'")
- message(STATUS "default_embedded_path='${${key}_DEFAULT_EMBEDDED_PATH}'")
- message(STATUS "embedded_item='${${key}_EMBEDDED_ITEM}'")
- message(STATUS "resolved_embedded_item='${${key}_RESOLVED_EMBEDDED_ITEM}'")
- message(STATUS "copyflag='${${key}_COPYFLAG}'")
- message(STATUS "")
- endif()
-
- if(${${key}_COPYFLAG})
- set(item "${${key}_ITEM}")
- if(item MATCHES "[^/]+\\.framework/")
- copy_resolved_framework_into_bundle("${${key}_RESOLVED_ITEM}"
- "${${key}_RESOLVED_EMBEDDED_ITEM}")
- else()
- copy_resolved_item_into_bundle("${${key}_RESOLVED_ITEM}"
- "${${key}_RESOLVED_EMBEDDED_ITEM}")
- endif()
- endif()
- endforeach()
-
- message(STATUS "fixup_bundle: fixing...")
- foreach(key ${keys})
- math(EXPR i ${i}+1)
- if(APPLE)
- message(STATUS "${i}/${n}: fixing up '${${key}_RESOLVED_EMBEDDED_ITEM}'")
- fixup_bundle_item("${${key}_RESOLVED_EMBEDDED_ITEM}" "${exepath}" "${dirs}")
- else()
- message(STATUS "${i}/${n}: fix-up not required on this platform '${${key}_RESOLVED_EMBEDDED_ITEM}'")
- endif()
- endforeach()
-
- message(STATUS "fixup_bundle: cleaning up...")
- clear_bundle_keys(keys)
-
- message(STATUS "fixup_bundle: verifying...")
- verify_app("${app}")
- else()
- message(SEND_ERROR "error: fixup_bundle: not a valid bundle")
- endif()
-
- message(STATUS "fixup_bundle: done")
-endfunction()
-
-
-function(copy_and_fixup_bundle src dst libs dirs)
- execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory "${src}" "${dst}")
- fixup_bundle("${dst}" "${libs}" "${dirs}")
-endfunction()
-
-
-function(verify_bundle_prerequisites bundle result_var info_var)
- set(result 1)
- set(info "")
- set(count 0)
-
- get_bundle_main_executable("${bundle}" main_bundle_exe)
-
- file(GLOB_RECURSE file_list "${bundle}/*")
- foreach(f ${file_list})
- is_file_executable("${f}" is_executable)
- if(is_executable)
- get_filename_component(exepath "${f}" PATH)
- math(EXPR count "${count} + 1")
-
- message(STATUS "executable file ${count}: ${f}")
-
- set(prereqs "")
- get_prerequisites("${f}" prereqs 1 1 "${exepath}" "")
-
- # On the Mac,
- # "embedded" and "system" prerequisites are fine... anything else means
- # the bundle's prerequisites are not verified (i.e., the bundle is not
- # really "standalone")
- #
- # On Windows (and others? Linux/Unix/...?)
- # "local" and "system" prereqs are fine...
- #
- set(external_prereqs "")
-
- foreach(p ${prereqs})
- set(p_type "")
- gp_file_type("${f}" "${p}" p_type)
-
- if(APPLE)
- if(NOT "${p_type}" STREQUAL "embedded" AND NOT "${p_type}" STREQUAL "system")
- set(external_prereqs ${external_prereqs} "${p}")
- endif()
- else()
- if(NOT "${p_type}" STREQUAL "local" AND NOT "${p_type}" STREQUAL "system")
- set(external_prereqs ${external_prereqs} "${p}")
- endif()
- endif()
- endforeach()
-
- if(external_prereqs)
- # Found non-system/somehow-unacceptable prerequisites:
- set(result 0)
- set(info ${info} "external prerequisites found:\nf='${f}'\nexternal_prereqs='${external_prereqs}'\n")
- endif()
- endif()
- endforeach()
-
- if(result)
- set(info "Verified ${count} executable files in '${bundle}'")
- endif()
-
- set(${result_var} "${result}" PARENT_SCOPE)
- set(${info_var} "${info}" PARENT_SCOPE)
-endfunction()
-
-
-function(verify_bundle_symlinks bundle result_var info_var)
- set(result 1)
- set(info "")
- set(count 0)
-
- # TODO: implement this function for real...
- # Right now, it is just a stub that verifies unconditionally...
-
- set(${result_var} "${result}" PARENT_SCOPE)
- set(${info_var} "${info}" PARENT_SCOPE)
-endfunction()
-
-
-function(verify_app app)
- set(verified 0)
- set(info "")
-
- get_bundle_and_executable("${app}" bundle executable valid)
-
- message(STATUS "===========================================================================")
- message(STATUS "Analyzing app='${app}'")
- message(STATUS "bundle='${bundle}'")
- message(STATUS "executable='${executable}'")
- message(STATUS "valid='${valid}'")
-
- # Verify that the bundle does not have any "external" prerequisites:
- #
- verify_bundle_prerequisites("${bundle}" verified info)
- message(STATUS "verified='${verified}'")
- message(STATUS "info='${info}'")
- message(STATUS "")
-
- if(verified)
- # Verify that the bundle does not have any symlinks to external files:
- #
- verify_bundle_symlinks("${bundle}" verified info)
- message(STATUS "verified='${verified}'")
- message(STATUS "info='${info}'")
- message(STATUS "")
- endif()
-
- if(NOT verified)
- message(FATAL_ERROR "error: verify_app failed")
- endif()
-endfunction()
diff --git a/cmake/GetPrerequisites.cmake b/cmake/GetPrerequisites.cmake
deleted file mode 100644
index 39c2cc63..00000000
--- a/cmake/GetPrerequisites.cmake
+++ /dev/null
@@ -1,902 +0,0 @@
-# - Functions to analyze and list executable file prerequisites.
-# This module provides functions to list the .dll, .dylib or .so
-# files that an executable or shared library file depends on. (Its
-# prerequisites.)
-#
-# It uses various tools to obtain the list of required shared library files:
-# dumpbin (Windows)
-# objdump (MinGW on Windows)
-# ldd (Linux/Unix)
-# otool (Mac OSX)
-# The following functions are provided by this module:
-# get_prerequisites
-# list_prerequisites
-# list_prerequisites_by_glob
-# gp_append_unique
-# is_file_executable
-# gp_item_default_embedded_path
-# (projects can override with gp_item_default_embedded_path_override)
-# gp_resolve_item
-# (projects can override with gp_resolve_item_override)
-# gp_resolved_file_type
-# (projects can override with gp_resolved_file_type_override)
-# gp_file_type
-# Requires CMake 2.6 or greater because it uses function, break, return and
-# PARENT_SCOPE.
-#
-# GET_PREREQUISITES(<target> <prerequisites_var> <exclude_system> <recurse>
-# <exepath> <dirs>)
-# Get the list of shared library files required by <target>. The list in
-# the variable named <prerequisites_var> should be empty on first entry to
-# this function. On exit, <prerequisites_var> will contain the list of
-# required shared library files.
-#
-# <target> is the full path to an executable file. <prerequisites_var> is the
-# name of a CMake variable to contain the results. <exclude_system> must be 0
-# or 1 indicating whether to include or exclude "system" prerequisites. If
-# <recurse> is set to 1 all prerequisites will be found recursively, if set to
-# 0 only direct prerequisites are listed. <exepath> is the path to the top
-# level executable used for @executable_path replacment on the Mac. <dirs> is
-# a list of paths where libraries might be found: these paths are searched
-# first when a target without any path info is given. Then standard system
-# locations are also searched: PATH, Framework locations, /usr/lib...
-#
-# LIST_PREREQUISITES(<target> [<recurse> [<exclude_system> [<verbose>]]])
-# Print a message listing the prerequisites of <target>.
-#
-# <target> is the name of a shared library or executable target or the full
-# path to a shared library or executable file. If <recurse> is set to 1 all
-# prerequisites will be found recursively, if set to 0 only direct
-# prerequisites are listed. <exclude_system> must be 0 or 1 indicating whether
-# to include or exclude "system" prerequisites. With <verbose> set to 0 only
-# the full path names of the prerequisites are printed, set to 1 extra
-# informatin will be displayed.
-#
-# LIST_PREREQUISITES_BY_GLOB(<glob_arg> <glob_exp>)
-# Print the prerequisites of shared library and executable files matching a
-# globbing pattern. <glob_arg> is GLOB or GLOB_RECURSE and <glob_exp> is a
-# globbing expression used with "file(GLOB" or "file(GLOB_RECURSE" to retrieve
-# a list of matching files. If a matching file is executable, its prerequisites
-# are listed.
-#
-# Any additional (optional) arguments provided are passed along as the
-# optional arguments to the list_prerequisites calls.
-#
-# GP_APPEND_UNIQUE(<list_var> <value>)
-# Append <value> to the list variable <list_var> only if the value is not
-# already in the list.
-#
-# IS_FILE_EXECUTABLE(<file> <result_var>)
-# Return 1 in <result_var> if <file> is a binary executable, 0 otherwise.
-#
-# GP_ITEM_DEFAULT_EMBEDDED_PATH(<item> <default_embedded_path_var>)
-# Return the path that others should refer to the item by when the item
-# is embedded inside a bundle.
-#
-# Override on a per-project basis by providing a project-specific
-# gp_item_default_embedded_path_override function.
-#
-# GP_RESOLVE_ITEM(<context> <item> <exepath> <dirs> <resolved_item_var>)
-# Resolve an item into an existing full path file.
-#
-# Override on a per-project basis by providing a project-specific
-# gp_resolve_item_override function.
-#
-# GP_RESOLVED_FILE_TYPE(<original_file> <file> <exepath> <dirs> <type_var>)
-# Return the type of <file> with respect to <original_file>. String
-# describing type of prerequisite is returned in variable named <type_var>.
-#
-# Use <exepath> and <dirs> if necessary to resolve non-absolute <file>
-# values -- but only for non-embedded items.
-#
-# Possible types are:
-# system
-# local
-# embedded
-# other
-# Override on a per-project basis by providing a project-specific
-# gp_resolved_file_type_override function.
-#
-# GP_FILE_TYPE(<original_file> <file> <type_var>)
-# Return the type of <file> with respect to <original_file>. String
-# describing type of prerequisite is returned in variable named <type_var>.
-#
-# Possible types are:
-# system
-# local
-# embedded
-# other
-
-#=============================================================================
-# Copyright 2008-2009 Kitware, Inc.
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distribute this file outside of CMake, substitute the full
-# License text for the above reference.)
-
-function(gp_append_unique list_var value)
- set(contains 0)
-
- foreach(item ${${list_var}})
- if("${item}" STREQUAL "${value}")
- set(contains 1)
- break()
- endif()
- endforeach()
-
- if(NOT contains)
- set(${list_var} ${${list_var}} "${value}" PARENT_SCOPE)
- endif()
-endfunction()
-
-
-function(is_file_executable file result_var)
- #
- # A file is not executable until proven otherwise:
- #
- set(${result_var} 0 PARENT_SCOPE)
-
- get_filename_component(file_full "${file}" ABSOLUTE)
- string(TOLOWER "${file_full}" file_full_lower)
-
- # If file name ends in .exe on Windows, *assume* executable:
- #
- if(WIN32 AND NOT UNIX)
- if("${file_full_lower}" MATCHES "\\.exe$")
- set(${result_var} 1 PARENT_SCOPE)
- return()
- endif()
-
- # A clause could be added here that uses output or return value of dumpbin
- # to determine ${result_var}. In 99%+? practical cases, the exe name
- # match will be sufficient...
- #
- endif()
-
- # Use the information returned from the Unix shell command "file" to
- # determine if ${file_full} should be considered an executable file...
- #
- # If the file command's output contains "executable" and does *not* contain
- # "text" then it is likely an executable suitable for prerequisite analysis
- # via the get_prerequisites macro.
- #
- if(UNIX)
- if(NOT file_cmd)
- find_program(file_cmd "file")
- mark_as_advanced(file_cmd)
- endif()
-
- if(file_cmd)
- execute_process(COMMAND "${file_cmd}" "${file_full}"
- OUTPUT_VARIABLE file_ov
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
-
- # Replace the name of the file in the output with a placeholder token
- # (the string " _file_full_ ") so that just in case the path name of
- # the file contains the word "text" or "executable" we are not fooled
- # into thinking "the wrong thing" because the file name matches the
- # other 'file' command output we are looking for...
- #
- string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}")
- string(TOLOWER "${file_ov}" file_ov)
-
- #message(STATUS "file_ov='${file_ov}'")
- if("${file_ov}" MATCHES "executable")
- #message(STATUS "executable!")
- if("${file_ov}" MATCHES "text")
- #message(STATUS "but text, so *not* a binary executable!")
- else()
- set(${result_var} 1 PARENT_SCOPE)
- return()
- endif()
- endif()
-
- # Also detect position independent executables on Linux,
- # where "file" gives "shared object ... (uses shared libraries)"
- if("${file_ov}" MATCHES "shared object.*\(uses shared libs\)")
- set(${result_var} 1 PARENT_SCOPE)
- return()
- endif()
-
- # "file" version 5.22 does not print "(used shared libraries)"
- # but uses "interpreter"
- if("${file_ov}" MATCHES "shared object.*interpreter")
- set(${result_var} 1 PARENT_SCOPE)
- return()
- endif()
-
- else()
- message(STATUS "warning: No 'file' command, skipping execute_process...")
- endif()
- endif()
-endfunction()
-
-
-function(gp_item_default_embedded_path item default_embedded_path_var)
-
- # On Windows and Linux, "embed" prerequisites in the same directory
- # as the executable by default:
- #
- set(path "@executable_path")
- set(overridden 0)
-
- # On the Mac, relative to the executable depending on the type
- # of the thing we are embedding:
- #
- if(APPLE)
- #
- # The assumption here is that all executables in the bundle will be
- # in same-level-directories inside the bundle. The parent directory
- # of an executable inside the bundle should be MacOS or a sibling of
- # MacOS and all embedded paths returned from here will begin with
- # "@executable_path/../" and will work from all executables in all
- # such same-level-directories inside the bundle.
- #
-
- # By default, embed things right next to the main bundle executable:
- #
- set(path "@executable_path/../../Contents/MacOS")
-
- # Embed .dylibs right next to the main bundle executable:
- #
- if(item MATCHES "\\.dylib$")
- set(path "@executable_path/../MacOS")
- set(overridden 1)
- endif()
-
- # Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS):
- #
- if(NOT overridden)
- if(item MATCHES "[^/]+\\.framework/")
- set(path "@executable_path/../Frameworks")
- set(overridden 1)
- endif()
- endif()
- endif()
-
- # Provide a hook so that projects can override the default embedded location
- # of any given library by whatever logic they choose:
- #
- if(COMMAND gp_item_default_embedded_path_override)
- gp_item_default_embedded_path_override("${item}" path)
- endif()
-
- set(${default_embedded_path_var} "${path}" PARENT_SCOPE)
-endfunction()
-
-
-function(gp_resolve_item context item exepath dirs resolved_item_var)
- set(resolved 0)
- set(resolved_item "${item}")
-
- # Is it already resolved?
- #
- if(IS_ABSOLUTE "${resolved_item}" AND EXISTS "${resolved_item}")
- set(resolved 1)
- endif()
-
- if(NOT resolved)
- if(item MATCHES "@executable_path")
- #
- # @executable_path references are assumed relative to exepath
- #
- string(REPLACE "@executable_path" "${exepath}" ri "${item}")
- get_filename_component(ri "${ri}" ABSOLUTE)
-
- if(EXISTS "${ri}")
- #message(STATUS "info: embedded item exists (${ri})")
- set(resolved 1)
- set(resolved_item "${ri}")
- else()
- message(STATUS "warning: embedded item does not exist '${ri}'")
- endif()
- endif()
- endif()
-
- if(NOT resolved)
- if(item MATCHES "@loader_path")
- #
- # @loader_path references are assumed relative to the
- # PATH of the given "context" (presumably another library)
- #
- get_filename_component(contextpath "${context}" PATH)
- string(REPLACE "@loader_path" "${contextpath}" ri "${item}")
- get_filename_component(ri "${ri}" ABSOLUTE)
-
- if(EXISTS "${ri}")
- #message(STATUS "info: embedded item exists (${ri})")
- set(resolved 1)
- set(resolved_item "${ri}")
- else()
- message(STATUS "warning: embedded item does not exist '${ri}'")
- endif()
- endif()
- endif()
-
- if(NOT resolved)
- if(item MATCHES "@rpath")
- #
- # @rpath references are relative to the paths built into the binaries with -rpath
- # We handle this case like we do for other Unixes
- #
- string(REPLACE "@rpath/" "" norpath_item "${item}")
-
- set(ri "ri-NOTFOUND")
- find_file(ri "${norpath_item}" ${exepath} ${dirs} NO_DEFAULT_PATH)
- if(ri)
- #message(STATUS "info: 'find_file' in exepath/dirs (${ri})")
- set(resolved 1)
- set(resolved_item "${ri}")
- set(ri "ri-NOTFOUND")
- endif()
-
- endif()
- endif()
-
- if(NOT resolved)
- set(ri "ri-NOTFOUND")
- find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH)
- find_file(ri "${item}" ${exepath} ${dirs} /usr/lib)
- if(ri)
- #message(STATUS "info: 'find_file' in exepath/dirs (${ri})")
- set(resolved 1)
- set(resolved_item "${ri}")
- set(ri "ri-NOTFOUND")
- endif()
- endif()
-
- if(NOT resolved)
- if(item MATCHES "[^/]+\\.framework/")
- set(fw "fw-NOTFOUND")
- find_file(fw "${item}"
- "~/Library/Frameworks"
- "/Library/Frameworks"
- "/System/Library/Frameworks"
- )
- if(fw)
- #message(STATUS "info: 'find_file' found framework (${fw})")
- set(resolved 1)
- set(resolved_item "${fw}")
- set(fw "fw-NOTFOUND")
- endif()
- endif()
- endif()
-
- # Using find_program on Windows will find dll files that are in the PATH.
- # (Converting simple file names into full path names if found.)
- #
- if(WIN32 AND NOT UNIX)
- if(NOT resolved)
- set(ri "ri-NOTFOUND")
- find_program(ri "${item}" PATHS "${exepath};${dirs}" NO_DEFAULT_PATH)
- find_program(ri "${item}" PATHS "${exepath};${dirs}")
- if(ri)
- #message(STATUS "info: 'find_program' in exepath/dirs (${ri})")
- set(resolved 1)
- set(resolved_item "${ri}")
- set(ri "ri-NOTFOUND")
- endif()
- endif()
- endif()
-
- # Provide a hook so that projects can override item resolution
- # by whatever logic they choose:
- #
- if(COMMAND gp_resolve_item_override)
- gp_resolve_item_override("${context}" "${item}" "${exepath}" "${dirs}" resolved_item resolved)
- endif()
-
- if(NOT resolved)
- message(STATUS "
-warning: cannot resolve item '${item}'
-
- possible problems:
- need more directories?
- need to use InstallRequiredSystemLibraries?
- run in install tree instead of build tree?
-")
-# message(STATUS "
-#******************************************************************************
-#warning: cannot resolve item '${item}'
-#
-# possible problems:
-# need more directories?
-# need to use InstallRequiredSystemLibraries?
-# run in install tree instead of build tree?
-#
-# context='${context}'
-# item='${item}'
-# exepath='${exepath}'
-# dirs='${dirs}'
-# resolved_item_var='${resolved_item_var}'
-#******************************************************************************
-#")
- endif()
-
- set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE)
-endfunction()
-
-
-function(gp_resolved_file_type original_file file exepath dirs type_var)
- #message(STATUS "**")
-
- if(NOT IS_ABSOLUTE "${original_file}")
- message(STATUS "warning: gp_resolved_file_type expects absolute full path for first arg original_file")
- endif()
-
- set(is_embedded 0)
- set(is_local 0)
- set(is_system 0)
-
- set(resolved_file "${file}")
-
- if("${file}" MATCHES "^@(executable|loader)_path")
- set(is_embedded 1)
- endif()
-
- if(NOT is_embedded)
- if(NOT IS_ABSOLUTE "${file}")
- gp_resolve_item("${original_file}" "${file}" "${exepath}" "${dirs}" resolved_file)
- endif()
-
- string(TOLOWER "${original_file}" original_lower)
- string(TOLOWER "${resolved_file}" lower)
-
- if(UNIX)
- if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/|/usr/bin/)")
- set(is_system 1)
- endif()
- endif()
-
- if(APPLE)
- if(resolved_file MATCHES "^(/System/Library/|/usr/lib/)")
- set(is_system 1)
- endif()
- endif()
-
- if(WIN32)
- string(TOLOWER "$ENV{SystemRoot}" sysroot)
- string(REGEX REPLACE "\\\\" "/" sysroot "${sysroot}")
-
- string(TOLOWER "$ENV{windir}" windir)
- string(REGEX REPLACE "\\\\" "/" windir "${windir}")
-
- if(lower MATCHES "^(${sysroot}/sys(tem|wow)|${windir}/sys(tem|wow)|(.*/)*msvc[^/]+dll)")
- set(is_system 1)
- endif()
-
- if(UNIX)
- # if cygwin, we can get the properly formed windows paths from cygpath
- find_program(CYGPATH_EXECUTABLE cygpath)
-
- if(CYGPATH_EXECUTABLE)
- execute_process(COMMAND ${CYGPATH_EXECUTABLE} -W
- OUTPUT_VARIABLE env_windir
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- execute_process(COMMAND ${CYGPATH_EXECUTABLE} -S
- OUTPUT_VARIABLE env_sysdir
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- string(TOLOWER "${env_windir}" windir)
- string(TOLOWER "${env_sysdir}" sysroot)
-
- if(lower MATCHES "^(${sysroot}/sys(tem|wow)|${windir}/sys(tem|wow)|(.*/)*msvc[^/]+dll)")
- set(is_system 1)
- endif()
- endif()
- endif()
- endif()
-
- if(NOT is_system)
- get_filename_component(original_path "${original_lower}" PATH)
- get_filename_component(path "${lower}" PATH)
- if("${original_path}" STREQUAL "${path}")
- set(is_local 1)
- else()
- string(LENGTH "${original_path}/" original_length)
- string(LENGTH "${lower}" path_length)
- if(${path_length} GREATER ${original_length})
- string(SUBSTRING "${lower}" 0 ${original_length} path)
- if("${original_path}/" STREQUAL "${path}")
- set(is_embedded 1)
- endif()
- endif()
- endif()
- endif()
- endif()
-
- # Return type string based on computed booleans:
- #
- set(type "other")
-
- if(is_system)
- set(type "system")
- elseif(is_embedded)
- set(type "embedded")
- elseif(is_local)
- set(type "local")
- endif()
-
- #message(STATUS "gp_resolved_file_type: '${file}' '${resolved_file}'")
- #message(STATUS " type: '${type}'")
-
- if(NOT is_embedded)
- if(NOT IS_ABSOLUTE "${resolved_file}")
- if(lower MATCHES "^msvc[^/]+dll" AND is_system)
- message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'")
- else()
- message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect")
- endif()
- endif()
- endif()
-
- # Provide a hook so that projects can override the decision on whether a
- # library belongs to the system or not by whatever logic they choose:
- #
- if(COMMAND gp_resolved_file_type_override)
- gp_resolved_file_type_override("${resolved_file}" type)
- endif()
-
- set(${type_var} "${type}" PARENT_SCOPE)
-
- #message(STATUS "**")
-endfunction()
-
-
-function(gp_file_type original_file file type_var)
- if(NOT IS_ABSOLUTE "${original_file}")
- message(STATUS "warning: gp_file_type expects absolute full path for first arg original_file")
- endif()
-
- get_filename_component(exepath "${original_file}" PATH)
-
- set(type "")
- gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "" type)
-
- set(${type_var} "${type}" PARENT_SCOPE)
-endfunction()
-
-
-function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs)
- set(verbose 0)
- set(eol_char "E")
-
- if(NOT IS_ABSOLUTE "${target}")
- message("warning: target '${target}' is not absolute...")
- endif()
-
- if(NOT EXISTS "${target}")
- message("warning: target '${target}' does not exist...")
- endif()
-
- set(gp_cmd_paths ${gp_cmd_paths}
- "C:/Program Files/Microsoft Visual Studio 9.0/VC/bin"
- "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin"
- "C:/Program Files/Microsoft Visual Studio 8/VC/BIN"
- "C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN"
- "C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN"
- "C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN"
- "/usr/local/bin"
- "/usr/bin"
- )
-
- # <setup-gp_tool-vars>
- #
- # Try to choose the right tool by default. Caller can set gp_tool prior to
- # calling this function to force using a different tool.
- #
- if("${gp_tool}" STREQUAL "")
- set(gp_tool "ldd")
-
- if(APPLE)
- set(gp_tool "otool")
- endif()
-
- if(WIN32 AND NOT UNIX) # This is how to check for cygwin, har!
- find_program(gp_dumpbin "dumpbin" PATHS ${gp_cmd_paths})
- if(gp_dumpbin)
- set(gp_tool "dumpbin")
- else() # Try harder. Maybe we're on MinGW
- set(gp_tool "objdump")
- endif()
- endif()
- endif()
-
- find_program(gp_cmd ${gp_tool} PATHS ${gp_cmd_paths})
-
- if(NOT gp_cmd)
- message(FATAL_ERROR "FATAL ERROR: could not find '${gp_tool}' - cannot analyze prerequisites!")
- return()
- endif()
-
- set(gp_tool_known 0)
-
- if("${gp_tool}" STREQUAL "ldd")
- set(gp_cmd_args "")
- set(gp_regex "^[\t ]*[^\t ]+ => ([^\t\(]+) .*${eol_char}$")
- set(gp_regex_error "not found${eol_char}$")
- set(gp_regex_fallback "^[\t ]*([^\t ]+) => ([^\t ]+).*${eol_char}$")
- set(gp_regex_cmp_count 1)
- set(gp_tool_known 1)
- endif()
-
- if("${gp_tool}" STREQUAL "otool")
- set(gp_cmd_args "-L")
- set(gp_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$")
- set(gp_regex_error "")
- set(gp_regex_fallback "")
- set(gp_regex_cmp_count 3)
- set(gp_tool_known 1)
- endif()
-
- if("${gp_tool}" STREQUAL "dumpbin")
- set(gp_cmd_args "/dependents")
- set(gp_regex "^ ([^ ].*[Dd][Ll][Ll])${eol_char}$")
- set(gp_regex_error "")
- set(gp_regex_fallback "")
- set(gp_regex_cmp_count 1)
- set(gp_tool_known 1)
- endif()
-
- if("${gp_tool}" STREQUAL "objdump")
- set(gp_cmd_args "-p")
- set(gp_regex "^\t*DLL Name: (.*\\.[Dd][Ll][Ll])${eol_char}$")
- set(gp_regex_error "")
- set(gp_regex_fallback "")
- set(gp_regex_cmp_count 1)
- set(gp_tool_known 1)
- endif()
-
- if(NOT gp_tool_known)
- message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...")
- message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'")
- message(STATUS "Valid gp_tool values are dumpbin, ldd, objdump and otool.")
- return()
- endif()
-
-
- if("${gp_tool}" STREQUAL "dumpbin")
- # When running dumpbin, it also needs the "Common7/IDE" directory in the
- # PATH. It will already be in the PATH if being run from a Visual Studio
- # command prompt. Add it to the PATH here in case we are running from a
- # different command prompt.
- #
- get_filename_component(gp_cmd_dir "${gp_cmd}" PATH)
- get_filename_component(gp_cmd_dlls_dir "${gp_cmd_dir}/../../Common7/IDE" ABSOLUTE)
- # Use cmake paths as a user may have a PATH element ending with a backslash.
- # This will escape the list delimiter and create havoc!
- if(EXISTS "${gp_cmd_dlls_dir}")
- # only add to the path if it is not already in the path
- set(gp_found_cmd_dlls_dir 0)
- file(TO_CMAKE_PATH "$ENV{PATH}" env_path)
- foreach(gp_env_path_element ${env_path})
- if("${gp_env_path_element}" STREQUAL "${gp_cmd_dlls_dir}")
- set(gp_found_cmd_dlls_dir 1)
- endif()
- endforeach()
-
- if(NOT gp_found_cmd_dlls_dir)
- file(TO_NATIVE_PATH "${gp_cmd_dlls_dir}" gp_cmd_dlls_dir)
- set(ENV{PATH} "$ENV{PATH};${gp_cmd_dlls_dir}")
- endif()
- endif()
- endif()
- #
- # </setup-gp_tool-vars>
-
- if("${gp_tool}" STREQUAL "ldd")
- set(old_ld_env "$ENV{LD_LIBRARY_PATH}")
- foreach(dir ${exepath} ${dirs})
- set(ENV{LD_LIBRARY_PATH} "${dir}:$ENV{LD_LIBRARY_PATH}")
- endforeach()
- endif()
-
-
- # Track new prerequisites at each new level of recursion. Start with an
- # empty list at each level:
- #
- set(unseen_prereqs)
-
- # Run gp_cmd on the target:
- #
- execute_process(
- COMMAND ${gp_cmd} ${gp_cmd_args} ${target}
- OUTPUT_VARIABLE gp_cmd_ov
- )
-
- if("${gp_tool}" STREQUAL "ldd")
- set(ENV{LD_LIBRARY_PATH} "${old_ld_env}")
- endif()
-
- if(verbose)
- message(STATUS "<RawOutput cmd='${gp_cmd} ${gp_cmd_args} ${target}'>")
- message(STATUS "gp_cmd_ov='${gp_cmd_ov}'")
- message(STATUS "</RawOutput>")
- endif()
-
- get_filename_component(target_dir "${target}" PATH)
-
- # Convert to a list of lines:
- #
- string(REGEX REPLACE ";" "\\\\;" candidates "${gp_cmd_ov}")
- string(REGEX REPLACE "\n" "${eol_char};" candidates "${candidates}")
-
- # check for install id and remove it from list, since otool -L can include a
- # reference to itself
- set(gp_install_id)
- if("${gp_tool}" STREQUAL "otool")
- execute_process(
- COMMAND otool -D ${target}
- OUTPUT_VARIABLE gp_install_id_ov
- )
- # second line is install name
- string(REGEX REPLACE ".*:\n" "" gp_install_id "${gp_install_id_ov}")
- if(gp_install_id)
- # trim
- string(REGEX MATCH "[^\n ].*[^\n ]" gp_install_id "${gp_install_id}")
- #message("INSTALL ID is \"${gp_install_id}\"")
- endif()
- endif()
-
- # Analyze each line for file names that match the regular expression:
- #
- foreach(candidate ${candidates})
- if("${candidate}" MATCHES "${gp_regex}")
-
- # Extract information from each candidate:
- if(gp_regex_error AND "${candidate}" MATCHES "${gp_regex_error}")
- string(REGEX REPLACE "${gp_regex_fallback}" "\\1" raw_item "${candidate}")
- else()
- string(REGEX REPLACE "${gp_regex}" "\\1" raw_item "${candidate}")
- endif()
-
- if(gp_regex_cmp_count GREATER 1)
- string(REGEX REPLACE "${gp_regex}" "\\2" raw_compat_version "${candidate}")
- string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}")
- string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}")
- string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}")
- endif()
-
- if(gp_regex_cmp_count GREATER 2)
- string(REGEX REPLACE "${gp_regex}" "\\3" raw_current_version "${candidate}")
- string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}")
- string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}")
- string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}")
- endif()
-
- # Use the raw_item as the list entries returned by this function. Use the
- # gp_resolve_item function to resolve it to an actual full path file if
- # necessary.
- #
- set(item "${raw_item}")
-
- # Add each item unless it is excluded:
- #
- set(add_item 1)
-
- if("${item}" STREQUAL "${gp_install_id}")
- set(add_item 0)
- endif()
-
- if(add_item AND ${exclude_system})
- set(type "")
- gp_resolved_file_type("${target}" "${item}" "${exepath}" "${dirs}" type)
-
- if("${type}" STREQUAL "system")
- set(add_item 0)
- endif()
- endif()
-
- if(add_item)
- list(LENGTH ${prerequisites_var} list_length_before_append)
- gp_append_unique(${prerequisites_var} "${item}")
- list(LENGTH ${prerequisites_var} list_length_after_append)
-
- if(${recurse})
- # If item was really added, this is the first time we have seen it.
- # Add it to unseen_prereqs so that we can recursively add *its*
- # prerequisites...
- #
- # But first: resolve its name to an absolute full path name such
- # that the analysis tools can simply accept it as input.
- #
- if(NOT list_length_before_append EQUAL list_length_after_append)
- gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item)
- set(unseen_prereqs ${unseen_prereqs} "${resolved_item}")
- endif()
- endif()
- endif()
- else()
- if(verbose)
- message(STATUS "ignoring non-matching line: '${candidate}'")
- endif()
- endif()
- endforeach()
-
- list(LENGTH ${prerequisites_var} prerequisites_var_length)
- if(prerequisites_var_length GREATER 0)
- list(SORT ${prerequisites_var})
- endif()
- if(${recurse})
- set(more_inputs ${unseen_prereqs})
- foreach(input ${more_inputs})
- get_prerequisites("${input}" ${prerequisites_var} ${exclude_system} ${recurse} "${exepath}" "${dirs}")
- endforeach()
- endif()
-
- set(${prerequisites_var} ${${prerequisites_var}} PARENT_SCOPE)
-endfunction()
-
-
-function(list_prerequisites target)
- if("${ARGV1}" STREQUAL "")
- set(all 1)
- else()
- set(all "${ARGV1}")
- endif()
-
- if("${ARGV2}" STREQUAL "")
- set(exclude_system 0)
- else()
- set(exclude_system "${ARGV2}")
- endif()
-
- if("${ARGV3}" STREQUAL "")
- set(verbose 0)
- else()
- set(verbose "${ARGV3}")
- endif()
-
- set(count 0)
- set(count_str "")
- set(print_count "${verbose}")
- set(print_prerequisite_type "${verbose}")
- set(print_target "${verbose}")
- set(type_str "")
-
- get_filename_component(exepath "${target}" PATH)
-
- set(prereqs "")
- get_prerequisites("${target}" prereqs ${exclude_system} ${all} "${exepath}" "")
-
- if(print_target)
- message(STATUS "File '${target}' depends on:")
- endif()
-
- foreach(d ${prereqs})
- math(EXPR count "${count} + 1")
-
- if(print_count)
- set(count_str "${count}. ")
- endif()
-
- if(print_prerequisite_type)
- gp_file_type("${target}" "${d}" type)
- set(type_str " (${type})")
- endif()
-
- message(STATUS "${count_str}${d}${type_str}")
- endforeach()
-endfunction()
-
-
-function(list_prerequisites_by_glob glob_arg glob_exp)
- message(STATUS "=============================================================================")
- message(STATUS "List prerequisites of executables matching ${glob_arg} '${glob_exp}'")
- message(STATUS "")
- file(${glob_arg} file_list ${glob_exp})
- foreach(f ${file_list})
- is_file_executable("${f}" is_f_executable)
- if(is_f_executable)
- message(STATUS "=============================================================================")
- list_prerequisites("${f}" ${ARGN})
- message(STATUS "")
- endif()
- endforeach()
-endfunction()
diff --git a/cmake/MacOSXBundleInfo.plist.in b/cmake/MacOSXBundleInfo.plist.in
index 0e3a43c6..9e663d31 100644
--- a/cmake/MacOSXBundleInfo.plist.in
+++ b/cmake/MacOSXBundleInfo.plist.in
@@ -2,10 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>NSCameraUsageDescription</key>
- <string>A Minecraft mod wants to access your camera.</string>
- <key>NSMicrophoneUsageDescription</key>
- <string>A Minecraft mod wants to access your microphone.</string>
+ <key>NSCameraUsageDescription</key>
+ <string>A Minecraft mod wants to access your camera.</string>
+ <key>NSMicrophoneUsageDescription</key>
+ <string>A Minecraft mod wants to access your microphone.</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>
diff --git a/cmake/UseJava.cmake b/cmake/UseJava.cmake
deleted file mode 100644
index 1a5ef107..00000000
--- a/cmake/UseJava.cmake
+++ /dev/null
@@ -1,881 +0,0 @@
-# - Use Module for Java
-# This file provides functions for Java. It is assumed that FindJava.cmake
-# has already been loaded. See FindJava.cmake for information on how to
-# load Java into your CMake project.
-#
-# add_jar(TARGET_NAME SRC1 SRC2 .. SRCN RCS1 RCS2 .. RCSN)
-#
-# This command creates a <TARGET_NAME>.jar. It compiles the given source
-# files (SRC) and adds the given resource files (RCS) to the jar file.
-# If only resource files are given then just a jar file is created.
-#
-# Additional instructions:
-# To add compile flags to the target you can set these flags with
-# the following variable:
-#
-# set(CMAKE_JAVA_COMPILE_FLAGS -nowarn)
-#
-# To add a path or a jar file to the class path you can do this
-# with the CMAKE_JAVA_INCLUDE_PATH variable.
-#
-# set(CMAKE_JAVA_INCLUDE_PATH /usr/share/java/shibboleet.jar)
-#
-# To use a different output name for the target you can set it with:
-#
-# set(CMAKE_JAVA_TARGET_OUTPUT_NAME shibboleet.jar)
-# add_jar(foobar foobar.java)
-#
-# To use a different output directory than CMAKE_CURRENT_BINARY_DIR
-# you can set it with:
-#
-# set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/bin)
-#
-# To define an entry point in your jar you can set it with:
-#
-# set(CMAKE_JAVA_JAR_ENTRY_POINT com/examples/MyProject/Main)
-#
-# To add a VERSION to the target output name you can set it using
-# CMAKE_JAVA_TARGET_VERSION. This will create a jar file with the name
-# shibboleet-1.0.0.jar and will create a symlink shibboleet.jar
-# pointing to the jar with the version information.
-#
-# set(CMAKE_JAVA_TARGET_VERSION 1.2.0)
-# add_jar(shibboleet shibbotleet.java)
-#
-# If the target is a JNI library, utilize the following commands to
-# create a JNI symbolic link:
-#
-# set(CMAKE_JNI_TARGET TRUE)
-# set(CMAKE_JAVA_TARGET_VERSION 1.2.0)
-# add_jar(shibboleet shibbotleet.java)
-# install_jar(shibboleet ${LIB_INSTALL_DIR}/shibboleet)
-# install_jni_symlink(shibboleet ${JAVA_LIB_INSTALL_DIR})
-#
-# If a single target needs to produce more than one jar from its
-# java source code, to prevent the accumulation of duplicate class
-# files in subsequent jars, set/reset CMAKE_JAR_CLASSES_PREFIX prior
-# to calling the add_jar() function:
-#
-# set(CMAKE_JAR_CLASSES_PREFIX com/redhat/foo)
-# add_jar(foo foo.java)
-#
-# set(CMAKE_JAR_CLASSES_PREFIX com/redhat/bar)
-# add_jar(bar bar.java)
-#
-# Target Properties:
-# The add_jar() functions sets some target properties. You can get these
-# properties with the
-# get_property(TARGET <target_name> PROPERTY <propery_name>)
-# command.
-#
-# INSTALL_FILES The files which should be installed. This is used by
-# install_jar().
-# JNI_SYMLINK The JNI symlink which should be installed.
-# This is used by install_jni_symlink().
-# JAR_FILE The location of the jar file so that you can include
-# it.
-# CLASS_DIR The directory where the class files can be found. For
-# example to use them with javah.
-#
-# find_jar(<VAR>
-# name | NAMES name1 [name2 ...]
-# [PATHS path1 [path2 ... ENV var]]
-# [VERSIONS version1 [version2]]
-# [DOC "cache documentation string"]
-# )
-#
-# This command is used to find a full path to the named jar. A cache
-# entry named by <VAR> is created to stor the result of this command. If
-# the full path to a jar is found the result is stored in the variable
-# and the search will not repeated unless the variable is cleared. If
-# nothing is found, the result will be <VAR>-NOTFOUND, and the search
-# will be attempted again next time find_jar is invoked with the same
-# variable.
-# The name of the full path to a file that is searched for is specified
-# by the names listed after NAMES argument. Additional search locations
-# can be specified after the PATHS argument. If you require special a
-# version of a jar file you can specify it with the VERSIONS argument.
-# The argument after DOC will be used for the documentation string in
-# the cache.
-#
-# install_jar(TARGET_NAME DESTINATION)
-#
-# This command installs the TARGET_NAME files to the given DESTINATION.
-# It should be called in the same scope as add_jar() or it will fail.
-#
-# install_jni_symlink(TARGET_NAME DESTINATION)
-#
-# This command installs the TARGET_NAME JNI symlinks to the given
-# DESTINATION. It should be called in the same scope as add_jar()
-# or it will fail.
-#
-# create_javadoc(<VAR>
-# PACKAGES pkg1 [pkg2 ...]
-# [SOURCEPATH <sourcepath>]
-# [CLASSPATH <classpath>]
-# [INSTALLPATH <install path>]
-# [DOCTITLE "the documentation title"]
-# [WINDOWTITLE "the title of the document"]
-# [AUTHOR TRUE|FALSE]
-# [USE TRUE|FALSE]
-# [VERSION TRUE|FALSE]
-# )
-#
-# Create java documentation based on files or packages. For more
-# details please read the javadoc manpage.
-#
-# There are two main signatures for create_javadoc. The first
-# signature works with package names on a path with source files:
-#
-# Example:
-# create_javadoc(my_example_doc
-# PACKAGES com.exmaple.foo com.example.bar
-# SOURCEPATH "${CMAKE_CURRENT_SOURCE_DIR}"
-# CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
-# WINDOWTITLE "My example"
-# DOCTITLE "<h1>My example</h1>"
-# AUTHOR TRUE
-# USE TRUE
-# VERSION TRUE
-# )
-#
-# The second signature for create_javadoc works on a given list of
-# files.
-#
-# create_javadoc(<VAR>
-# FILES file1 [file2 ...]
-# [CLASSPATH <classpath>]
-# [INSTALLPATH <install path>]
-# [DOCTITLE "the documentation title"]
-# [WINDOWTITLE "the title of the document"]
-# [AUTHOR TRUE|FALSE]
-# [USE TRUE|FALSE]
-# [VERSION TRUE|FALSE]
-# )
-#
-# Example:
-# create_javadoc(my_example_doc
-# FILES ${example_SRCS}
-# CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
-# WINDOWTITLE "My example"
-# DOCTITLE "<h1>My example</h1>"
-# AUTHOR TRUE
-# USE TRUE
-# VERSION TRUE
-# )
-#
-# Both signatures share most of the options. These options are the
-# same as what you can find in the javadoc manpage. Please look at
-# the manpage for CLASSPATH, DOCTITLE, WINDOWTITLE, AUTHOR, USE and
-# VERSION.
-#
-# The documentation will be by default installed to
-#
-# ${CMAKE_INSTALL_PREFIX}/share/javadoc/<VAR>
-#
-# if you don't set the INSTALLPATH.
-#
-
-#=============================================================================
-# Copyright 2010-2011 Andreas schneider <asn@redhat.com>
-# Copyright 2010 Ben Boeckel <ben.boeckel@kitware.com>
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distribute this file outside of CMake, substitute the full
-# License text for the above reference.)
-
-function (__java_copy_file src dest comment)
- add_custom_command(
- OUTPUT ${dest}
- COMMAND cmake -E copy_if_different
- ARGS ${src}
- ${dest}
- DEPENDS ${src}
- COMMENT ${comment})
-endfunction (__java_copy_file src dest comment)
-
-# define helper scripts
-set(_JAVA_CLASS_FILELIST_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaClassFilelist.cmake)
-set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaSymlinks.cmake)
-
-function(add_jar _TARGET_NAME)
- set(_JAVA_SOURCE_FILES ${ARGN})
-
- if (NOT DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR)
- set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
- endif(NOT DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR)
-
- if (CMAKE_JAVA_JAR_ENTRY_POINT)
- set(_ENTRY_POINT_OPTION e)
- set(_ENTRY_POINT_VALUE ${CMAKE_JAVA_JAR_ENTRY_POINT})
- endif (CMAKE_JAVA_JAR_ENTRY_POINT)
-
- if (LIBRARY_OUTPUT_PATH)
- set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH})
- else (LIBRARY_OUTPUT_PATH)
- set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR})
- endif (LIBRARY_OUTPUT_PATH)
-
- set(CMAKE_JAVA_INCLUDE_PATH
- ${CMAKE_JAVA_INCLUDE_PATH}
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_JAVA_OBJECT_OUTPUT_PATH}
- ${CMAKE_JAVA_LIBRARY_OUTPUT_PATH}
- )
-
- if (WIN32 AND NOT CYGWIN AND NOT CMAKE_CROSSCOMPILING)
- set(CMAKE_JAVA_INCLUDE_FLAG_SEP ";")
- else ()
- set(CMAKE_JAVA_INCLUDE_FLAG_SEP ":")
- endif()
-
- foreach (JAVA_INCLUDE_DIR ${CMAKE_JAVA_INCLUDE_PATH})
- set(CMAKE_JAVA_INCLUDE_PATH_FINAL "${CMAKE_JAVA_INCLUDE_PATH_FINAL}${CMAKE_JAVA_INCLUDE_FLAG_SEP}${JAVA_INCLUDE_DIR}")
- endforeach(JAVA_INCLUDE_DIR)
-
- set(CMAKE_JAVA_CLASS_OUTPUT_PATH "${CMAKE_JAVA_TARGET_OUTPUT_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir")
-
- set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}.jar")
- if (CMAKE_JAVA_TARGET_OUTPUT_NAME AND CMAKE_JAVA_TARGET_VERSION)
- set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar")
- set(_JAVA_TARGET_OUTPUT_LINK "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar")
- elseif (CMAKE_JAVA_TARGET_VERSION)
- set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar")
- set(_JAVA_TARGET_OUTPUT_LINK "${_TARGET_NAME}.jar")
- elseif (CMAKE_JAVA_TARGET_OUTPUT_NAME)
- set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar")
- endif (CMAKE_JAVA_TARGET_OUTPUT_NAME AND CMAKE_JAVA_TARGET_VERSION)
- # reset
- set(CMAKE_JAVA_TARGET_OUTPUT_NAME)
-
- set(_JAVA_CLASS_FILES)
- set(_JAVA_COMPILE_FILES)
- set(_JAVA_DEPENDS)
- set(_JAVA_RESOURCE_FILES)
- foreach(_JAVA_SOURCE_FILE ${_JAVA_SOURCE_FILES})
- get_filename_component(_JAVA_EXT ${_JAVA_SOURCE_FILE} EXT)
- get_filename_component(_JAVA_FILE ${_JAVA_SOURCE_FILE} NAME_WE)
- get_filename_component(_JAVA_PATH ${_JAVA_SOURCE_FILE} PATH)
- get_filename_component(_JAVA_FULL ${_JAVA_SOURCE_FILE} ABSOLUTE)
-
- file(RELATIVE_PATH _JAVA_REL_BINARY_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR} ${_JAVA_FULL})
- file(RELATIVE_PATH _JAVA_REL_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${_JAVA_FULL})
- string(LENGTH ${_JAVA_REL_BINARY_PATH} _BIN_LEN)
- string(LENGTH ${_JAVA_REL_SOURCE_PATH} _SRC_LEN)
- if (${_BIN_LEN} LESS ${_SRC_LEN})
- set(_JAVA_REL_PATH ${_JAVA_REL_BINARY_PATH})
- else (${_BIN_LEN} LESS ${_SRC_LEN})
- set(_JAVA_REL_PATH ${_JAVA_REL_SOURCE_PATH})
- endif (${_BIN_LEN} LESS ${_SRC_LEN})
- get_filename_component(_JAVA_REL_PATH ${_JAVA_REL_PATH} PATH)
-
- if (_JAVA_EXT MATCHES ".java")
- list(APPEND _JAVA_COMPILE_FILES ${_JAVA_SOURCE_FILE})
- set(_JAVA_CLASS_FILE "${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${_JAVA_REL_PATH}/${_JAVA_FILE}.class")
- set(_JAVA_CLASS_FILES ${_JAVA_CLASS_FILES} ${_JAVA_CLASS_FILE})
-
- elseif (_JAVA_EXT MATCHES ".jar"
- OR _JAVA_EXT MATCHES ".war"
- OR _JAVA_EXT MATCHES ".ear"
- OR _JAVA_EXT MATCHES ".sar")
- list(APPEND CMAKE_JAVA_INCLUDE_PATH ${_JAVA_SOURCE_FILE})
-
- elseif (_JAVA_EXT STREQUAL "")
- list(APPEND CMAKE_JAVA_INCLUDE_PATH ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}} ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}_CLASSPATH})
- list(APPEND _JAVA_DEPENDS ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}})
-
- else (_JAVA_EXT MATCHES ".java")
- __java_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/${_JAVA_SOURCE_FILE}
- ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${_JAVA_SOURCE_FILE}
- "Copying ${_JAVA_SOURCE_FILE} to the build directory")
- list(APPEND _JAVA_RESOURCE_FILES ${_JAVA_SOURCE_FILE})
- endif (_JAVA_EXT MATCHES ".java")
- endforeach(_JAVA_SOURCE_FILE)
-
- # create an empty java_class_filelist
- if (NOT EXISTS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist)
- file(WRITE ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist "")
- endif()
-
- if (_JAVA_COMPILE_FILES)
- # Compile the java files and create a list of class files
- add_custom_command(
- # NOTE: this command generates an artificial dependency file
- OUTPUT ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
- COMMAND ${Java_JAVAC_EXECUTABLE}
- ${CMAKE_JAVA_COMPILE_FLAGS}
- -classpath "${CMAKE_JAVA_INCLUDE_PATH_FINAL}"
- -d ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
- ${_JAVA_COMPILE_FILES}
- COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
- DEPENDS ${_JAVA_COMPILE_FILES}
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- COMMENT "Building Java objects for ${_TARGET_NAME}.jar"
- )
- add_custom_command(
- OUTPUT ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist
- COMMAND ${CMAKE_COMMAND}
- -DCMAKE_JAVA_CLASS_OUTPUT_PATH=${CMAKE_JAVA_CLASS_OUTPUT_PATH}
- -DCMAKE_JAR_CLASSES_PREFIX="${CMAKE_JAR_CLASSES_PREFIX}"
- -P ${_JAVA_CLASS_FILELIST_SCRIPT}
- DEPENDS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- )
- endif (_JAVA_COMPILE_FILES)
-
- # create the jar file
- set(_JAVA_JAR_OUTPUT_PATH
- ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_NAME})
- if (CMAKE_JNI_TARGET)
- add_custom_command(
- OUTPUT ${_JAVA_JAR_OUTPUT_PATH}
- COMMAND ${Java_JAR_EXECUTABLE}
- -cf${_ENTRY_POINT_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE}
- ${_JAVA_RESOURCE_FILES} @java_class_filelist
- COMMAND ${CMAKE_COMMAND}
- -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR}
- -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME}
- -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK}
- -P ${_JAVA_SYMLINK_SCRIPT}
- COMMAND ${CMAKE_COMMAND}
- -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR}
- -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_JAR_OUTPUT_PATH}
- -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK}
- -P ${_JAVA_SYMLINK_SCRIPT}
- DEPENDS ${_JAVA_RESOURCE_FILES} ${_JAVA_DEPENDS} ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist
- WORKING_DIRECTORY ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
- COMMENT "Creating Java archive ${_JAVA_TARGET_OUTPUT_NAME}"
- )
- else ()
- add_custom_command(
- OUTPUT ${_JAVA_JAR_OUTPUT_PATH}
- COMMAND ${Java_JAR_EXECUTABLE}
- -cf${_ENTRY_POINT_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE}
- ${_JAVA_RESOURCE_FILES} @java_class_filelist
- COMMAND ${CMAKE_COMMAND}
- -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR}
- -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME}
- -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK}
- -P ${_JAVA_SYMLINK_SCRIPT}
- WORKING_DIRECTORY ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
- DEPENDS ${_JAVA_RESOURCE_FILES} ${_JAVA_DEPENDS} ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist
- COMMENT "Creating Java archive ${_JAVA_TARGET_OUTPUT_NAME}"
- )
- endif (CMAKE_JNI_TARGET)
-
- # Add the target and make sure we have the latest resource files.
- add_custom_target(${_TARGET_NAME} ALL DEPENDS ${_JAVA_JAR_OUTPUT_PATH})
-
- set_property(
- TARGET
- ${_TARGET_NAME}
- PROPERTY
- INSTALL_FILES
- ${_JAVA_JAR_OUTPUT_PATH}
- )
-
- if (_JAVA_TARGET_OUTPUT_LINK)
- set_property(
- TARGET
- ${_TARGET_NAME}
- PROPERTY
- INSTALL_FILES
- ${_JAVA_JAR_OUTPUT_PATH}
- ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK}
- )
-
- if (CMAKE_JNI_TARGET)
- set_property(
- TARGET
- ${_TARGET_NAME}
- PROPERTY
- JNI_SYMLINK
- ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK}
- )
- endif (CMAKE_JNI_TARGET)
- endif (_JAVA_TARGET_OUTPUT_LINK)
-
- set_property(
- TARGET
- ${_TARGET_NAME}
- PROPERTY
- JAR_FILE
- ${_JAVA_JAR_OUTPUT_PATH}
- )
-
- set_property(
- TARGET
- ${_TARGET_NAME}
- PROPERTY
- CLASSDIR
- ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
- )
-
-endfunction(add_jar)
-
-function(INSTALL_JAR _TARGET_NAME _DESTINATION)
- get_property(__FILES
- TARGET
- ${_TARGET_NAME}
- PROPERTY
- INSTALL_FILES
- )
-
- if (__FILES)
- install(
- FILES
- ${__FILES}
- DESTINATION
- ${_DESTINATION}
- )
- else (__FILES)
- message(SEND_ERROR "The target ${_TARGET_NAME} is not known in this scope.")
- endif (__FILES)
-endfunction(INSTALL_JAR _TARGET_NAME _DESTINATION)
-
-function(INSTALL_JNI_SYMLINK _TARGET_NAME _DESTINATION)
- get_property(__SYMLINK
- TARGET
- ${_TARGET_NAME}
- PROPERTY
- JNI_SYMLINK
- )
-
- if (__SYMLINK)
- install(
- FILES
- ${__SYMLINK}
- DESTINATION
- ${_DESTINATION}
- )
- else (__SYMLINK)
- message(SEND_ERROR "The target ${_TARGET_NAME} is not known in this scope.")
- endif (__SYMLINK)
-endfunction(INSTALL_JNI_SYMLINK _TARGET_NAME _DESTINATION)
-
-function (find_jar VARIABLE)
- set(_jar_names)
- set(_jar_files)
- set(_jar_versions)
- set(_jar_paths
- /usr/share/java/
- /usr/local/share/java/
- ${Java_JAR_PATHS})
- set(_jar_doc "NOTSET")
-
- set(_state "name")
-
- foreach (arg ${ARGN})
- if (${_state} STREQUAL "name")
- if (${arg} STREQUAL "VERSIONS")
- set(_state "versions")
- elseif (${arg} STREQUAL "NAMES")
- set(_state "names")
- elseif (${arg} STREQUAL "PATHS")
- set(_state "paths")
- elseif (${arg} STREQUAL "DOC")
- set(_state "doc")
- else (${arg} STREQUAL "NAMES")
- set(_jar_names ${arg})
- if (_jar_doc STREQUAL "NOTSET")
- set(_jar_doc "Finding ${arg} jar")
- endif (_jar_doc STREQUAL "NOTSET")
- endif (${arg} STREQUAL "VERSIONS")
- elseif (${_state} STREQUAL "versions")
- if (${arg} STREQUAL "NAMES")
- set(_state "names")
- elseif (${arg} STREQUAL "PATHS")
- set(_state "paths")
- elseif (${arg} STREQUAL "DOC")
- set(_state "doc")
- else (${arg} STREQUAL "NAMES")
- set(_jar_versions ${_jar_versions} ${arg})
- endif (${arg} STREQUAL "NAMES")
- elseif (${_state} STREQUAL "names")
- if (${arg} STREQUAL "VERSIONS")
- set(_state "versions")
- elseif (${arg} STREQUAL "PATHS")
- set(_state "paths")
- elseif (${arg} STREQUAL "DOC")
- set(_state "doc")
- else (${arg} STREQUAL "VERSIONS")
- set(_jar_names ${_jar_names} ${arg})
- if (_jar_doc STREQUAL "NOTSET")
- set(_jar_doc "Finding ${arg} jar")
- endif (_jar_doc STREQUAL "NOTSET")
- endif (${arg} STREQUAL "VERSIONS")
- elseif (${_state} STREQUAL "paths")
- if (${arg} STREQUAL "VERSIONS")
- set(_state "versions")
- elseif (${arg} STREQUAL "NAMES")
- set(_state "names")
- elseif (${arg} STREQUAL "DOC")
- set(_state "doc")
- else (${arg} STREQUAL "VERSIONS")
- set(_jar_paths ${_jar_paths} ${arg})
- endif (${arg} STREQUAL "VERSIONS")
- elseif (${_state} STREQUAL "doc")
- if (${arg} STREQUAL "VERSIONS")
- set(_state "versions")
- elseif (${arg} STREQUAL "NAMES")
- set(_state "names")
- elseif (${arg} STREQUAL "PATHS")
- set(_state "paths")
- else (${arg} STREQUAL "VERSIONS")
- set(_jar_doc ${arg})
- endif (${arg} STREQUAL "VERSIONS")
- endif (${_state} STREQUAL "name")
- endforeach (arg ${ARGN})
-
- if (NOT _jar_names)
- message(FATAL_ERROR "find_jar: No name to search for given")
- endif (NOT _jar_names)
-
- foreach (jar_name ${_jar_names})
- foreach (version ${_jar_versions})
- set(_jar_files ${_jar_files} ${jar_name}-${version}.jar)
- endforeach (version ${_jar_versions})
- set(_jar_files ${_jar_files} ${jar_name}.jar)
- endforeach (jar_name ${_jar_names})
-
- find_file(${VARIABLE}
- NAMES ${_jar_files}
- PATHS ${_jar_paths}
- DOC ${_jar_doc}
- NO_DEFAULT_PATH)
-endfunction (find_jar VARIABLE)
-
-function(create_javadoc _target)
- set(_javadoc_packages)
- set(_javadoc_files)
- set(_javadoc_sourcepath)
- set(_javadoc_classpath)
- set(_javadoc_installpath "${CMAKE_INSTALL_PREFIX}/share/javadoc")
- set(_javadoc_doctitle)
- set(_javadoc_windowtitle)
- set(_javadoc_author FALSE)
- set(_javadoc_version FALSE)
- set(_javadoc_use FALSE)
-
- set(_state "package")
-
- foreach (arg ${ARGN})
- if (${_state} STREQUAL "package")
- if (${arg} STREQUAL "PACKAGES")
- set(_state "packages")
- elseif (${arg} STREQUAL "FILES")
- set(_state "files")
- elseif (${arg} STREQUAL "SOURCEPATH")
- set(_state "sourcepath")
- elseif (${arg} STREQUAL "CLASSPATH")
- set(_state "classpath")
- elseif (${arg} STREQUAL "INSTALLPATH")
- set(_state "installpath")
- elseif (${arg} STREQUAL "DOCTITLE")
- set(_state "doctitle")
- elseif (${arg} STREQUAL "WINDOWTITLE")
- set(_state "windowtitle")
- elseif (${arg} STREQUAL "AUTHOR")
- set(_state "author")
- elseif (${arg} STREQUAL "USE")
- set(_state "use")
- elseif (${arg} STREQUAL "VERSION")
- set(_state "version")
- else ()
- set(_javadoc_packages ${arg})
- set(_state "packages")
- endif ()
- elseif (${_state} STREQUAL "packages")
- if (${arg} STREQUAL "FILES")
- set(_state "files")
- elseif (${arg} STREQUAL "SOURCEPATH")
- set(_state "sourcepath")
- elseif (${arg} STREQUAL "CLASSPATH")
- set(_state "classpath")
- elseif (${arg} STREQUAL "INSTALLPATH")
- set(_state "installpath")
- elseif (${arg} STREQUAL "DOCTITLE")
- set(_state "doctitle")
- elseif (${arg} STREQUAL "WINDOWTITLE")
- set(_state "windowtitle")
- elseif (${arg} STREQUAL "AUTHOR")
- set(_state "author")
- elseif (${arg} STREQUAL "USE")
- set(_state "use")
- elseif (${arg} STREQUAL "VERSION")
- set(_state "version")
- else ()
- list(APPEND _javadoc_packages ${arg})
- endif ()
- elseif (${_state} STREQUAL "files")
- if (${arg} STREQUAL "PACKAGES")
- set(_state "packages")
- elseif (${arg} STREQUAL "SOURCEPATH")
- set(_state "sourcepath")
- elseif (${arg} STREQUAL "CLASSPATH")
- set(_state "classpath")
- elseif (${arg} STREQUAL "INSTALLPATH")
- set(_state "installpath")
- elseif (${arg} STREQUAL "DOCTITLE")
- set(_state "doctitle")
- elseif (${arg} STREQUAL "WINDOWTITLE")
- set(_state "windowtitle")
- elseif (${arg} STREQUAL "AUTHOR")
- set(_state "author")
- elseif (${arg} STREQUAL "USE")
- set(_state "use")
- elseif (${arg} STREQUAL "VERSION")
- set(_state "version")
- else ()
- list(APPEND _javadoc_files ${arg})
- endif ()
- elseif (${_state} STREQUAL "sourcepath")
- if (${arg} STREQUAL "PACKAGES")
- set(_state "packages")
- elseif (${arg} STREQUAL "FILES")
- set(_state "files")
- elseif (${arg} STREQUAL "CLASSPATH")
- set(_state "classpath")
- elseif (${arg} STREQUAL "INSTALLPATH")
- set(_state "installpath")
- elseif (${arg} STREQUAL "DOCTITLE")
- set(_state "doctitle")
- elseif (${arg} STREQUAL "WINDOWTITLE")
- set(_state "windowtitle")
- elseif (${arg} STREQUAL "AUTHOR")
- set(_state "author")
- elseif (${arg} STREQUAL "USE")
- set(_state "use")
- elseif (${arg} STREQUAL "VERSION")
- set(_state "version")
- else ()
- list(APPEND _javadoc_sourcepath ${arg})
- endif ()
- elseif (${_state} STREQUAL "classpath")
- if (${arg} STREQUAL "PACKAGES")
- set(_state "packages")
- elseif (${arg} STREQUAL "FILES")
- set(_state "files")
- elseif (${arg} STREQUAL "SOURCEPATH")
- set(_state "sourcepath")
- elseif (${arg} STREQUAL "INSTALLPATH")
- set(_state "installpath")
- elseif (${arg} STREQUAL "DOCTITLE")
- set(_state "doctitle")
- elseif (${arg} STREQUAL "WINDOWTITLE")
- set(_state "windowtitle")
- elseif (${arg} STREQUAL "AUTHOR")
- set(_state "author")
- elseif (${arg} STREQUAL "USE")
- set(_state "use")
- elseif (${arg} STREQUAL "VERSION")
- set(_state "version")
- else ()
- list(APPEND _javadoc_classpath ${arg})
- endif ()
- elseif (${_state} STREQUAL "installpath")
- if (${arg} STREQUAL "PACKAGES")
- set(_state "packages")
- elseif (${arg} STREQUAL "FILES")
- set(_state "files")
- elseif (${arg} STREQUAL "SOURCEPATH")
- set(_state "sourcepath")
- elseif (${arg} STREQUAL "DOCTITLE")
- set(_state "doctitle")
- elseif (${arg} STREQUAL "WINDOWTITLE")
- set(_state "windowtitle")
- elseif (${arg} STREQUAL "AUTHOR")
- set(_state "author")
- elseif (${arg} STREQUAL "USE")
- set(_state "use")
- elseif (${arg} STREQUAL "VERSION")
- set(_state "version")
- else ()
- set(_javadoc_installpath ${arg})
- endif ()
- elseif (${_state} STREQUAL "doctitle")
- if (${arg} STREQUAL "PACKAGES")
- set(_state "packages")
- elseif (${arg} STREQUAL "FILES")
- set(_state "files")
- elseif (${arg} STREQUAL "SOURCEPATH")
- set(_state "sourcepath")
- elseif (${arg} STREQUAL "INSTALLPATH")
- set(_state "installpath")
- elseif (${arg} STREQUAL "CLASSPATH")
- set(_state "classpath")
- elseif (${arg} STREQUAL "WINDOWTITLE")
- set(_state "windowtitle")
- elseif (${arg} STREQUAL "AUTHOR")
- set(_state "author")
- elseif (${arg} STREQUAL "USE")
- set(_state "use")
- elseif (${arg} STREQUAL "VERSION")
- set(_state "version")
- else ()
- set(_javadoc_doctitle ${arg})
- endif ()
- elseif (${_state} STREQUAL "windowtitle")
- if (${arg} STREQUAL "PACKAGES")
- set(_state "packages")
- elseif (${arg} STREQUAL "FILES")
- set(_state "files")
- elseif (${arg} STREQUAL "SOURCEPATH")
- set(_state "sourcepath")
- elseif (${arg} STREQUAL "CLASSPATH")
- set(_state "classpath")
- elseif (${arg} STREQUAL "INSTALLPATH")
- set(_state "installpath")
- elseif (${arg} STREQUAL "DOCTITLE")
- set(_state "doctitle")
- elseif (${arg} STREQUAL "AUTHOR")
- set(_state "author")
- elseif (${arg} STREQUAL "USE")
- set(_state "use")
- elseif (${arg} STREQUAL "VERSION")
- set(_state "version")
- else ()
- set(_javadoc_windowtitle ${arg})
- endif ()
- elseif (${_state} STREQUAL "author")
- if (${arg} STREQUAL "PACKAGES")
- set(_state "packages")
- elseif (${arg} STREQUAL "FILES")
- set(_state "files")
- elseif (${arg} STREQUAL "SOURCEPATH")
- set(_state "sourcepath")
- elseif (${arg} STREQUAL "CLASSPATH")
- set(_state "classpath")
- elseif (${arg} STREQUAL "INSTALLPATH")
- set(_state "installpath")
- elseif (${arg} STREQUAL "DOCTITLE")
- set(_state "doctitle")
- elseif (${arg} STREQUAL "WINDOWTITLE")
- set(_state "windowtitle")
- elseif (${arg} STREQUAL "AUTHOR")
- set(_state "author")
- elseif (${arg} STREQUAL "USE")
- set(_state "use")
- elseif (${arg} STREQUAL "VERSION")
- set(_state "version")
- else ()
- set(_javadoc_author ${arg})
- endif ()
- elseif (${_state} STREQUAL "use")
- if (${arg} STREQUAL "PACKAGES")
- set(_state "packages")
- elseif (${arg} STREQUAL "FILES")
- set(_state "files")
- elseif (${arg} STREQUAL "SOURCEPATH")
- set(_state "sourcepath")
- elseif (${arg} STREQUAL "CLASSPATH")
- set(_state "classpath")
- elseif (${arg} STREQUAL "INSTALLPATH")
- set(_state "installpath")
- elseif (${arg} STREQUAL "DOCTITLE")
- set(_state "doctitle")
- elseif (${arg} STREQUAL "WINDOWTITLE")
- set(_state "windowtitle")
- elseif (${arg} STREQUAL "AUTHOR")
- set(_state "author")
- elseif (${arg} STREQUAL "USE")
- set(_state "use")
- elseif (${arg} STREQUAL "VERSION")
- set(_state "version")
- else ()
- set(_javadoc_use ${arg})
- endif ()
- elseif (${_state} STREQUAL "version")
- if (${arg} STREQUAL "PACKAGES")
- set(_state "packages")
- elseif (${arg} STREQUAL "FILES")
- set(_state "files")
- elseif (${arg} STREQUAL "SOURCEPATH")
- set(_state "sourcepath")
- elseif (${arg} STREQUAL "CLASSPATH")
- set(_state "classpath")
- elseif (${arg} STREQUAL "INSTALLPATH")
- set(_state "installpath")
- elseif (${arg} STREQUAL "DOCTITLE")
- set(_state "doctitle")
- elseif (${arg} STREQUAL "WINDOWTITLE")
- set(_state "windowtitle")
- elseif (${arg} STREQUAL "AUTHOR")
- set(_state "author")
- elseif (${arg} STREQUAL "USE")
- set(_state "use")
- elseif (${arg} STREQUAL "VERSION")
- set(_state "version")
- else ()
- set(_javadoc_version ${arg})
- endif ()
- endif (${_state} STREQUAL "package")
- endforeach (arg ${ARGN})
-
- set(_javadoc_builddir ${CMAKE_CURRENT_BINARY_DIR}/javadoc/${_target})
- set(_javadoc_options -d ${_javadoc_builddir})
-
- if (_javadoc_sourcepath)
- set(_start TRUE)
- foreach(_path ${_javadoc_sourcepath})
- if (_start)
- set(_sourcepath ${_path})
- set(_start FALSE)
- else (_start)
- set(_sourcepath ${_sourcepath}:${_path})
- endif (_start)
- endforeach(_path ${_javadoc_sourcepath})
- set(_javadoc_options ${_javadoc_options} -sourcepath ${_sourcepath})
- endif (_javadoc_sourcepath)
-
- if (_javadoc_classpath)
- set(_start TRUE)
- foreach(_path ${_javadoc_classpath})
- if (_start)
- set(_classpath ${_path})
- set(_start FALSE)
- else (_start)
- set(_classpath ${_classpath}:${_path})
- endif (_start)
- endforeach(_path ${_javadoc_classpath})
- set(_javadoc_options ${_javadoc_options} -classpath "${_classpath}")
- endif (_javadoc_classpath)
-
- if (_javadoc_doctitle)
- set(_javadoc_options ${_javadoc_options} -doctitle '${_javadoc_doctitle}')
- endif (_javadoc_doctitle)
-
- if (_javadoc_windowtitle)
- set(_javadoc_options ${_javadoc_options} -windowtitle '${_javadoc_windowtitle}')
- endif (_javadoc_windowtitle)
-
- if (_javadoc_author)
- set(_javadoc_options ${_javadoc_options} -author)
- endif (_javadoc_author)
-
- if (_javadoc_use)
- set(_javadoc_options ${_javadoc_options} -use)
- endif (_javadoc_use)
-
- if (_javadoc_version)
- set(_javadoc_options ${_javadoc_options} -version)
- endif (_javadoc_version)
-
- add_custom_target(${_target}_javadoc ALL
- COMMAND ${Java_JAVADOC_EXECUTABLE} ${_javadoc_options}
- ${_javadoc_files}
- ${_javadoc_packages}
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- )
-
- install(
- DIRECTORY ${_javadoc_builddir}
- DESTINATION ${_javadoc_installpath}
- )
-endfunction(create_javadoc)
diff --git a/cmake/UseJavaClassFilelist.cmake b/cmake/UseJavaClassFilelist.cmake
deleted file mode 100644
index c842bf71..00000000
--- a/cmake/UseJavaClassFilelist.cmake
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# This script create a list of compiled Java class files to be added to a
-# jar file. This avoids including cmake files which get created in the
-# binary directory.
-#
-
-#=============================================================================
-# Copyright 2010-2011 Andreas schneider <asn@redhat.com>
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distribute this file outside of CMake, substitute the full
-# License text for the above reference.)
-
-if (CMAKE_JAVA_CLASS_OUTPUT_PATH)
- if (EXISTS "${CMAKE_JAVA_CLASS_OUTPUT_PATH}")
-
- set(_JAVA_GLOBBED_FILES)
- if (CMAKE_JAR_CLASSES_PREFIX)
- foreach(JAR_CLASS_PREFIX ${CMAKE_JAR_CLASSES_PREFIX})
- message(STATUS "JAR_CLASS_PREFIX: ${JAR_CLASS_PREFIX}")
-
- file(GLOB_RECURSE _JAVA_GLOBBED_TMP_FILES "${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${JAR_CLASS_PREFIX}/*.class")
- if (_JAVA_GLOBBED_TMP_FILES)
- list(APPEND _JAVA_GLOBBED_FILES ${_JAVA_GLOBBED_TMP_FILES})
- endif (_JAVA_GLOBBED_TMP_FILES)
- endforeach(JAR_CLASS_PREFIX ${CMAKE_JAR_CLASSES_PREFIX})
- else()
- file(GLOB_RECURSE _JAVA_GLOBBED_FILES "${CMAKE_JAVA_CLASS_OUTPUT_PATH}/*.class")
- endif (CMAKE_JAR_CLASSES_PREFIX)
-
- set(_JAVA_CLASS_FILES)
- # file(GLOB_RECURSE foo RELATIVE) is broken so we need this.
- foreach(_JAVA_GLOBBED_FILE ${_JAVA_GLOBBED_FILES})
- file(RELATIVE_PATH _JAVA_CLASS_FILE ${CMAKE_JAVA_CLASS_OUTPUT_PATH} ${_JAVA_GLOBBED_FILE})
- set(_JAVA_CLASS_FILES ${_JAVA_CLASS_FILES}${_JAVA_CLASS_FILE}\n)
- endforeach(_JAVA_GLOBBED_FILE ${_JAVA_GLOBBED_FILES})
-
- # write to file
- file(WRITE ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist ${_JAVA_CLASS_FILES})
-
- else (EXISTS "${CMAKE_JAVA_CLASS_OUTPUT_PATH}")
- message(SEND_ERROR "FATAL: Java class output path doesn't exist")
- endif (EXISTS "${CMAKE_JAVA_CLASS_OUTPUT_PATH}")
-else (CMAKE_JAVA_CLASS_OUTPUT_PATH)
- message(SEND_ERROR "FATAL: Can't find CMAKE_JAVA_CLASS_OUTPUT_PATH")
-endif (CMAKE_JAVA_CLASS_OUTPUT_PATH)
diff --git a/cmake/UseJavaSymlinks.cmake b/cmake/UseJavaSymlinks.cmake
deleted file mode 100644
index c66ee1ea..00000000
--- a/cmake/UseJavaSymlinks.cmake
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Helper script for UseJava.cmake
-#
-
-#=============================================================================
-# Copyright 2010-2011 Andreas schneider <asn@redhat.com>
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distribute this file outside of CMake, substitute the full
-# License text for the above reference.)
-
-if (UNIX AND _JAVA_TARGET_OUTPUT_LINK)
- if (_JAVA_TARGET_OUTPUT_NAME)
- find_program(LN_EXECUTABLE
- NAMES
- ln
- )
-
- execute_process(
- COMMAND ${LN_EXECUTABLE} -sf "${_JAVA_TARGET_OUTPUT_NAME}" "${_JAVA_TARGET_OUTPUT_LINK}"
- WORKING_DIRECTORY ${_JAVA_TARGET_DIR}
- )
- else (_JAVA_TARGET_OUTPUT_NAME)
- message(SEND_ERROR "FATAL: Can't find _JAVA_TARGET_OUTPUT_NAME")
- endif (_JAVA_TARGET_OUTPUT_NAME)
-endif (UNIX AND _JAVA_TARGET_OUTPUT_LINK)
diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp
index 6e37e3d8..847d897e 100644
--- a/launcher/InstanceList.cpp
+++ b/launcher/InstanceList.cpp
@@ -38,6 +38,10 @@
#include "ExponentialSeries.h"
#include "WatchLock.h"
+#ifdef Q_OS_WIN32
+#include <Windows.h>
+#endif
+
const static int GROUP_FILE_FORMAT_VERSION = 1;
InstanceList::InstanceList(SettingsObjectPtr settings, const QString & instDir, QObject *parent)
@@ -851,13 +855,18 @@ Task * InstanceList::wrapInstanceTask(InstanceTask * task)
QString InstanceList::getStagedInstancePath()
{
QString key = QUuid::createUuid().toString();
- QString relPath = FS::PathCombine("_LAUNCHER_TEMP/" , key);
+ QString tempDir = ".LAUNCHER_TEMP/";
+ QString relPath = FS::PathCombine(tempDir, key);
QDir rootPath(m_instDir);
auto path = FS::PathCombine(m_instDir, relPath);
if(!rootPath.mkpath(relPath))
{
return QString();
}
+#ifdef Q_OS_WIN32
+ auto tempPath = FS::PathCombine(m_instDir, tempDir);
+ SetFileAttributesA(tempPath.toStdString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
+#endif
return path;
}
diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp
index 4cb62e69..002c08b9 100644
--- a/launcher/LaunchController.cpp
+++ b/launcher/LaunchController.cpp
@@ -93,7 +93,7 @@ void LaunchController::decideAccount()
auto reply = CustomMessageBox::selectable(
m_parentWidget,
tr("No Accounts"),
- tr("In order to play Minecraft, you must have at least one Mojang or Minecraft "
+ tr("In order to play Minecraft, you must have at least one Mojang or Microsoft "
"account logged in. "
"Would you like to open the account manager to add an account now?"),
QMessageBox::Information,
diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp
index 584edd69..c269d10a 100644
--- a/launcher/icons/IconList.cpp
+++ b/launcher/icons/IconList.cpp
@@ -36,7 +36,7 @@ IconList::IconList(const QStringList &builtinPaths, QString path, QObject *paren
auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name);
for (auto file_info : file_info_list)
{
- builtinNames.insert(file_info.baseName());
+ builtinNames.insert(file_info.completeBaseName());
}
}
for(auto & builtinName : builtinNames)
@@ -51,6 +51,9 @@ IconList::IconList(const QStringList &builtinPaths, QString path, QObject *paren
connect(m_watcher.get(), SIGNAL(fileChanged(QString)), SLOT(fileChanged(QString)));
directoryChanged(path);
+
+ // Forces the UI to update, so that lengthy icon names are shown properly from the start
+ emit iconUpdated({});
}
void IconList::directoryChanged(const QString &path)
@@ -94,7 +97,13 @@ void IconList::directoryChanged(const QString &path)
{
qDebug() << "Removing " << remove;
QFileInfo rmfile(remove);
- QString key = rmfile.baseName();
+ QString key = rmfile.completeBaseName();
+
+ QString suffix = rmfile.suffix();
+ // The icon doesnt have a suffix, but it can have other .s in the name, so we account for those as well
+ if (suffix != "jpeg" && suffix != "png" && suffix != "jpg" && suffix != "ico" && suffix != "svg" && suffix != "gif")
+ key = rmfile.fileName();
+
int idx = getIconIndex(key);
if (idx == -1)
continue;
@@ -117,8 +126,15 @@ void IconList::directoryChanged(const QString &path)
for (auto add : to_add)
{
qDebug() << "Adding " << add;
+
QFileInfo addfile(add);
- QString key = addfile.baseName();
+ QString key = addfile.completeBaseName();
+
+ QString suffix = addfile.suffix();
+ // The icon doesnt have a suffix, but it can have other .s in the name, so we account for those as well
+ if (suffix != "jpeg" && suffix != "png" && suffix != "jpg" && suffix != "ico" && suffix != "svg" && suffix != "gif")
+ key = addfile.fileName();
+
if (addIcon(key, QString(), addfile.filePath(), IconType::FileBased))
{
m_watcher->addPath(add);
@@ -133,7 +149,7 @@ void IconList::fileChanged(const QString &path)
QFileInfo checkfile(path);
if (!checkfile.exists())
return;
- QString key = checkfile.baseName();
+ QString key = checkfile.completeBaseName();
int idx = getIconIndex(key);
if (idx == -1)
return;
diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp
index 3ba79178..e20dc24c 100644
--- a/launcher/minecraft/MinecraftInstance.cpp
+++ b/launcher/minecraft/MinecraftInstance.cpp
@@ -162,6 +162,11 @@ MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsO
m_settings->registerSetting("JoinServerOnLaunch", false);
m_settings->registerSetting("JoinServerOnLaunchAddress", "");
+ // Miscellaneous
+ auto miscellaneousOverride = m_settings->registerSetting("OverrideMiscellaneous", false);
+ m_settings->registerOverride(globalSettings->getSetting("CloseAfterLaunch"), miscellaneousOverride);
+ m_settings->registerOverride(globalSettings->getSetting("QuitAfterGameStop"), miscellaneousOverride);
+
m_components.reset(new PackProfile(this));
}
@@ -984,7 +989,7 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
{
process->setCensorFilter(createCensorFilterFromSession(session));
}
- if(APPLICATION->settings()->get("QuitAfterGameStop").toBool())
+ if(m_settings->get("QuitAfterGameStop").toBool())
{
auto step = new QuitAfterGameStop(pptr);
process->appendStep(step);
diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp
index 173f29b5..d7010355 100644
--- a/launcher/minecraft/launch/LauncherPartLaunch.cpp
+++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp
@@ -25,7 +25,8 @@
LauncherPartLaunch::LauncherPartLaunch(LaunchTask *parent) : LaunchStep(parent)
{
- if (APPLICATION->settings()->get("CloseAfterLaunch").toBool())
+ auto instance = parent->instance();
+ if (instance->settings()->get("CloseAfterLaunch").toBool())
{
std::shared_ptr<QMetaObject::Connection> connection{new QMetaObject::Connection};
*connection = connect(&m_process, &LoggedProcess::log, this, [=](QStringList lines, MessageLevel::Enum level) {
@@ -168,7 +169,8 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state)
}
case LoggedProcess::Finished:
{
- if (APPLICATION->settings()->get("CloseAfterLaunch").toBool())
+ auto instance = m_parent->instance();
+ if (instance->settings()->get("CloseAfterLaunch").toBool())
APPLICATION->showMainWindow();
m_parent->setPid(-1);
diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp
index 3889a935..95924a68 100644
--- a/launcher/modplatform/flame/FileResolvingTask.cpp
+++ b/launcher/modplatform/flame/FileResolvingTask.cpp
@@ -1,14 +1,9 @@
#include "FileResolvingTask.h"
#include "Json.h"
-namespace {
- const char * metabase = "https://cursemeta.dries007.net";
-}
-
Flame::FileResolvingTask::FileResolvingTask(shared_qobject_ptr<QNetworkAccessManager> network, Flame::Manifest& toProcess)
: m_network(network), m_toProcess(toProcess)
-{
-}
+{}
void Flame::FileResolvingTask::executeTask()
{
@@ -17,14 +12,13 @@ void Flame::FileResolvingTask::executeTask()
m_dljob = new NetJob("Mod id resolver", m_network);
results.resize(m_toProcess.files.size());
int index = 0;
- for(auto & file: m_toProcess.files)
- {
+ for (auto& file : m_toProcess.files) {
auto projectIdStr = QString::number(file.projectId);
auto fileIdStr = QString::number(file.fileId);
- QString metaurl = QString("%1/%2/%3.json").arg(metabase, projectIdStr, fileIdStr);
+ QString metaurl = QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(projectIdStr, fileIdStr);
auto dl = Net::Download::makeByteArray(QUrl(metaurl), &results[index]);
m_dljob->addNetAction(dl);
- index ++;
+ index++;
}
connect(m_dljob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::netJobFinished);
m_dljob->start();
@@ -34,16 +28,11 @@ void Flame::FileResolvingTask::netJobFinished()
{
bool failed = false;
int index = 0;
- for(auto & bytes: results)
- {
- auto & out = m_toProcess.files[index];
- try
- {
+ for (auto& bytes : results) {
+ auto& out = m_toProcess.files[index];
+ try {
failed &= (!out.parseFromBytes(bytes));
- }
- catch (const JSONValidationError &e)
- {
-
+ } catch (const JSONValidationError& e) {
qCritical() << "Resolving of" << out.projectId << out.fileId << "failed because of a parsing error:";
qCritical() << e.cause();
qCritical() << "JSON:";
@@ -52,12 +41,9 @@ void Flame::FileResolvingTask::netJobFinished()
}
index++;
}
- if(!failed)
- {
+ if (!failed) {
emitSucceeded();
- }
- else
- {
+ } else {
emitFailed(tr("Some mod ID resolving tasks failed."));
}
}
diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h
index ce02df65..61628e60 100644
--- a/launcher/modplatform/flame/FlameAPI.h
+++ b/launcher/modplatform/flame/FlameAPI.h
@@ -4,32 +4,52 @@
class FlameAPI : public NetworkModAPI {
private:
+ inline auto getSortFieldInt(QString sortString) const -> int
+ {
+ return sortString == "Featured" ? 1
+ : sortString == "Popularity" ? 2
+ : sortString == "LastUpdated" ? 3
+ : sortString == "Name" ? 4
+ : sortString == "Author" ? 5
+ : sortString == "TotalDownloads" ? 6
+ : sortString == "Category" ? 7
+ : sortString == "GameVersion" ? 8
+ : 1;
+ }
+
+ private:
inline auto getModSearchURL(SearchArgs& args) const -> QString override
{
auto gameVersionStr = args.versions.size() != 0 ? QString("gameVersion=%1").arg(args.versions.front().toString()) : QString();
return QString(
- "https://addons-ecs.forgesvc.net/api/v2/addon/search?"
+ "https://api.curseforge.com/v1/mods/search?"
"gameId=432&"
- "categoryId=0&"
- "sectionId=6&"
+ "classId=6&"
"index=%1&"
"pageSize=25&"
"searchFilter=%2&"
- "sort=%3&"
+ "sortField=%3&"
+ "sortOrder=desc&"
"modLoaderType=%4&"
"%5")
.arg(args.offset)
.arg(args.search)
- .arg(args.sorting)
+ .arg(getSortFieldInt(args.sorting))
.arg(getMappedModLoader(args.mod_loader))
.arg(gameVersionStr);
};
inline auto getVersionsURL(VersionSearchArgs& args) const -> QString override
{
- return QString("https://addons-ecs.forgesvc.net/api/v2/addon/%1/files").arg(args.addonId);
+ QString gameVersionQuery = args.mcVersions.size() == 1 ? QString("gameVersion=%1&").arg(args.mcVersions.front().toString()) : "";
+ QString modLoaderQuery = QString("modLoaderType=%1&").arg(getMappedModLoader(args.loader));
+
+ return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&%2%3")
+ .arg(args.addonId)
+ .arg(gameVersionQuery)
+ .arg(modLoaderQuery);
};
public:
diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp
index c7b86b5c..ba0824cf 100644
--- a/launcher/modplatform/flame/FlameModIndex.cpp
+++ b/launcher/modplatform/flame/FlameModIndex.cpp
@@ -10,23 +10,12 @@ void FlameMod::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj)
{
pack.addonId = Json::requireInteger(obj, "id");
pack.name = Json::requireString(obj, "name");
- pack.websiteUrl = Json::ensureString(obj, "websiteUrl", "");
+ pack.websiteUrl = Json::ensureString(Json::ensureObject(obj, "links"), "websiteUrl", "");
pack.description = Json::ensureString(obj, "summary", "");
- bool thumbnailFound = false;
- auto attachments = Json::requireArray(obj, "attachments");
- for (auto attachmentRaw : attachments) {
- auto attachmentObj = Json::requireObject(attachmentRaw);
- bool isDefault = attachmentObj.value("isDefault").toBool(false);
- if (isDefault) {
- thumbnailFound = true;
- pack.logoName = Json::requireString(attachmentObj, "title");
- pack.logoUrl = Json::requireString(attachmentObj, "thumbnailUrl");
- break;
- }
- }
-
- if (!thumbnailFound) { throw JSONValidationError(QString("Pack without an icon, skipping: %1").arg(pack.name)); }
+ QJsonObject logo = Json::requireObject(obj, "logo");
+ pack.logoName = Json::requireString(logo, "title");
+ pack.logoUrl = Json::requireString(logo, "thumbnailUrl");
auto authors = Json::requireArray(obj, "authors");
for (auto authorIter : authors) {
@@ -45,18 +34,22 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
{
QVector<ModPlatform::IndexedVersion> unsortedVersions;
auto profile = (dynamic_cast<MinecraftInstance*>(inst))->getPackProfile();
- bool hasFabric = FlameAPI::getMappedModLoader(profile->getModLoader()) == ModAPI::Fabric;
QString mcVersion = profile->getComponentVersion("net.minecraft");
for (auto versionIter : arr) {
auto obj = versionIter.toObject();
- auto versionArray = Json::requireArray(obj, "gameVersion");
- if (versionArray.isEmpty()) { continue; }
+ auto versionArray = Json::requireArray(obj, "gameVersions");
+ if (versionArray.isEmpty()) {
+ continue;
+ }
ModPlatform::IndexedVersion file;
for (auto mcVer : versionArray) {
- file.mcVersion.append(mcVer.toString());
+ auto str = mcVer.toString();
+
+ if (str.contains('.'))
+ file.mcVersion.append(str);
}
file.addonId = pack.addonId;
@@ -66,28 +59,9 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
file.downloadUrl = Json::requireString(obj, "downloadUrl");
file.fileName = Json::requireString(obj, "fileName");
- auto modules = Json::requireArray(obj, "modules");
- bool is_valid_fabric_version = false;
- for (auto m : modules) {
- auto fname = Json::requireString(m.toObject(), "foldername");
- // FIXME: This does not work properly when a mod supports more than one mod loader, since
- // FIXME: This also doesn't deal with Quilt mods at the moment
- // they bundle the meta files for all of them in the same arquive, even when that version
- // doesn't support the given mod loader.
- if (hasFabric) {
- if (fname == "fabric.mod.json") {
- is_valid_fabric_version = true;
- break;
- }
- } else
- break;
- // NOTE: Since we're not validating forge versions, we can just skip this loop.
- }
-
- if (hasFabric && !is_valid_fabric_version) continue;
-
unsortedVersions.append(file);
}
+
auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool {
// dates are in RFC 3339 format
return a.date > b.date;
diff --git a/launcher/modplatform/flame/FlamePackIndex.cpp b/launcher/modplatform/flame/FlamePackIndex.cpp
index 3d8ea22a..ac24c647 100644
--- a/launcher/modplatform/flame/FlamePackIndex.cpp
+++ b/launcher/modplatform/flame/FlamePackIndex.cpp
@@ -2,76 +2,63 @@
#include "Json.h"
-void Flame::loadIndexedPack(Flame::IndexedPack & pack, QJsonObject & obj)
+void Flame::loadIndexedPack(Flame::IndexedPack& pack, QJsonObject& obj)
{
pack.addonId = Json::requireInteger(obj, "id");
pack.name = Json::requireString(obj, "name");
- pack.websiteUrl = Json::ensureString(obj, "websiteUrl", "");
+ pack.websiteUrl = Json::ensureString(Json::ensureObject(obj, "links"), "websiteUrl", "");
pack.description = Json::ensureString(obj, "summary", "");
- bool thumbnailFound = false;
- auto attachments = Json::requireArray(obj, "attachments");
- for(auto attachmentRaw: attachments) {
- auto attachmentObj = Json::requireObject(attachmentRaw);
- bool isDefault = attachmentObj.value("isDefault").toBool(false);
- if(isDefault) {
- thumbnailFound = true;
- pack.logoName = Json::requireString(attachmentObj, "title");
- pack.logoUrl = Json::requireString(attachmentObj, "thumbnailUrl");
- break;
- }
- }
-
- if(!thumbnailFound) {
- throw JSONValidationError(QString("Pack without an icon, skipping: %1").arg(pack.name));
- }
+ auto logo = Json::requireObject(obj, "logo");
+ pack.logoName = Json::requireString(logo, "title");
+ pack.logoUrl = Json::requireString(logo, "thumbnailUrl");
auto authors = Json::requireArray(obj, "authors");
- for(auto authorIter: authors) {
+ for (auto authorIter : authors) {
auto author = Json::requireObject(authorIter);
Flame::ModpackAuthor packAuthor;
packAuthor.name = Json::requireString(author, "name");
packAuthor.url = Json::requireString(author, "url");
pack.authors.append(packAuthor);
}
- int defaultFileId = Json::requireInteger(obj, "defaultFileId");
+ int defaultFileId = Json::requireInteger(obj, "mainFileId");
bool found = false;
// check if there are some files before adding the pack
auto files = Json::requireArray(obj, "latestFiles");
- for(auto fileIter: files) {
+ for (auto fileIter : files) {
auto file = Json::requireObject(fileIter);
int id = Json::requireInteger(file, "id");
// NOTE: for now, ignore everything that's not the default...
- if(id != defaultFileId) {
+ if (id != defaultFileId) {
continue;
}
- auto versionArray = Json::requireArray(file, "gameVersion");
- if(versionArray.size() < 1) {
+ auto versionArray = Json::requireArray(file, "gameVersions");
+ if (versionArray.size() < 1) {
continue;
}
found = true;
break;
}
- if(!found) {
+ if (!found) {
throw JSONValidationError(QString("Pack with no good file, skipping: %1").arg(pack.name));
}
}
-void Flame::loadIndexedPackVersions(Flame::IndexedPack & pack, QJsonArray & arr)
+void Flame::loadIndexedPackVersions(Flame::IndexedPack& pack, QJsonArray& arr)
{
QVector<Flame::IndexedVersion> unsortedVersions;
- for(auto versionIter: arr) {
+ for (auto versionIter : arr) {
auto version = Json::requireObject(versionIter);
- Flame::IndexedVersion file;
+ Flame::IndexedVersion file;
file.addonId = pack.addonId;
file.fileId = Json::requireInteger(version, "id");
- auto versionArray = Json::requireArray(version, "gameVersion");
- if(versionArray.size() < 1) {
+ auto versionArray = Json::requireArray(version, "gameVersions");
+ if (versionArray.size() < 1) {
continue;
}
@@ -82,10 +69,7 @@ void Flame::loadIndexedPackVersions(Flame::IndexedPack & pack, QJsonArray & arr)
unsortedVersions.append(file);
}
- auto orderSortPredicate = [](const IndexedVersion & a, const IndexedVersion & b) -> bool
- {
- return a.fileId > b.fileId;
- };
+ auto orderSortPredicate = [](const IndexedVersion& a, const IndexedVersion& b) -> bool { return a.fileId > b.fileId; };
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
pack.versions = unsortedVersions;
pack.versionsLoaded = true;
diff --git a/launcher/modplatform/flame/PackManifest.cpp b/launcher/modplatform/flame/PackManifest.cpp
index b928fd16..e4f90c1a 100644
--- a/launcher/modplatform/flame/PackManifest.cpp
+++ b/launcher/modplatform/flame/PackManifest.cpp
@@ -1,28 +1,27 @@
#include "PackManifest.h"
#include "Json.h"
-static void loadFileV1(Flame::File & f, QJsonObject & file)
+static void loadFileV1(Flame::File& f, QJsonObject& file)
{
f.projectId = Json::requireInteger(file, "projectID");
f.fileId = Json::requireInteger(file, "fileID");
f.required = Json::ensureBoolean(file, QString("required"), true);
}
-static void loadModloaderV1(Flame::Modloader & m, QJsonObject & modLoader)
+static void loadModloaderV1(Flame::Modloader& m, QJsonObject& modLoader)
{
m.id = Json::requireString(modLoader, "id");
m.primary = Json::ensureBoolean(modLoader, QString("primary"), false);
}
-static void loadMinecraftV1(Flame::Minecraft & m, QJsonObject & minecraft)
+static void loadMinecraftV1(Flame::Minecraft& m, QJsonObject& minecraft)
{
m.version = Json::requireString(minecraft, "version");
// extra libraries... apparently only used for a custom Minecraft launcher in the 1.2.5 FTB retro pack
// intended use is likely hardcoded in the 'Flame' client, the manifest says nothing
m.libraries = Json::ensureString(minecraft, QString("libraries"), QString());
auto arr = Json::ensureArray(minecraft, "modLoaders", QJsonArray());
- for (QJsonValueRef item : arr)
- {
+ for (QJsonValueRef item : arr) {
auto obj = Json::requireObject(item);
Flame::Modloader loader;
loadModloaderV1(loader, obj);
@@ -30,16 +29,15 @@ static void loadMinecraftV1(Flame::Minecraft & m, QJsonObject & minecraft)
}
}
-static void loadManifestV1(Flame::Manifest & m, QJsonObject & manifest)
+static void loadManifestV1(Flame::Manifest& m, QJsonObject& manifest)
{
auto mc = Json::requireObject(manifest, "minecraft");
loadMinecraftV1(m.minecraft, mc);
m.name = Json::ensureString(manifest, QString("name"), "Unnamed");
m.version = Json::ensureString(manifest, QString("version"), QString());
- m.author = Json::ensureString(manifest, QString("author"), "Anonymous Coward");
+ m.author = Json::ensureString(manifest, QString("author"), "Anonymous");
auto arr = Json::ensureArray(manifest, "files", QJsonArray());
- for (QJsonValueRef item : arr)
- {
+ for (QJsonValueRef item : arr) {
auto obj = Json::requireObject(item);
Flame::File file;
loadFileV1(file, obj);
@@ -48,18 +46,16 @@ static void loadManifestV1(Flame::Manifest & m, QJsonObject & manifest)
m.overrides = Json::ensureString(manifest, "overrides", "overrides");
}
-void Flame::loadManifest(Flame::Manifest & m, const QString &filepath)
+void Flame::loadManifest(Flame::Manifest& m, const QString& filepath)
{
auto doc = Json::requireDocument(filepath);
auto obj = Json::requireObject(doc);
m.manifestType = Json::requireString(obj, "manifestType");
- if(m.manifestType != "minecraftModpack")
- {
+ if (m.manifestType != "minecraftModpack") {
throw JSONValidationError("Not a modpack manifest!");
}
m.manifestVersion = Json::requireInteger(obj, "manifestVersion");
- if(m.manifestVersion != 1)
- {
+ if (m.manifestVersion != 1) {
throw JSONValidationError(QString("Unknown manifest version (%1)").arg(m.manifestVersion));
}
loadManifestV1(m, obj);
@@ -68,59 +64,30 @@ void Flame::loadManifest(Flame::Manifest & m, const QString &filepath)
bool Flame::File::parseFromBytes(const QByteArray& bytes)
{
auto doc = Json::requireDocument(bytes);
- auto obj = Json::requireObject(doc);
- // result code signifies true failure.
- if(obj.contains("code"))
- {
- qCritical() << "Resolving of" << projectId << fileId << "failed because of a negative result:";
- qCritical() << bytes;
- return false;
+ if (!doc.isObject()) {
+ throw JSONValidationError(QString("data is not an object? that's not supposed to happen"));
}
- fileName = Json::requireString(obj, "FileNameOnDisk");
- QString rawUrl = Json::requireString(obj, "DownloadURL");
+ auto obj = Json::ensureObject(doc.object(), "data");
+
+ fileName = Json::requireString(obj, "fileName");
+
+ QString rawUrl = Json::requireString(obj, "downloadUrl");
url = QUrl(rawUrl, QUrl::TolerantMode);
- if(!url.isValid())
- {
+ if (!url.isValid()) {
throw JSONValidationError(QString("Invalid URL: %1").arg(rawUrl));
}
// This is a piece of a Flame project JSON pulled out into the file metadata (here) for convenience
// It is also optional
- QJsonObject projObj = Json::ensureObject(obj, "_Project", {});
- if(!projObj.isEmpty())
- {
- QString strType = Json::ensureString(projObj, "PackageType", "mod").toLower();
- if(strType == "singlefile")
- {
- type = File::Type::SingleFile;
- }
- else if(strType == "ctoc")
- {
- type = File::Type::Ctoc;
- }
- else if(strType == "cmod2")
- {
- type = File::Type::Cmod2;
- }
- else if(strType == "mod")
- {
- type = File::Type::Mod;
- }
- else if(strType == "folder")
- {
- type = File::Type::Folder;
- }
- else if(strType == "modpack")
- {
- type = File::Type::Modpack;
- }
- else
- {
- qCritical() << "Resolving of" << projectId << fileId << "failed because of unknown file type:" << strType;
- type = File::Type::Unknown;
- return false;
- }
- targetFolder = Json::ensureString(projObj, "Path", "mods");
+ type = File::Type::SingleFile;
+
+ if (fileName.endsWith(".zip")) {
+ // this is probably a resource pack
+ targetFolder = "resourcepacks";
+ } else {
+ // this is probably a mod, dunno what else could modpacks download
+ targetFolder = "mods";
}
+
resolved = true;
return true;
}
diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp
index b314573f..65cc8f67 100644
--- a/launcher/net/Download.cpp
+++ b/launcher/net/Download.cpp
@@ -15,27 +15,27 @@
#include "Download.h"
-#include <QFileInfo>
#include <QDateTime>
#include <QDebug>
+#include <QFileInfo>
-#include "FileSystem.h"
+#include "ByteArraySink.h"
#include "ChecksumValidator.h"
+#include "FileSystem.h"
#include "MetaCacheSink.h"
-#include "ByteArraySink.h"
#include "BuildConfig.h"
namespace Net {
-Download::Download():NetAction()
+Download::Download() : NetAction()
{
m_status = Job_NotStarted;
}
Download::Ptr Download::makeCached(QUrl url, MetaEntryPtr entry, Options options)
{
- Download * dl = new Download();
+ Download* dl = new Download();
dl->m_url = url;
dl->m_options = options;
auto md5Node = new ChecksumValidator(QCryptographicHash::Md5);
@@ -45,9 +45,9 @@ Download::Ptr Download::makeCached(QUrl url, MetaEntryPtr entry, Options options
return dl;
}
-Download::Ptr Download::makeByteArray(QUrl url, QByteArray *output, Options options)
+Download::Ptr Download::makeByteArray(QUrl url, QByteArray* output, Options options)
{
- Download * dl = new Download();
+ Download* dl = new Download();
dl->m_url = url;
dl->m_options = options;
dl->m_sink.reset(new ByteArraySink(output));
@@ -56,30 +56,28 @@ Download::Ptr Download::makeByteArray(QUrl url, QByteArray *output, Options opti
Download::Ptr Download::makeFile(QUrl url, QString path, Options options)
{
- Download * dl = new Download();
+ Download* dl = new Download();
dl->m_url = url;
dl->m_options = options;
dl->m_sink.reset(new FileSink(path));
return dl;
}
-void Download::addValidator(Validator * v)
+void Download::addValidator(Validator* v)
{
m_sink->addValidator(v);
}
void Download::startImpl()
{
- if(m_status == Job_Aborted)
- {
+ if (m_status == Job_Aborted) {
qWarning() << "Attempt to start an aborted Download:" << m_url.toString();
emit aborted(m_index_within_job);
return;
}
QNetworkRequest request(m_url);
m_status = m_sink->init(request);
- switch(m_status)
- {
+ switch (m_status) {
case Job_Finished:
emit succeeded(m_index_within_job);
qDebug() << "Download cache hit " << m_url.toString();
@@ -87,7 +85,7 @@ void Download::startImpl()
case Job_InProgress:
qDebug() << "Downloading " << m_url.toString();
break;
- case Job_Failed_Proceed: // this is meaningless in this context. We do need a sink.
+ case Job_Failed_Proceed: // this is meaningless in this context. We do need a sink.
case Job_NotStarted:
case Job_Failed:
emit failed(m_index_within_job);
@@ -97,8 +95,11 @@ void Download::startImpl()
}
request.setHeader(QNetworkRequest::UserAgentHeader, BuildConfig.USER_AGENT);
+ if (request.url().host().contains("api.curseforge.com")) {
+ request.setRawHeader("x-api-key", BuildConfig.CURSEFORGE_API_KEY.toUtf8());
+ };
- QNetworkReply *rep = m_network->get(request);
+ QNetworkReply* rep = m_network->get(request);
m_reply.reset(rep);
connect(rep, SIGNAL(downloadProgress(qint64, qint64)), SLOT(downloadProgress(qint64, qint64)));
@@ -117,17 +118,12 @@ void Download::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
void Download::downloadError(QNetworkReply::NetworkError error)
{
- if(error == QNetworkReply::OperationCanceledError)
- {
+ if (error == QNetworkReply::OperationCanceledError) {
qCritical() << "Aborted " << m_url.toString();
m_status = Job_Aborted;
- }
- else
- {
- if(m_options & Option::AcceptLocalFiles)
- {
- if(m_sink->hasLocalData())
- {
+ } else {
+ if (m_options & Option::AcceptLocalFiles) {
+ if (m_sink->hasLocalData()) {
m_status = Job_Failed_Proceed;
return;
}
@@ -138,11 +134,10 @@ void Download::downloadError(QNetworkReply::NetworkError error)
}
}
-void Download::sslErrors(const QList<QSslError> & errors)
+void Download::sslErrors(const QList<QSslError>& errors)
{
int i = 1;
- for (auto error : errors)
- {
+ for (auto error : errors) {
qCritical() << "Download" << m_url.toString() << "SSL Error #" << i << " : " << error.errorString();
auto cert = error.certificate();
qCritical() << "Certificate in question:\n" << cert.toText();
@@ -153,33 +148,27 @@ void Download::sslErrors(const QList<QSslError> & errors)
bool Download::handleRedirect()
{
QUrl redirect = m_reply->header(QNetworkRequest::LocationHeader).toUrl();
- if(!redirect.isValid())
- {
- if(!m_reply->hasRawHeader("Location"))
- {
+ if (!redirect.isValid()) {
+ if (!m_reply->hasRawHeader("Location")) {
// no redirect -> it's fine to continue
return false;
}
// there is a Location header, but it's not correct. we need to apply some workarounds...
QByteArray redirectBA = m_reply->rawHeader("Location");
- if(redirectBA.size() == 0)
- {
+ if (redirectBA.size() == 0) {
// empty, yet present redirect header? WTF?
return false;
}
QString redirectStr = QString::fromUtf8(redirectBA);
- if(redirectStr.startsWith("//"))
- {
+ if (redirectStr.startsWith("//")) {
/*
* IF the URL begins with //, we need to insert the URL scheme.
* See: https://bugreports.qt.io/browse/QTBUG-41061
* See: http://tools.ietf.org/html/rfc3986#section-4.2
*/
redirectStr = m_reply->url().scheme() + ":" + redirectStr;
- }
- else if(redirectStr.startsWith("/"))
- {
+ } else if (redirectStr.startsWith("/")) {
/*
* IF the URL begins with /, we need to process it as a relative URL
*/
@@ -193,16 +182,13 @@ bool Download::handleRedirect()
* FIXME: report Qt bug for this
*/
redirect = QUrl(redirectStr, QUrl::TolerantMode);
- if(!redirect.isValid())
- {
+ if (!redirect.isValid()) {
qWarning() << "Failed to parse redirect URL:" << redirectStr;
downloadError(QNetworkReply::ProtocolFailure);
return false;
}
qDebug() << "Fixed location header:" << redirect;
- }
- else
- {
+ } else {
qDebug() << "Location header:" << redirect;
}
@@ -212,35 +198,28 @@ bool Download::handleRedirect()
return true;
}
-
void Download::downloadFinished()
{
// handle HTTP redirection first
- if(handleRedirect())
- {
+ if (handleRedirect()) {
qDebug() << "Download redirected:" << m_url.toString();
return;
}
// if the download failed before this point ...
- if (m_status == Job_Failed_Proceed)
- {
+ if (m_status == Job_Failed_Proceed) {
qDebug() << "Download failed but we are allowed to proceed:" << m_url.toString();
m_sink->abort();
m_reply.reset();
emit succeeded(m_index_within_job);
return;
- }
- else if (m_status == Job_Failed)
- {
+ } else if (m_status == Job_Failed) {
qDebug() << "Download failed in previous step:" << m_url.toString();
m_sink->abort();
m_reply.reset();
emit failed(m_index_within_job);
return;
- }
- else if(m_status == Job_Aborted)
- {
+ } else if (m_status == Job_Aborted) {
qDebug() << "Download aborted in previous step:" << m_url.toString();
m_sink->abort();
m_reply.reset();
@@ -250,16 +229,14 @@ void Download::downloadFinished()
// make sure we got all the remaining data, if any
auto data = m_reply->readAll();
- if(data.size())
- {
+ if (data.size()) {
qDebug() << "Writing extra" << data.size() << "bytes to" << m_target_path;
m_status = m_sink->write(data);
}
// otherwise, finalize the whole graph
m_status = m_sink->finalize(*m_reply.get());
- if (m_status != Job_Finished)
- {
+ if (m_status != Job_Finished) {
qDebug() << "Download failed to finalize:" << m_url.toString();
m_sink->abort();
m_reply.reset();
@@ -273,32 +250,25 @@ void Download::downloadFinished()
void Download::downloadReadyRead()
{
- if(m_status == Job_InProgress)
- {
+ if (m_status == Job_InProgress) {
auto data = m_reply->readAll();
m_status = m_sink->write(data);
- if(m_status == Job_Failed)
- {
+ if (m_status == Job_Failed) {
qCritical() << "Failed to process response chunk for " << m_target_path;
}
// qDebug() << "Download" << m_url.toString() << "gained" << data.size() << "bytes";
- }
- else
- {
+ } else {
qCritical() << "Cannot write to " << m_target_path << ", illegal status" << m_status;
}
}
-}
+} // namespace Net
bool Net::Download::abort()
{
- if(m_reply)
- {
+ if (m_reply) {
m_reply->abort();
- }
- else
- {
+ } else {
m_status = Job_Aborted;
}
return true;
diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp
index 44eba369..f016dc76 100644
--- a/launcher/ui/MainWindow.cpp
+++ b/launcher/ui/MainWindow.cpp
@@ -238,6 +238,9 @@ public:
TranslatedAction actionREDDIT;
TranslatedAction actionAbout;
+ TranslatedAction actionNoAccountsAdded;
+ TranslatedAction actionNoDefaultAccount;
+
QVector<TranslatedToolButton *> all_toolbuttons;
QWidget *centralWidget = nullptr;
@@ -831,7 +834,7 @@ public:
QMetaObject::connectSlotsByName(MainWindow);
} // setupUi
- void retranslateUi(QMainWindow *MainWindow)
+ void retranslateUi(MainWindow *MainWindow)
{
QString winTitle = tr("%1 - Version %2", "Launcher - Version X").arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString());
MainWindow->setWindowTitle(winTitle);
@@ -851,6 +854,12 @@ public:
// submenu buttons
foldersMenuButton->setText(tr("Folders"));
helpMenuButton->setText(tr("Help"));
+
+ // playtime counter
+ if (MainWindow->m_statusCenter)
+ {
+ MainWindow->updateStatusCenter();
+ }
} // retranslateUi
};
@@ -953,6 +962,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
ui->mainToolBar->addWidget(spacer);
accountMenu = new QMenu(this);
+ // Use undocumented property... https://stackoverflow.com/questions/7121718/create-a-scrollbar-in-a-submenu-qt
+ accountMenu->setStyleSheet("QMenu { menu-scrollable: 1; }");
repopulateAccountsMenu();
@@ -1255,10 +1266,14 @@ void MainWindow::repopulateAccountsMenu()
if (accounts->count() <= 0)
{
- QAction *action = new QAction(tr("No accounts added!"), this);
- action->setEnabled(false);
- accountMenu->addAction(action);
- ui->profileMenu->addAction(action);
+ ui->all_actions.removeAll(&ui->actionNoAccountsAdded);
+ ui->actionNoAccountsAdded = TranslatedAction(this);
+ ui->actionNoAccountsAdded->setObjectName(QStringLiteral("actionNoAccountsAdded"));
+ ui->actionNoAccountsAdded.setTextId(QT_TRANSLATE_NOOP("MainWindow", "No accounts added!"));
+ ui->actionNoAccountsAdded->setEnabled(false);
+ accountMenu->addAction(ui->actionNoAccountsAdded);
+ ui->profileMenu->addAction(ui->actionNoAccountsAdded);
+ ui->all_actions.append(&ui->actionNoAccountsAdded);
}
else
{
@@ -1298,18 +1313,23 @@ void MainWindow::repopulateAccountsMenu()
accountMenu->addSeparator();
ui->profileMenu->addSeparator();
- QAction *action = new QAction(tr("No Default Account"), this);
- action->setCheckable(true);
- action->setIcon(APPLICATION->getThemedIcon("noaccount"));
- action->setData(-1);
- action->setShortcut(QKeySequence(tr("Ctrl+0")));
+ ui->all_actions.removeAll(&ui->actionNoDefaultAccount);
+ ui->actionNoDefaultAccount = TranslatedAction(this);
+ ui->actionNoDefaultAccount->setObjectName(QStringLiteral("actionNoDefaultAccount"));
+ ui->actionNoDefaultAccount.setTextId(QT_TRANSLATE_NOOP("MainWindow", "No Default Account"));
+ ui->actionNoDefaultAccount->setCheckable(true);
+ ui->actionNoDefaultAccount->setIcon(APPLICATION->getThemedIcon("noaccount"));
+ ui->actionNoDefaultAccount->setData(-1);
+ ui->actionNoDefaultAccount->setShortcut(QKeySequence(tr("Ctrl+0")));
if (!defaultAccount) {
- action->setChecked(true);
+ ui->actionNoDefaultAccount->setChecked(true);
}
- accountMenu->addAction(action);
- ui->profileMenu->addAction(action);
- connect(action, SIGNAL(triggered(bool)), SLOT(changeActiveAccount()));
+ accountMenu->addAction(ui->actionNoDefaultAccount);
+ ui->profileMenu->addAction(ui->actionNoDefaultAccount);
+ connect(ui->actionNoDefaultAccount, SIGNAL(triggered(bool)), SLOT(changeActiveAccount()));
+ ui->all_actions.append(&ui->actionNoDefaultAccount);
+ ui->actionNoDefaultAccount.retranslate();
accountMenu->addSeparator();
ui->profileMenu->addSeparator();
diff --git a/launcher/ui/dialogs/SkinUploadDialog.cpp b/launcher/ui/dialogs/SkinUploadDialog.cpp
index 6a5a324f..8d137afc 100644
--- a/launcher/ui/dialogs/SkinUploadDialog.cpp
+++ b/launcher/ui/dialogs/SkinUploadDialog.cpp
@@ -100,7 +100,8 @@ void SkinUploadDialog::on_buttonBox_accepted()
void SkinUploadDialog::on_skinBrowseBtn_clicked()
{
- QString raw_path = QFileDialog::getOpenFileName(this, tr("Select Skin Texture"), QString(), "*.png");
+ auto filter = QMimeDatabase().mimeTypeForName("image/png").filterString();
+ QString raw_path = QFileDialog::getOpenFileName(this, tr("Select Skin Texture"), QString(), filter);
if (raw_path.isEmpty() || !QFileInfo::exists(raw_path))
{
return;
diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp
index a48c4d69..b4562843 100644
--- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp
+++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp
@@ -101,6 +101,20 @@ void InstanceSettingsPage::applySettings()
{
SettingsObject::Lock lock(m_settings);
+ // Miscellaneous
+ bool miscellaneous = ui->miscellaneousSettingsBox->isChecked();
+ m_settings->set("OverrideMiscellaneous", miscellaneous);
+ if (miscellaneous)
+ {
+ m_settings->set("CloseAfterLaunch", ui->closeAfterLaunchCheck->isChecked());
+ m_settings->set("QuitAfterGameStop", ui->quitAfterGameStopCheck->isChecked());
+ }
+ else
+ {
+ m_settings->reset("CloseAfterLaunch");
+ m_settings->reset("QuitAfterGameStop");
+ }
+
// Console
bool console = ui->consoleSettingsBox->isChecked();
m_settings->set("OverrideConsole", console);
@@ -247,6 +261,11 @@ void InstanceSettingsPage::applySettings()
void InstanceSettingsPage::loadSettings()
{
+ // Miscellaneous
+ ui->miscellaneousSettingsBox->setChecked(m_settings->get("OverrideMiscellaneous").toBool());
+ ui->closeAfterLaunchCheck->setChecked(m_settings->get("CloseAfterLaunch").toBool());
+ ui->quitAfterGameStopCheck->setChecked(m_settings->get("QuitAfterGameStop").toBool());
+
// Console
ui->consoleSettingsBox->setChecked(m_settings->get("OverrideConsole").toBool());
ui->showConsoleCheck->setChecked(m_settings->get("ShowConsole").toBool());
diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui
index 5db2d147..cb66b3ce 100644
--- a/launcher/ui/pages/instance/InstanceSettingsPage.ui
+++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui
@@ -350,6 +350,35 @@
</widget>
</item>
<item>
+ <widget class="QGroupBox" name="miscellaneousSettingsBox">
+ <property name="title">
+ <string>Miscellaneous</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_12">
+ <item>
+ <widget class="QCheckBox" name="closeAfterLaunchCheck">
+ <property name="text">
+ <string>Close the launcher after game window opens</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="quitAfterGameStopCheck">
+ <property name="text">
+ <string>Quit the launcher after game window closes</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<spacer name="verticalSpacerMinecraft_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp
index e694ebe3..2cf17b32 100644
--- a/launcher/ui/pages/instance/ScreenshotsPage.cpp
+++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp
@@ -251,7 +251,7 @@ ScreenshotsPage::ScreenshotsPage(QString path, QWidget *parent)
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->setFilter(QDir::Files);
m_model->setReadOnly(false);
m_model->setNameFilters({"*.png"});
m_model->setNameFilterDisables(false);
@@ -343,6 +343,29 @@ void ScreenshotsPage::onItemActivated(QModelIndex index)
DesktopServices::openFile(info.absoluteFilePath());
}
+void ScreenshotsPage::onCurrentSelectionChanged(const QItemSelection &selected)
+{
+ bool allReadable = !selected.isEmpty();
+ bool allWritable = !selected.isEmpty();
+
+ for (auto index : selected.indexes())
+ {
+ if (!index.isValid())
+ break;
+ auto info = m_model->fileInfo(index);
+ if (!info.isReadable())
+ allReadable = false;
+ if (!info.isWritable())
+ allWritable = false;
+ }
+
+ ui->actionUpload->setEnabled(allReadable);
+ ui->actionCopy_Image->setEnabled(allReadable);
+ ui->actionCopy_File_s->setEnabled(allReadable);
+ ui->actionDelete->setEnabled(allWritable);
+ ui->actionRename->setEnabled(allWritable);
+}
+
void ScreenshotsPage::on_actionView_Folder_triggered()
{
DesktopServices::openDirectory(m_folder, true);
@@ -503,6 +526,8 @@ void ScreenshotsPage::openedImpl()
if(idx.isValid())
{
ui->listView->setModel(m_filterModel.get());
+ connect(ui->listView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ScreenshotsPage::onCurrentSelectionChanged);
+ onCurrentSelectionChanged(ui->listView->selectionModel()->selection()); // set initial button enable states
ui->listView->setRootIndex(m_filterModel->mapFromSource(idx));
}
else
diff --git a/launcher/ui/pages/instance/ScreenshotsPage.h b/launcher/ui/pages/instance/ScreenshotsPage.h
index 50cf1a17..c22706af 100644
--- a/launcher/ui/pages/instance/ScreenshotsPage.h
+++ b/launcher/ui/pages/instance/ScreenshotsPage.h
@@ -100,6 +100,7 @@ private slots:
void on_actionRename_triggered();
void on_actionView_Folder_triggered();
void onItemActivated(QModelIndex);
+ void onCurrentSelectionChanged(const QItemSelection &selected);
void ShowContextMenu(const QPoint &pos);
private:
diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp
index 487bf77b..1b53dd40 100644
--- a/launcher/ui/pages/modplatform/ImportPage.cpp
+++ b/launcher/ui/pages/modplatform/ImportPage.cpp
@@ -143,7 +143,8 @@ void ImportPage::setUrl(const QString& url)
void ImportPage::on_modpackBtn_clicked()
{
- const QUrl url = QFileDialog::getOpenFileUrl(this, tr("Choose modpack"), modpackUrl(), tr("Zip (*.zip)"));
+ auto filter = QMimeDatabase().mimeTypeForName("application/zip").filterString();
+ const QUrl url = QFileDialog::getOpenFileUrl(this, tr("Choose modpack"), modpackUrl(), filter);
if (url.isValid())
{
if (url.isLocalFile())
diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp
index e82e1cdb..540ee2fd 100644
--- a/launcher/ui/pages/modplatform/ModModel.cpp
+++ b/launcher/ui/pages/modplatform/ModModel.cpp
@@ -21,7 +21,8 @@ auto ListModel::debugName() const -> QString
void ListModel::fetchMore(const QModelIndex& parent)
{
- if (parent.isValid()) return;
+ if (parent.isValid())
+ return;
if (nextSearchOffset == 0) {
qWarning() << "fetchMore with 0 offset is wrong...";
return;
@@ -32,7 +33,9 @@ void ListModel::fetchMore(const QModelIndex& parent)
auto ListModel::data(const QModelIndex& index, int role) const -> QVariant
{
int pos = index.row();
- if (pos >= modpacks.size() || pos < 0 || !index.isValid()) { return QString("INVALID INDEX %1").arg(pos); }
+ if (pos >= modpacks.size() || pos < 0 || !index.isValid()) {
+ return QString("INVALID INDEX %1").arg(pos);
+ }
ModPlatform::IndexedPack pack = modpacks.at(pos);
if (role == Qt::DisplayRole) {
@@ -46,7 +49,9 @@ auto ListModel::data(const QModelIndex& index, int role) const -> QVariant
}
return pack.description;
} else if (role == Qt::DecorationRole) {
- if (m_logoMap.contains(pack.logoName)) { return (m_logoMap.value(pack.logoName)); }
+ if (m_logoMap.contains(pack.logoName)) {
+ return (m_logoMap.value(pack.logoName));
+ }
QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder");
((ListModel*)this)->requestLogo(pack.logoName, pack.logoUrl);
return icon;
@@ -63,16 +68,15 @@ void ListModel::requestModVersions(ModPlatform::IndexedPack const& current)
{
auto profile = (dynamic_cast<MinecraftInstance*>((dynamic_cast<ModPage*>(parent()))->m_instance))->getPackProfile();
- m_parent->apiProvider()->getVersions(this,
- { current.addonId.toString(), getMineVersions(), profile->getModLoader() });
+ m_parent->apiProvider()->getVersions(this, { current.addonId.toString(), getMineVersions(), profile->getModLoader() });
}
void ListModel::performPaginatedSearch()
{
auto profile = (dynamic_cast<MinecraftInstance*>((dynamic_cast<ModPage*>(parent()))->m_instance))->getPackProfile();
- m_parent->apiProvider()->searchMods(this,
- { nextSearchOffset, currentSearchTerm, getSorts()[currentSort], profile->getModLoader(), getMineVersions() });
+ m_parent->apiProvider()->searchMods(
+ this, { nextSearchOffset, currentSearchTerm, getSorts()[currentSort], profile->getModLoader(), getMineVersions() });
}
void ListModel::refresh()
@@ -93,11 +97,9 @@ void ListModel::refresh()
void ListModel::searchWithTerm(const QString& term, const int sort, const bool filter_changed)
{
- if (currentSearchTerm == term
- && currentSearchTerm.isNull() == term.isNull()
- && currentSort == sort
- && !filter_changed)
- { return; }
+ if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort && !filter_changed) {
+ return;
+ }
currentSearchTerm = term;
currentSort = sort;
@@ -118,7 +120,9 @@ void ListModel::getLogo(const QString& logo, const QString& logoUrl, LogoCallbac
void ListModel::requestLogo(QString logo, QString url)
{
- if (m_loadingLogos.contains(logo) || m_failedLogos.contains(logo)) { return; }
+ if (m_loadingLogos.contains(logo) || m_failedLogos.contains(logo)) {
+ return;
+ }
MetaEntryPtr entry =
APPLICATION->metacache()->resolveEntry(m_parent->metaEntryBase(), QString("logos/%1").arg(logo.section(".", 0, 0)));
@@ -129,7 +133,9 @@ void ListModel::requestLogo(QString logo, QString url)
QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath, job] {
job->deleteLater();
emit logoLoaded(logo, QIcon(fullPath));
- if (waitingCallbacks.contains(logo)) { waitingCallbacks.value(logo)(fullPath); }
+ if (waitingCallbacks.contains(logo)) {
+ waitingCallbacks.value(logo)(fullPath);
+ }
});
QObject::connect(job, &NetJob::failed, this, [this, logo, job] {
@@ -148,7 +154,9 @@ void ListModel::logoLoaded(QString logo, QIcon out)
m_loadingLogos.removeAll(logo);
m_logoMap.insert(logo, out);
for (int i = 0; i < modpacks.size(); i++) {
- if (modpacks[i].logoName == logo) { emit dataChanged(createIndex(i, 0), createIndex(i, 0), { Qt::DecorationRole }); }
+ if (modpacks[i].logoName == logo) {
+ emit dataChanged(createIndex(i, 0), createIndex(i, 0), { Qt::DecorationRole });
+ }
}
}
@@ -199,7 +207,9 @@ void ListModel::searchRequestFailed(QString reason)
// 409 Gone, notify user to update
QMessageBox::critical(nullptr, tr("Error"),
//: %1 refers to the launcher itself
- QString("%1 %2").arg(m_parent->displayName()).arg(tr("API version too old!\nPlease update %1!").arg(BuildConfig.LAUNCHER_NAME)));
+ QString("%1 %2")
+ .arg(m_parent->displayName())
+ .arg(tr("API version too old!\nPlease update %1!").arg(BuildConfig.LAUNCHER_NAME)));
}
jobPtr.reset();
@@ -218,9 +228,12 @@ void ListModel::searchRequestFailed(QString reason)
void ListModel::versionRequestSucceeded(QJsonDocument doc, QString addonId)
{
auto& current = m_parent->getCurrent();
- if (addonId != current.addonId) { return; }
+ if (addonId != current.addonId) {
+ return;
+ }
+
+ auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
- QJsonArray arr = doc.array();
try {
loadIndexedPackVersions(current, arr);
} catch (const JSONValidationError& e) {
diff --git a/launcher/ui/pages/modplatform/flame/FlameModModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModModel.cpp
index 905fb2dd..8de2e545 100644
--- a/launcher/ui/pages/modplatform/flame/FlameModModel.cpp
+++ b/launcher/ui/pages/modplatform/flame/FlameModModel.cpp
@@ -1,5 +1,5 @@
#include "FlameModModel.h"
-
+#include "Json.h"
#include "modplatform/flame/FlameModIndex.h"
namespace FlameMod {
@@ -19,7 +19,7 @@ void ListModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray&
auto ListModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
{
- return obj.array();
+ return Json::ensureArray(obj.object(), "data");
}
} // namespace FlameMod
diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp
index fe163cae..f97536e8 100644
--- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp
+++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp
@@ -1,6 +1,6 @@
#include "FlameModel.h"
-#include "Application.h"
#include <Json.h>
+#include "Application.h"
#include <MMCStrings.h>
#include <Version.h>
@@ -9,61 +9,46 @@
namespace Flame {
-ListModel::ListModel(QObject *parent) : QAbstractListModel(parent)
-{
-}
+ListModel::ListModel(QObject* parent) : QAbstractListModel(parent) {}
-ListModel::~ListModel()
-{
-}
+ListModel::~ListModel() {}
-int ListModel::rowCount(const QModelIndex &parent) const
+int ListModel::rowCount(const QModelIndex& parent) const
{
return modpacks.size();
}
-int ListModel::columnCount(const QModelIndex &parent) const
+int ListModel::columnCount(const QModelIndex& parent) const
{
return 1;
}
-QVariant ListModel::data(const QModelIndex &index, int role) const
+QVariant ListModel::data(const QModelIndex& index, int role) const
{
int pos = index.row();
- if(pos >= modpacks.size() || pos < 0 || !index.isValid())
- {
+ if (pos >= modpacks.size() || pos < 0 || !index.isValid()) {
return QString("INVALID INDEX %1").arg(pos);
}
IndexedPack pack = modpacks.at(pos);
- if(role == Qt::DisplayRole)
- {
+ if (role == Qt::DisplayRole) {
return pack.name;
- }
- else if (role == Qt::ToolTipRole)
- {
- if(pack.description.length() > 100)
- {
- //some magic to prevent to long tooltips and replace html linebreaks
+ } else if (role == Qt::ToolTipRole) {
+ if (pack.description.length() > 100) {
+ // some magic to prevent to long tooltips and replace html linebreaks
QString edit = pack.description.left(97);
edit = edit.left(edit.lastIndexOf("<br>")).left(edit.lastIndexOf(" ")).append("...");
return edit;
-
}
return pack.description;
- }
- else if(role == Qt::DecorationRole)
- {
- if(m_logoMap.contains(pack.logoName))
- {
+ } else if (role == Qt::DecorationRole) {
+ if (m_logoMap.contains(pack.logoName)) {
return (m_logoMap.value(pack.logoName));
}
QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder");
- ((ListModel *)this)->requestLogo(pack.logoName, pack.logoUrl);
+ ((ListModel*)this)->requestLogo(pack.logoName, pack.logoUrl);
return icon;
- }
- else if(role == Qt::UserRole)
- {
+ } else if (role == Qt::UserRole) {
QVariant v;
v.setValue(pack);
return v;
@@ -76,9 +61,9 @@ void ListModel::logoLoaded(QString logo, QIcon out)
{
m_loadingLogos.removeAll(logo);
m_logoMap.insert(logo, out);
- for(int i = 0; i < modpacks.size(); i++) {
- if(modpacks[i].logoName == logo) {
- emit dataChanged(createIndex(i, 0), createIndex(i, 0), {Qt::DecorationRole});
+ for (int i = 0; i < modpacks.size(); i++) {
+ if (modpacks[i].logoName == logo) {
+ emit dataChanged(createIndex(i, 0), createIndex(i, 0), { Qt::DecorationRole });
}
}
}
@@ -91,8 +76,7 @@ void ListModel::logoFailed(QString logo)
void ListModel::requestLogo(QString logo, QString url)
{
- if(m_loadingLogos.contains(logo) || m_failedLogos.contains(logo))
- {
+ if (m_loadingLogos.contains(logo) || m_failedLogos.contains(logo)) {
return;
}
@@ -101,18 +85,15 @@ void ListModel::requestLogo(QString logo, QString url)
job->addNetAction(Net::Download::makeCached(QUrl(url), entry));
auto fullPath = entry->getFullPath();
- QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath, job]
- {
+ QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath, job] {
job->deleteLater();
emit logoLoaded(logo, QIcon(fullPath));
- if(waitingCallbacks.contains(logo))
- {
+ if (waitingCallbacks.contains(logo)) {
waitingCallbacks.value(logo)(fullPath);
}
});
- QObject::connect(job, &NetJob::failed, this, [this, logo, job]
- {
+ QObject::connect(job, &NetJob::failed, this, [this, logo, job] {
job->deleteLater();
emit logoFailed(logo);
});
@@ -122,19 +103,16 @@ void ListModel::requestLogo(QString logo, QString url)
m_loadingLogos.append(logo);
}
-void ListModel::getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback)
+void ListModel::getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback)
{
- if(m_logoMap.contains(logo))
- {
+ if (m_logoMap.contains(logo)) {
callback(APPLICATION->metacache()->resolveEntry("FlamePacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath());
- }
- else
- {
+ } else {
requestLogo(logo, logoUrl);
}
}
-Qt::ItemFlags ListModel::flags(const QModelIndex &index) const
+Qt::ItemFlags ListModel::flags(const QModelIndex& index) const
{
return QAbstractListModel::flags(index);
}
@@ -148,7 +126,7 @@ void ListModel::fetchMore(const QModelIndex& parent)
{
if (parent.isValid())
return;
- if(nextSearchOffset == 0) {
+ if (nextSearchOffset == 0) {
qWarning() << "fetchMore with 0 offset is wrong...";
return;
}
@@ -157,17 +135,20 @@ void ListModel::fetchMore(const QModelIndex& parent)
void ListModel::performPaginatedSearch()
{
- NetJob *netJob = new NetJob("Flame::Search", APPLICATION->network());
+ NetJob* netJob = new NetJob("Flame::Search", APPLICATION->network());
auto searchUrl = QString(
- "https://addons-ecs.forgesvc.net/api/v2/addon/search?"
- "categoryId=0&"
- "gameId=432&"
- "index=%1&"
- "pageSize=25&"
- "searchFilter=%2&"
- "sectionId=4471&"
- "sort=%3"
- ).arg(nextSearchOffset).arg(currentSearchTerm).arg(currentSort);
+ "https://api.curseforge.com/v1/mods/search?"
+ "gameId=432&"
+ "classId=4471&"
+ "index=%1&"
+ "pageSize=25&"
+ "searchFilter=%2&"
+ "sortField=%3&"
+ "sortOrder=desc")
+ .arg(nextSearchOffset)
+ .arg(currentSearchTerm)
+ .arg(currentSort + 1);
+
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response));
jobPtr = netJob;
jobPtr->start();
@@ -177,17 +158,16 @@ void ListModel::performPaginatedSearch()
void ListModel::searchWithTerm(const QString& term, int sort)
{
- if(currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort) {
+ if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort) {
return;
}
currentSearchTerm = term;
currentSort = sort;
- if(jobPtr) {
+ if (jobPtr) {
jobPtr->abort();
searchState = ResetRequested;
return;
- }
- else {
+ } else {
beginResetModel();
modpacks.clear();
endResetModel();
@@ -203,30 +183,28 @@ void Flame::ListModel::searchRequestFinished()
QJsonParseError parse_error;
QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
- if(parse_error.error != QJsonParseError::NoError) {
- qWarning() << "Error while parsing JSON response from CurseForge at " << parse_error.offset << " reason: " << parse_error.errorString();
+ if (parse_error.error != QJsonParseError::NoError) {
+ qWarning() << "Error while parsing JSON response from CurseForge at " << parse_error.offset
+ << " reason: " << parse_error.errorString();
qWarning() << response;
return;
}
QList<Flame::IndexedPack> newList;
- auto packs = doc.array();
- for(auto packRaw : packs) {
+ auto packs = Json::ensureArray(doc.object(), "data");
+ for (auto packRaw : packs) {
auto packObj = packRaw.toObject();
Flame::IndexedPack pack;
- try
- {
+ try {
Flame::loadIndexedPack(pack, packObj);
newList.append(pack);
- }
- catch(const JSONValidationError &e)
- {
+ } catch (const JSONValidationError& e) {
qWarning() << "Error while loading pack from CurseForge: " << e.cause();
continue;
}
}
- if(packs.size() < 25) {
+ if (packs.size() < 25) {
searchState = Finished;
} else {
nextSearchOffset += 25;
@@ -241,7 +219,7 @@ void Flame::ListModel::searchRequestFailed(QString reason)
{
jobPtr.reset();
- if(searchState == ResetRequested) {
+ if (searchState == ResetRequested) {
beginResetModel();
modpacks.clear();
endResetModel();
@@ -253,5 +231,4 @@ void Flame::ListModel::searchRequestFailed(QString reason)
}
}
-}
-
+} // namespace Flame
diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp
index c90294ce..ec774621 100644
--- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp
+++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp
@@ -39,13 +39,12 @@
#include <QKeyEvent>
#include "Application.h"
+#include "FlameModel.h"
+#include "InstanceImportTask.h"
#include "Json.h"
#include "ui/dialogs/NewInstanceDialog.h"
-#include "InstanceImportTask.h"
-#include "FlameModel.h"
-FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget *parent)
- : QWidget(parent), ui(new Ui::FlamePage), dialog(dialog)
+FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), ui(new Ui::FlamePage), dialog(dialog)
{
ui->setupUi(this);
connect(ui->searchButton, &QPushButton::clicked, this, &FlamePage::triggerSearch);
@@ -112,10 +111,8 @@ void FlamePage::onSelectionChanged(QModelIndex first, QModelIndex second)
{
ui->versionSelectionBox->clear();
- if(!first.isValid())
- {
- if(isOpened)
- {
+ if (!first.isValid()) {
+ if (isOpened) {
dialog->setSuggestedPack();
}
return;
@@ -130,14 +127,14 @@ void FlamePage::onSelectionChanged(QModelIndex first, QModelIndex second)
else
text = "<a href=\"" + current.websiteUrl + "\">" + name + "</a>";
if (!current.authors.empty()) {
- auto authorToStr = [](Flame::ModpackAuthor & author) {
- if(author.url.isEmpty()) {
+ auto authorToStr = [](Flame::ModpackAuthor& author) {
+ if (author.url.isEmpty()) {
return author.name;
}
return QString("<a href=\"%1\">%2</a>").arg(author.url, author.name);
};
QStringList authorStrs;
- for(auto & author: current.authors) {
+ for (auto& author : current.authors) {
authorStrs.push_back(authorToStr(author));
}
text += "<br>" + tr(" by ") + authorStrs.join(", ");
@@ -146,53 +143,46 @@ void FlamePage::onSelectionChanged(QModelIndex first, QModelIndex second)
ui->packDescription->setHtml(text + current.description);
- if (current.versionsLoaded == false)
- {
+ if (current.versionsLoaded == false) {
qDebug() << "Loading flame modpack versions";
auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(current.name), APPLICATION->network());
auto response = new QByteArray();
int addonId = current.addonId;
- netJob->addNetAction(Net::Download::makeByteArray(QString("https://addons-ecs.forgesvc.net/api/v2/addon/%1/files").arg(addonId), response));
+ netJob->addNetAction(Net::Download::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/files").arg(addonId), response));
- QObject::connect(netJob, &NetJob::succeeded, this, [this, response, addonId]
- {
- if(addonId != current.addonId){
- return; //wrong request
+ QObject::connect(netJob, &NetJob::succeeded, this, [this, response, addonId] {
+ if (addonId != current.addonId) {
+ return; // wrong request
}
QJsonParseError parse_error;
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
- if(parse_error.error != QJsonParseError::NoError) {
- qWarning() << "Error while parsing JSON response from CurseForge at " << parse_error.offset << " reason: " << parse_error.errorString();
+ if (parse_error.error != QJsonParseError::NoError) {
+ qWarning() << "Error while parsing JSON response from CurseForge at " << parse_error.offset
+ << " reason: " << parse_error.errorString();
qWarning() << *response;
return;
}
- QJsonArray arr = doc.array();
- try
- {
+ auto arr = Json::ensureArray(doc.object(), "data");
+ try {
Flame::loadIndexedPackVersions(current, arr);
- }
- catch(const JSONValidationError &e)
- {
+ } catch (const JSONValidationError& e) {
qDebug() << *response;
qWarning() << "Error while reading flame modpack version: " << e.cause();
}
- for(auto version : current.versions) {
+ for (auto version : current.versions) {
ui->versionSelectionBox->addItem(version.version, QVariant(version.downloadUrl));
}
suggestCurrent();
});
- QObject::connect(netJob, &NetJob::finished, this, [response, netJob]
- {
+ QObject::connect(netJob, &NetJob::finished, this, [response, netJob] {
netJob->deleteLater();
delete response;
});
netJob->start();
- }
- else
- {
- for(auto version : current.versions) {
+ } else {
+ for (auto version : current.versions) {
ui->versionSelectionBox->addItem(version.version, QVariant(version.downloadUrl));
}
@@ -202,13 +192,11 @@ void FlamePage::onSelectionChanged(QModelIndex first, QModelIndex second)
void FlamePage::suggestCurrent()
{
- if(!isOpened)
- {
+ if (!isOpened) {
return;
}
- if (selectedVersion.isEmpty())
- {
+ if (selectedVersion.isEmpty()) {
dialog->setSuggestedPack();
return;
}
@@ -216,16 +204,13 @@ void FlamePage::suggestCurrent()
dialog->setSuggestedPack(current.name, new InstanceImportTask(selectedVersion));
QString editedLogoName;
editedLogoName = "curseforge_" + current.logoName.section(".", 0, 0);
- listModel->getLogo(current.logoName, current.logoUrl, [this, editedLogoName](QString logo)
- {
- dialog->setSuggestedIconFromFile(logo, editedLogoName);
- });
+ listModel->getLogo(current.logoName, current.logoUrl,
+ [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); });
}
void FlamePage::onVersionSelectionChanged(QString data)
{
- if(data.isNull() || data.isEmpty())
- {
+ if (data.isNull() || data.isEmpty()) {
selectedVersion = "";
return;
}
diff --git a/program_info/App.entitlements b/program_info/App.entitlements
index 1850b990..b46e8ff2 100644
--- a/program_info/App.entitlements
+++ b/program_info/App.entitlements
@@ -2,11 +2,13 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>com.apple.security.cs.disable-library-validation</key>
- <true/>
- <key>com.apple.security.device.audio-input</key>
- <true/>
- <key>com.apple.security.device.camera</key>
- <true/>
+ <key>com.apple.security.cs.disable-library-validation</key>
+ <true/>
+ <key>com.apple.security.cs.allow-dyld-environment-variables</key>
+ <true/>
+ <key>com.apple.security.device.audio-input</key>
+ <true/>
+ <key>com.apple.security.device.camera</key>
+ <true/>
</dict>
</plist>