mirror of
https://github.com/UltimMC/Launcher.git
synced 2025-12-14 04:32:14 +00:00
Compare commits
339 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c11ce8063 | ||
|
|
cff2e4823a | ||
|
|
d0b31da4b5 | ||
|
|
2ad9e6393f | ||
|
|
743af4769e | ||
|
|
6ab6a450f6 | ||
|
|
3ed467e1fa | ||
|
|
44d76f5d82 | ||
|
|
ff715f7785 | ||
|
|
43c777f386 | ||
|
|
a39fb1ef17 | ||
|
|
c75cac684e | ||
|
|
f2026df597 | ||
|
|
416e08f741 | ||
|
|
5bbe1c7132 | ||
|
|
bd1a28d863 | ||
|
|
ffcb5ab1ef | ||
|
|
88f975eff7 | ||
|
|
11c376f6f1 | ||
|
|
757b4e260b | ||
|
|
2a4647125d | ||
|
|
9598f80335 | ||
|
|
34a5e59007 | ||
|
|
1271188019 | ||
|
|
4c6edc9fd4 | ||
|
|
49d3705d16 | ||
|
|
c09dc85090 | ||
|
|
c10a4a54d9 | ||
|
|
1b884d0a9d | ||
|
|
8e9d5f56b5 | ||
|
|
5779ffd664 | ||
|
|
4fc4a17256 | ||
|
|
bb01c91469 | ||
|
|
fb3c9efc8a | ||
|
|
55f9117ce3 | ||
|
|
994c815bb9 | ||
|
|
32f45578fd | ||
|
|
2af03ba0d9 | ||
|
|
aea51a0876 | ||
|
|
75dfbc61fc | ||
|
|
f8650e3965 | ||
|
|
84549ed807 | ||
|
|
d5c79db12c | ||
|
|
f623dc54ef | ||
|
|
dc279fbfdc | ||
|
|
8fa58dc244 | ||
|
|
07bebddac9 | ||
|
|
4f417d527e | ||
|
|
c7c81463fd | ||
|
|
6cfac115b1 | ||
|
|
3507ccaf50 | ||
|
|
28aa8f342e | ||
|
|
4d8f068f9c | ||
|
|
1f9dd45e49 | ||
|
|
f061bf7a27 | ||
|
|
d8ea3501eb | ||
|
|
9df2f1fa5c | ||
|
|
fe540e5dda | ||
|
|
c7398dfdc5 | ||
|
|
0220fe4f9d | ||
|
|
58840ac10c | ||
|
|
3d3725f088 | ||
|
|
47bbc349eb | ||
|
|
c8687a8d05 | ||
|
|
234f57b8e6 | ||
|
|
d4d8cb4891 | ||
|
|
d1ba972c59 | ||
|
|
db877ba121 | ||
|
|
4730f54df7 | ||
|
|
7a71ecd8af | ||
|
|
4e94de413b | ||
|
|
141e0a02a0 | ||
|
|
473971b6e7 | ||
|
|
b47e196b32 | ||
|
|
cd9d37aac4 | ||
|
|
28a39ef7ac | ||
|
|
d313e9ab09 | ||
|
|
382ae78a0b | ||
|
|
aa70ed2244 | ||
|
|
154d19bb74 | ||
|
|
c088d3bef0 | ||
|
|
6775e3e72b | ||
|
|
8b4e22bbb8 | ||
|
|
c7b39fe116 | ||
|
|
865b200571 | ||
|
|
dc84ac3682 | ||
|
|
695bfd5f7c | ||
|
|
5ff2681da6 | ||
|
|
5359f4499a | ||
|
|
04b45f3629 | ||
|
|
9249768db5 | ||
|
|
6f3aa65bd6 | ||
|
|
e508728246 | ||
|
|
360ec557b2 | ||
|
|
7334b8e520 | ||
|
|
791221e923 | ||
|
|
593111b144 | ||
|
|
3b6574181e | ||
|
|
eae544f0eb | ||
|
|
2eb3ec39bf | ||
|
|
a27c341781 | ||
|
|
02f82e9694 | ||
|
|
405833bbbe | ||
|
|
8be865fb2a | ||
|
|
568a79e7b1 | ||
|
|
06c9a64a87 | ||
|
|
ceec70e014 | ||
|
|
ef34cafe17 | ||
|
|
93b247592d | ||
|
|
b8a8b09796 | ||
|
|
a53f8d506e | ||
|
|
f9a17eb9de | ||
|
|
c6c5134398 | ||
|
|
49ff31f131 | ||
|
|
e25e076d2e | ||
|
|
125ddc5f93 | ||
|
|
d03dbea1b7 | ||
|
|
c6427caa9e | ||
|
|
0be0e822e4 | ||
|
|
55e5322fbe | ||
|
|
0886786bb5 | ||
|
|
1151037f96 | ||
|
|
acb3346409 | ||
|
|
85756d0e78 | ||
|
|
5c599d8658 | ||
|
|
4db31aacd6 | ||
|
|
a30a9559c7 | ||
|
|
01f44e0f39 | ||
|
|
bbcd44a657 | ||
|
|
a060d79c12 | ||
|
|
28140b1db6 | ||
|
|
5af1f0cf50 | ||
|
|
7778c84121 | ||
|
|
4ae0d8e0af | ||
|
|
9f14b319df | ||
|
|
a9af17eebb | ||
|
|
d3c2230a24 | ||
|
|
f8bd687994 | ||
|
|
fa8d3c564d | ||
|
|
80d3f734c6 | ||
|
|
9ad9826d08 | ||
|
|
6a09fd2898 | ||
|
|
03a25c9a5d | ||
|
|
83b90d8bfb | ||
|
|
1d5c09051c | ||
|
|
940f160091 | ||
|
|
3d2de6add8 | ||
|
|
b7c4284019 | ||
|
|
2315bf7bc5 | ||
|
|
41bd2a6634 | ||
|
|
5711b1be95 | ||
|
|
90eea4f05c | ||
|
|
cbb1e0ea45 | ||
|
|
ec4805cce8 | ||
|
|
a2ac9c5a3a | ||
|
|
551e101146 | ||
|
|
1dd8978f8c | ||
|
|
24a0635b62 | ||
|
|
2e9284951c | ||
|
|
f9a7c1cf21 | ||
|
|
28eebc09fc | ||
|
|
cc19159f4d | ||
|
|
587fedce84 | ||
|
|
fa42a27525 | ||
|
|
84723add8f | ||
|
|
992ba0c3f8 | ||
|
|
7d1dd2a32f | ||
|
|
add23a9a0b | ||
|
|
d9b2f0ed42 | ||
|
|
9217d9263e | ||
|
|
a3a5afe119 | ||
|
|
7fb6cafe9e | ||
|
|
c1b6f42551 | ||
|
|
3d1426b559 | ||
|
|
095640ed01 | ||
|
|
9e8a74cc89 | ||
|
|
547f6f77d0 | ||
|
|
8f7aec032b | ||
|
|
92560bf0cd | ||
|
|
2dd2b7a291 | ||
|
|
b4122cff89 | ||
|
|
43b9706b5c | ||
|
|
bbdf5c1395 | ||
|
|
382e167d64 | ||
|
|
de2bb0c6f3 | ||
|
|
2083ac8cc1 | ||
|
|
16955c6188 | ||
|
|
b00e63dbe8 | ||
|
|
20cb97a35a | ||
|
|
36efcf8d3c | ||
|
|
a59e83cd12 | ||
|
|
febf3645d0 | ||
|
|
01ca3d6aad | ||
|
|
6deb41e32d | ||
|
|
74f7bd9a1c | ||
|
|
7d8c5ac9b5 | ||
|
|
d172daf3a9 | ||
|
|
56b16320dd | ||
|
|
376467740b | ||
|
|
814d5d3315 | ||
|
|
fd6706391b | ||
|
|
21597da33d | ||
|
|
c0254d9a75 | ||
|
|
151fbde8d0 | ||
|
|
03b13b0b3f | ||
|
|
9b82c87c92 | ||
|
|
75cb329f17 | ||
|
|
bef869ff76 | ||
|
|
0a64579401 | ||
|
|
d71697efb3 | ||
|
|
e5b393318f | ||
|
|
1ed90293ac | ||
|
|
bc05ad30aa | ||
|
|
e178284172 | ||
|
|
c91adfb3d1 | ||
|
|
77d9360d25 | ||
|
|
3403553d44 | ||
|
|
c767707c95 | ||
|
|
66fa241257 | ||
|
|
8a56ab6780 | ||
|
|
71575a5022 | ||
|
|
222c26f9cf | ||
|
|
ce68efa174 | ||
|
|
8bb906bbd7 | ||
|
|
e7f67a73b3 | ||
|
|
3821569363 | ||
|
|
d8d6f5929b | ||
|
|
977cc1cfbb | ||
|
|
4c0dc51110 | ||
|
|
5c43842359 | ||
|
|
aba1f89e2a | ||
|
|
cc6968e9a3 | ||
|
|
d570037331 | ||
|
|
6a8984a21d | ||
|
|
0d4046de39 | ||
|
|
24698fe85f | ||
|
|
40c238442f | ||
|
|
ff06489fed | ||
|
|
08fbfa7434 | ||
|
|
6f75009a80 | ||
|
|
7c51cc475b | ||
|
|
fc911add58 | ||
|
|
6349800f07 | ||
|
|
9b3ae29a36 | ||
|
|
19278c853b | ||
|
|
b3cf19190f | ||
|
|
842328df8e | ||
|
|
f72a38b06c | ||
|
|
d934e64831 | ||
|
|
15775bd30a | ||
|
|
cc499488db | ||
|
|
a218d7b7f6 | ||
|
|
b5d6f50fb1 | ||
|
|
252f375454 | ||
|
|
a75e64dd18 | ||
|
|
18a342ef14 | ||
|
|
8b86306d48 | ||
|
|
dd0752e69f | ||
|
|
d166340097 | ||
|
|
eb5699c835 | ||
|
|
b9fb718822 | ||
|
|
1f498266d8 | ||
|
|
e241c3625c | ||
|
|
421a46e3d3 | ||
|
|
5179aed3a0 | ||
|
|
77de2d1e54 | ||
|
|
e422eff959 | ||
|
|
828254dd11 | ||
|
|
1f3a840f3c | ||
|
|
56d91fda3a | ||
|
|
e8731c5d01 | ||
|
|
30b1f5e5cf | ||
|
|
7f4073840a | ||
|
|
f0d850e1ee | ||
|
|
d6e5c472b5 | ||
|
|
c31dbf13cb | ||
|
|
affb2fdd6c | ||
|
|
c081cd8021 | ||
|
|
1194ec9a8e | ||
|
|
d911c9908c | ||
|
|
702e00e059 | ||
|
|
478815dae6 | ||
|
|
c08bfce5f2 | ||
|
|
9ec6deea84 | ||
|
|
0bccc94471 | ||
|
|
a0a805735b | ||
|
|
171325d427 | ||
|
|
be73eb3322 | ||
|
|
bf7b070508 | ||
|
|
223a7aba7b | ||
|
|
84ae67fff5 | ||
|
|
694067c603 | ||
|
|
6b3d1101cb | ||
|
|
f485885757 | ||
|
|
48d3052ac1 | ||
|
|
e118b1f990 | ||
|
|
55a0d110b6 | ||
|
|
f3900f2966 | ||
|
|
db8b47e7f6 | ||
|
|
439e17b149 | ||
|
|
8c71a5d61f | ||
|
|
6d34411f54 | ||
|
|
68ef451be5 | ||
|
|
e993adaf44 | ||
|
|
ad1f2c530c | ||
|
|
69c3e7111f | ||
|
|
92abe4c603 | ||
|
|
9860d5ee12 | ||
|
|
8a3a0f5a52 | ||
|
|
69a9ca39ad | ||
|
|
825d31bf1a | ||
|
|
2590c6be15 | ||
|
|
4c3bd416c6 | ||
|
|
aade36860c | ||
|
|
3a0cdf2d3d | ||
|
|
d2b2d55aa9 | ||
|
|
eb9661370b | ||
|
|
e1f542b5b0 | ||
|
|
15920aa9d0 | ||
|
|
e17364de6b | ||
|
|
b911a3834c | ||
|
|
94c2c363b2 | ||
|
|
df82d8fadb | ||
|
|
851a77d5bb | ||
|
|
41caf7976d | ||
|
|
fc3c0b0971 | ||
|
|
94cb5c7d77 | ||
|
|
911ac19a56 | ||
|
|
7f2a16917e | ||
|
|
8a8c4193e6 | ||
|
|
927217c7f0 | ||
|
|
e6ca58a89e | ||
|
|
aefa73ad11 | ||
|
|
4f6cd65c13 | ||
|
|
5099964c67 | ||
|
|
9e80ddb040 | ||
|
|
489cb4dbf5 | ||
|
|
e3b9b30302 | ||
|
|
93ae21abfc |
@@ -9,6 +9,7 @@ NamespaceIndentation: None
|
||||
|
||||
BreakBeforeBraces: Allman
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
ColumnLimit: 96
|
||||
MaxEmptyLinesToKeep: 1
|
||||
|
||||
|
||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.pem -crlf
|
||||
14
.travis.yml
14
.travis.yml
@@ -4,26 +4,20 @@ compiler:
|
||||
- clang
|
||||
cache: apt
|
||||
before_install:
|
||||
- sudo apt-add-repository -y ppa:beineri/opt-qt521
|
||||
- sudo apt-add-repository -y ppa:beineri/opt-qt532
|
||||
- sudo apt-add-repository -y ppa:kalakris/cmake
|
||||
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
- sudo apt-get update -qq
|
||||
install:
|
||||
- sudo apt-get install -y -qq cmake qt52base qt52svg qt52tools qt52x11extras
|
||||
- sudo apt-get install -y -qq cmake qt53base qt53svg qt53tools qt53x11extras qt53webkit
|
||||
- sudo apt-get install -y -qq g++-4.8
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
|
||||
before_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -DCMAKE_PREFIX_PATH=/opt/qt52/lib/cmake ..
|
||||
- cmake -DCMAKE_PREFIX_PATH=/opt/qt53/lib/cmake ..
|
||||
script:
|
||||
- make -j4
|
||||
after_script:
|
||||
- make test
|
||||
- make test ARGS="-V"
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
- "irc.esper.net#MultiMC"
|
||||
template:
|
||||
- "%{build_number} (%{branch} - %{commit} : %{author}): %{message} (%{build_url})"
|
||||
email: false
|
||||
|
||||
8
BUILD.md
8
BUILD.md
@@ -2,10 +2,18 @@ Build Instructions
|
||||
==================
|
||||
|
||||
# Contents
|
||||
* [Note](#note)
|
||||
* [Linux](#linux)
|
||||
* [Windows](#windows)
|
||||
* [OS X](#os-x)
|
||||
|
||||
# Note
|
||||
|
||||
MultiMC is a portable application and is not supposed to be installed into any system folders.
|
||||
That would be anything outside your home folder. Before runing `make install`, make sure
|
||||
you set the install path to something you have write access to. Never build this under
|
||||
an administrator/root level account. Don't use `sudo`. It won't work and it's not supposed to work.
|
||||
|
||||
# Linux
|
||||
|
||||
Getting the project to build and run on Linux is easy if you use Ubuntu 13.10 (or 13.04) and Qt's IDE, Qt Creator.
|
||||
|
||||
726
CMakeLists.txt
726
CMakeLists.txt
@@ -10,13 +10,12 @@ if(WIN32)
|
||||
cmake_policy(SET CMP0020 OLD)
|
||||
endif()
|
||||
|
||||
project(MultiMC)
|
||||
project(Megatron)
|
||||
enable_testing()
|
||||
|
||||
######## Set CMake options ########
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(FILES_TO_TRANSLATE )
|
||||
|
||||
######## Set module path ########
|
||||
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
|
||||
@@ -35,25 +34,29 @@ set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/jars)
|
||||
######## Set compiler flags ########
|
||||
include(UseCXX11)
|
||||
include(Coverage)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||
set(CMAKE_CXX_FLAGS " -Wall ${CMAKE_CXX_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror=return-type")
|
||||
|
||||
# cmake code needed for the coverity scan upload
|
||||
include(Coverity)
|
||||
|
||||
################################ 3rd Party Libs ################################
|
||||
|
||||
# Find the required Qt parts
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5Concurrent REQUIRED)
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5Test REQUIRED)
|
||||
find_package(Qt5Concurrent REQUIRED)
|
||||
find_package(Qt5LinguistTools REQUIRED)
|
||||
find_package(Qt5Xml REQUIRED)
|
||||
|
||||
include_directories(
|
||||
${Qt5Core_INCLUDE_DIRS}
|
||||
${Qt5Widgets_INCLUDE_DIRS}
|
||||
${Qt5Concurrent_INCLUDE_DIRS}
|
||||
${Qt5Network_INCLUDE_DIRS}
|
||||
${Qt5Test_INCLUDE_DIRS}
|
||||
${Qt5Network_INCLUDE_DIRS}
|
||||
${Qt5Xml_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# The Qt5 cmake files don't provide its install paths, so ask qmake.
|
||||
@@ -61,156 +64,37 @@ include(QMakeQuery)
|
||||
query_qmake(QT_INSTALL_PLUGINS QT_PLUGINS_DIR)
|
||||
query_qmake(QT_INSTALL_IMPORTS QT_IMPORTS_DIR)
|
||||
query_qmake(QT_INSTALL_LIBS QT_LIBS_DIR)
|
||||
query_qmake(QT_INSTALL_LIBEXECS QT_LIBEXECS_DIR)
|
||||
query_qmake(QT_HOST_DATA QT_DATA_DIR)
|
||||
set(QT_MKSPECS_DIR ${QT_DATA_DIR}/mkspecs)
|
||||
|
||||
|
||||
################################ SET UP BUILD OPTIONS ################################
|
||||
|
||||
######## Check endianness ########
|
||||
include(TestBigEndian)
|
||||
test_big_endian(BIGENDIAN)
|
||||
if(${BIGENDIAN})
|
||||
add_definitions(-DMULTIMC_BIG_ENDIAN)
|
||||
endif(${BIGENDIAN})
|
||||
|
||||
|
||||
######## Set URLs ########
|
||||
|
||||
set(MultiMC_NEWS_RSS_URL "http://multimc.org/rss.xml" CACHE STRING "URL to fetch MultiMC's news RSS feed from.")
|
||||
|
||||
|
||||
######## Set version numbers ########
|
||||
set(MultiMC_VERSION_MAJOR 0)
|
||||
set(MultiMC_VERSION_MINOR 3)
|
||||
set(MultiMC_VERSION_HOTFIX 5)
|
||||
|
||||
# Build number
|
||||
set(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
|
||||
|
||||
# Version type
|
||||
set(MultiMC_VERSION_TYPE "Custom" CACHE STRING "MultiMC's version type. This should be one of 'Custom', 'Release', 'ReleaseCandidate', or 'Development', depending on what type of version this is.")
|
||||
|
||||
# Build platform.
|
||||
set(MultiMC_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used by the notification system and to display in the about dialog.")
|
||||
|
||||
# Version channel
|
||||
set(MultiMC_VERSION_CHANNEL "" CACHE STRING "The current build's channel. Included in the version string.")
|
||||
|
||||
# Channel list URL
|
||||
set(MultiMC_CHANLIST_URL "" CACHE STRING "URL for the channel list.")
|
||||
|
||||
# Updater enabled?
|
||||
set(MultiMC_UPDATER false CACHE BOOL "Whether or not the update system is enabled. If this is enabled, you must also set MultiMC_CHANLIST_URL and MultiMC_VERSION_CHANNEL in order for it to work properly.")
|
||||
|
||||
# Notification URL
|
||||
set(MultiMC_NOTIFICATION_URL "" CACHE STRING "URL for checking for notifications.")
|
||||
|
||||
set(MultiMC_RELEASE_VERSION_NAME "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}")
|
||||
if(MultiMC_VERSION_HOTFIX GREATER 0)
|
||||
set(MultiMC_RELEASE_VERSION_NAME "${MultiMC_RELEASE_VERSION_NAME}.${MultiMC_VERSION_HOTFIX}")
|
||||
endif()
|
||||
|
||||
# Build a version string to display in the configure logs.
|
||||
if(MultiMC_VERSION_TYPE STREQUAL "Custom")
|
||||
message(STATUS "Version Type: Custom")
|
||||
set(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}")
|
||||
elseif(MultiMC_VERSION_TYPE STREQUAL "Release")
|
||||
message(STATUS "Version Type: Stable Release")
|
||||
set(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}")
|
||||
elseif(MultiMC_VERSION_TYPE STREQUAL "ReleaseCandidate")
|
||||
message(STATUS "Version Type: Release Candidate")
|
||||
set(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}-rc${MultiMC_VERSION_BUILD}")
|
||||
elseif(MultiMC_VERSION_TYPE STREQUAL "Development")
|
||||
message(STATUS "Version Type: Development")
|
||||
set(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}-dev${MultiMC_VERSION_BUILD}")
|
||||
else()
|
||||
message(ERROR "Invalid build type.")
|
||||
endif()
|
||||
|
||||
message(STATUS "MultiMC 5 Version: ${MultiMC_VERSION_STRING}")
|
||||
|
||||
# If the update system is enabled, make sure MultiMC_CHANLIST_URL and MultiMC_VERSION_CHANNEL are set.
|
||||
if(MultiMC_UPDATER)
|
||||
if(MultiMC_VERSION_CHANNEL STREQUAL "")
|
||||
message(FATAL_ERROR "Update system is enabled, but MultiMC_VERSION_CHANNEL is not set.\n"
|
||||
"Please ensure the CMake variables MultiMC_VERSION_CHANNEL, MultiMC_CHANLIST_URL, and MultiMC_VERSION_BUILD are set.")
|
||||
endif()
|
||||
if(MultiMC_CHANLIST_URL STREQUAL "")
|
||||
message(FATAL_ERROR "Update system is enabled, but MultiMC_CHANLIST_URL is not set.\n"
|
||||
"Please ensure the CMake variables MultiMC_VERSION_CHANNEL, MultiMC_CHANLIST_URL, and MultiMC_VERSION_BUILD are set.")
|
||||
endif()
|
||||
if(MultiMC_VERSION_BUILD LESS 0)
|
||||
message(FATAL_ERROR "Update system is enabled, but MultiMC_VERSION_BUILD is not set.\n"
|
||||
"Please ensure the CMake variables MultiMC_VERSION_CHANNEL, MultiMC_CHANLIST_URL, and MultiMC_VERSION_BUILD are set.")
|
||||
endif()
|
||||
message(STATUS "Updater is enabled. Channel list URL: ${MultiMC_CHANLIST_URL}")
|
||||
endif()
|
||||
|
||||
#### Updater-related build config options ####
|
||||
option(MultiMC_UPDATER_DRY_RUN "Enable updater dry-run mode -- for updater development." OFF)
|
||||
option(MultiMC_UPDATER_FORCE_LOCAL "Do not download updated updater -- for updater development." OFF)
|
||||
|
||||
if(MultiMC_UPDATER_DRY_RUN)
|
||||
set(MultiMC_UPDATER_DRY_RUN_value "true")
|
||||
else()
|
||||
set(MultiMC_UPDATER_DRY_RUN_value "false")
|
||||
endif()
|
||||
|
||||
if(MultiMC_UPDATER_FORCE_LOCAL)
|
||||
set(MultiMC_UPDATER_FORCE_LOCAL_value "true")
|
||||
else()
|
||||
set(MultiMC_UPDATER_FORCE_LOCAL_value "false")
|
||||
endif()
|
||||
|
||||
#### Custom target to just print the version.
|
||||
add_custom_target(version echo "Version: ${MultiMC_VERSION_STRING}")
|
||||
|
||||
#### Check the current Git commit
|
||||
include(GitFunctions)
|
||||
git_run(COMMAND rev-parse HEAD DEFAULT "Unknown" OUTPUT_VAR MultiMC_GIT_COMMIT)
|
||||
message(STATUS "Git commit: ${MultiMC_GIT_COMMIT}")
|
||||
|
||||
######## Configure header ########
|
||||
configure_file("${PROJECT_SOURCE_DIR}/BuildConfig.cpp.in" "${PROJECT_BINARY_DIR}/BuildConfig.cpp")
|
||||
|
||||
######## Packaging/install paths setup ########
|
||||
|
||||
if(UNIX AND APPLE)
|
||||
set(BINARY_DEST_DIR MultiMC.app/Contents/MacOS)
|
||||
set(PLUGIN_DEST_DIR MultiMC.app/Contents/MacOS)
|
||||
set(QTCONF_DEST_DIR MultiMC.app/Contents/Resources)
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app")
|
||||
|
||||
set(MACOSX_BUNDLE_BUNDLE_NAME "MultiMC")
|
||||
set(MACOSX_BUNDLE_INFO_STRING "MultiMC Minecraft launcher and management utility.")
|
||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.multimc.MultiMC5")
|
||||
set(MACOSX_BUNDLE_BUNDLE_VERSION "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
|
||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
|
||||
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
|
||||
set(MACOSX_BUNDLE_ICON_FILE MultiMC.icns)
|
||||
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2013 MultiMC Contributors")
|
||||
elseif(UNIX)
|
||||
set(BINARY_DEST_DIR bin)
|
||||
set(PLUGIN_DEST_DIR plugins)
|
||||
set(QTCONF_DEST_DIR .)
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC")
|
||||
elseif(WIN32)
|
||||
set(BINARY_DEST_DIR .)
|
||||
set(PLUGIN_DEST_DIR .)
|
||||
set(QTCONF_DEST_DIR .)
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.exe")
|
||||
endif()
|
||||
|
||||
# directories to look for dependencies
|
||||
set(DIRS "${QT_LIBS_DIR}")
|
||||
|
||||
################################ Included Libs ################################
|
||||
|
||||
include(ExternalProject)
|
||||
set_directory_properties(PROPERTIES EP_BASE External)
|
||||
|
||||
# Add quazip
|
||||
add_definitions(-DQUAZIP_STATIC)
|
||||
add_subdirectory(depends/quazip)
|
||||
include_directories(depends/quazip)
|
||||
set(QUAZIP_VERSION "0.7.1")
|
||||
if(NOT EXISTS ${CMAKE_BINARY_DIR}/quazip-${QUAZIP_VERSION}.tar.gz)
|
||||
file(DOWNLOAD http://downloads.sourceforge.net/project/quazip/quazip/${QUAZIP_VERSION}/quazip-${QUAZIP_VERSION}.tar.gz ${CMAKE_BINARY_DIR}/quazip-${QUAZIP_VERSION}.tar.gz)
|
||||
endif()
|
||||
ExternalProject_Add(QuaZIP
|
||||
SOURCE_DIR <BINARY_DIR>/../Source/quazip-${QUAZIP_VERSION}
|
||||
DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E chdir <SOURCE_DIR>/.. ${CMAKE_COMMAND} -E tar xzf ${CMAKE_BINARY_DIR}/quazip-${QUAZIP_VERSION}.tar.gz
|
||||
PATCH_COMMAND patch -p0 -i ${CMAKE_SOURCE_DIR}/quazip.patch
|
||||
CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} -DCMAKE_CXX_FLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG} -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
|
||||
)
|
||||
include_directories("${CMAKE_BINARY_DIR}/External/Install/QuaZIP/include/quazip")
|
||||
if(UNIX)
|
||||
set(QUAZIP_LIBRARIES -L"${CMAKE_BINARY_DIR}/External/Install/QuaZIP/lib" quazip z)
|
||||
else()
|
||||
set(QUAZIP_LIBRARIES -L"${CMAKE_BINARY_DIR}/External/Install/QuaZIP/lib" quazip)
|
||||
endif()
|
||||
|
||||
# Add the markdown parser thing
|
||||
add_subdirectory(depends/hoedown)
|
||||
include_directories(${HOEDOWN_INCLUDE_DIR})
|
||||
|
||||
# Add the java launcher and checker
|
||||
add_subdirectory(depends/launcher)
|
||||
@@ -231,540 +115,22 @@ add_definitions(-DLIBUTIL_STATIC)
|
||||
add_subdirectory(depends/util)
|
||||
include_directories(${LIBUTIL_INCLUDE_DIR})
|
||||
|
||||
# Add the settings library.
|
||||
add_definitions(-DLIBSETTINGS_STATIC)
|
||||
add_subdirectory(depends/settings)
|
||||
include_directories(${LIBSETTINGS_INCLUDE_DIR})
|
||||
# Add the GUI -> Logic connection header
|
||||
add_subdirectory(depends/LogicalGui)
|
||||
include_directories(${LOGICALGUI_INCLUDE_DIR})
|
||||
|
||||
# Add the updater
|
||||
add_subdirectory(mmc_updater)
|
||||
|
||||
################################ FILES ################################
|
||||
|
||||
######## Sources and headers ########
|
||||
SET(MULTIMC_SOURCES
|
||||
# Application base
|
||||
MultiMC.h
|
||||
MultiMC.cpp
|
||||
MMCError.h
|
||||
BuildConfig.h
|
||||
${PROJECT_BINARY_DIR}/BuildConfig.cpp
|
||||
|
||||
# Logging
|
||||
logger/QsDebugOutput.cpp
|
||||
logger/QsDebugOutput.h
|
||||
logger/QsLog.cpp
|
||||
logger/QsLog.h
|
||||
logger/QsLogDest.cpp
|
||||
logger/QsLogDest.h
|
||||
|
||||
# GUI - windows
|
||||
gui/MainWindow.h
|
||||
gui/MainWindow.cpp
|
||||
gui/ConsoleWindow.h
|
||||
gui/ConsoleWindow.cpp
|
||||
|
||||
# GUI - dialogs
|
||||
gui/dialogs/SettingsDialog.h
|
||||
gui/dialogs/SettingsDialog.cpp
|
||||
gui/dialogs/CopyInstanceDialog.h
|
||||
gui/dialogs/CopyInstanceDialog.cpp
|
||||
gui/dialogs/NewInstanceDialog.cpp
|
||||
gui/dialogs/ProgressDialog.h
|
||||
gui/dialogs/ProgressDialog.cpp
|
||||
gui/dialogs/AboutDialog.h
|
||||
gui/dialogs/AboutDialog.cpp
|
||||
gui/dialogs/VersionSelectDialog.h
|
||||
gui/dialogs/VersionSelectDialog.cpp
|
||||
gui/dialogs/LwjglSelectDialog.h
|
||||
gui/dialogs/LwjglSelectDialog.cpp
|
||||
gui/dialogs/InstanceSettings.h
|
||||
gui/dialogs/InstanceSettings.cpp
|
||||
gui/dialogs/IconPickerDialog.h
|
||||
gui/dialogs/IconPickerDialog.cpp
|
||||
gui/dialogs/LegacyModEditDialog.h
|
||||
gui/dialogs/LegacyModEditDialog.cpp
|
||||
gui/dialogs/OneSixModEditDialog.h
|
||||
gui/dialogs/OneSixModEditDialog.cpp
|
||||
gui/dialogs/ModEditDialogCommon.h
|
||||
gui/dialogs/ModEditDialogCommon.cpp
|
||||
gui/dialogs/EditNotesDialog.h
|
||||
gui/dialogs/EditNotesDialog.cpp
|
||||
gui/dialogs/CustomMessageBox.h
|
||||
gui/dialogs/CustomMessageBox.cpp
|
||||
gui/dialogs/EditAccountDialog.h
|
||||
gui/dialogs/EditAccountDialog.cpp
|
||||
gui/dialogs/LoginDialog.h
|
||||
gui/dialogs/LoginDialog.cpp
|
||||
gui/dialogs/AccountListDialog.h
|
||||
gui/dialogs/AccountListDialog.cpp
|
||||
gui/dialogs/AccountSelectDialog.h
|
||||
gui/dialogs/AccountSelectDialog.cpp
|
||||
gui/dialogs/UpdateDialog.h
|
||||
gui/dialogs/UpdateDialog.cpp
|
||||
gui/dialogs/ScreenshotDialog.h
|
||||
gui/dialogs/ScreenshotDialog.cpp
|
||||
gui/dialogs/NotificationDialog.h
|
||||
gui/dialogs/NotificationDialog.cpp
|
||||
|
||||
# GUI - widgets
|
||||
gui/widgets/Common.h
|
||||
gui/widgets/Common.cpp
|
||||
gui/widgets/ModListView.h
|
||||
gui/widgets/ModListView.cpp
|
||||
gui/widgets/VersionListView.h
|
||||
gui/widgets/VersionListView.cpp
|
||||
gui/widgets/LabeledToolButton.h
|
||||
gui/widgets/LabeledToolButton.cpp
|
||||
gui/widgets/MCModInfoFrame.h
|
||||
gui/widgets/MCModInfoFrame.cpp
|
||||
|
||||
# GUI - instance group view
|
||||
gui/groupview/Group.cpp
|
||||
gui/groupview/Group.h
|
||||
gui/groupview/GroupedProxyModel.cpp
|
||||
gui/groupview/GroupedProxyModel.h
|
||||
gui/groupview/GroupView.cpp
|
||||
gui/groupview/GroupView.h
|
||||
gui/groupview/InstanceDelegate.cpp
|
||||
gui/groupview/InstanceDelegate.h
|
||||
|
||||
# Base classes and infrastructure
|
||||
logic/BaseVersion.h
|
||||
logic/MinecraftVersion.h
|
||||
logic/InstanceFactory.h
|
||||
logic/InstanceFactory.cpp
|
||||
logic/BaseInstance.h
|
||||
logic/BaseInstance.cpp
|
||||
logic/BaseInstance_p.h
|
||||
|
||||
logic/MinecraftProcess.h
|
||||
logic/MinecraftProcess.cpp
|
||||
logic/Mod.h
|
||||
logic/Mod.cpp
|
||||
logic/ModList.h
|
||||
logic/ModList.cpp
|
||||
|
||||
# Basic instance launcher for starting from terminal
|
||||
logic/InstanceLauncher.h
|
||||
logic/InstanceLauncher.cpp
|
||||
|
||||
# JSON parsing helpers
|
||||
logic/MMCJson.h
|
||||
logic/MMCJson.cpp
|
||||
|
||||
# network stuffs
|
||||
logic/net/NetAction.h
|
||||
logic/net/MD5EtagDownload.h
|
||||
logic/net/MD5EtagDownload.cpp
|
||||
logic/net/ByteArrayDownload.h
|
||||
logic/net/ByteArrayDownload.cpp
|
||||
logic/net/CacheDownload.h
|
||||
logic/net/CacheDownload.cpp
|
||||
logic/net/ForgeMirrors.h
|
||||
logic/net/ForgeMirrors.cpp
|
||||
logic/net/ForgeXzDownload.h
|
||||
logic/net/ForgeXzDownload.cpp
|
||||
logic/net/NetJob.h
|
||||
logic/net/NetJob.cpp
|
||||
logic/net/HttpMetaCache.h
|
||||
logic/net/HttpMetaCache.cpp
|
||||
logic/net/PasteUpload.h
|
||||
logic/net/PasteUpload.cpp
|
||||
logic/net/URLConstants.h
|
||||
logic/net/URLConstants.cpp
|
||||
|
||||
# Yggdrasil login stuff
|
||||
logic/auth/AuthSession.h
|
||||
logic/auth/AuthSession.cpp
|
||||
logic/auth/MojangAccountList.h
|
||||
logic/auth/MojangAccountList.cpp
|
||||
logic/auth/MojangAccount.h
|
||||
logic/auth/MojangAccount.cpp
|
||||
logic/auth/YggdrasilTask.h
|
||||
logic/auth/YggdrasilTask.cpp
|
||||
logic/auth/flows/AuthenticateTask.h
|
||||
logic/auth/flows/AuthenticateTask.cpp
|
||||
logic/auth/flows/RefreshTask.cpp
|
||||
logic/auth/flows/RefreshTask.cpp
|
||||
logic/auth/flows/ValidateTask.h
|
||||
logic/auth/flows/ValidateTask.cpp
|
||||
|
||||
# Update system
|
||||
logic/updater/UpdateChecker.h
|
||||
logic/updater/UpdateChecker.cpp
|
||||
logic/updater/DownloadUpdateTask.h
|
||||
logic/updater/DownloadUpdateTask.cpp
|
||||
logic/updater/NotificationChecker.h
|
||||
logic/updater/NotificationChecker.cpp
|
||||
|
||||
# News System
|
||||
logic/news/NewsChecker.h
|
||||
logic/news/NewsChecker.cpp
|
||||
logic/news/NewsEntry.h
|
||||
logic/news/NewsEntry.cpp
|
||||
|
||||
# Status system
|
||||
logic/status/StatusChecker.h
|
||||
logic/status/StatusChecker.cpp
|
||||
|
||||
# legacy instances
|
||||
logic/LegacyInstance.h
|
||||
logic/LegacyInstance.cpp
|
||||
logic/LegacyInstance_p.h
|
||||
logic/LegacyUpdate.h
|
||||
logic/LegacyUpdate.cpp
|
||||
|
||||
logic/LegacyForge.h
|
||||
logic/LegacyForge.cpp
|
||||
|
||||
# OneSix instances
|
||||
logic/OneSixUpdate.h
|
||||
logic/OneSixUpdate.cpp
|
||||
logic/OneSixInstance.h
|
||||
logic/OneSixInstance.cpp
|
||||
logic/OneSixInstance_p.h
|
||||
|
||||
# OneSix version json infrastructure
|
||||
logic/OneSixVersionBuilder.h
|
||||
logic/OneSixVersionBuilder.cpp
|
||||
logic/VersionFile.h
|
||||
logic/VersionFile.cpp
|
||||
logic/VersionFinal.h
|
||||
logic/VersionFinal.cpp
|
||||
logic/OneSixLibrary.h
|
||||
logic/OneSixLibrary.cpp
|
||||
logic/OneSixRule.h
|
||||
logic/OneSixRule.cpp
|
||||
logic/OpSys.h
|
||||
logic/OpSys.cpp
|
||||
|
||||
# Mod installers
|
||||
logic/BaseInstaller.h
|
||||
logic/BaseInstaller.cpp
|
||||
logic/ForgeInstaller.h
|
||||
logic/ForgeInstaller.cpp
|
||||
logic/LiteLoaderInstaller.h
|
||||
logic/LiteLoaderInstaller.cpp
|
||||
|
||||
# Nostalgia
|
||||
logic/NostalgiaInstance.h
|
||||
logic/NostalgiaInstance.cpp
|
||||
|
||||
# FTB
|
||||
logic/OneSixFTBInstance.h
|
||||
logic/OneSixFTBInstance.cpp
|
||||
logic/LegacyFTBInstance.h
|
||||
logic/LegacyFTBInstance.cpp
|
||||
|
||||
# Lists
|
||||
logic/lists/InstanceList.h
|
||||
logic/lists/InstanceList.cpp
|
||||
logic/lists/BaseVersionList.h
|
||||
logic/lists/BaseVersionList.cpp
|
||||
logic/lists/MinecraftVersionList.h
|
||||
logic/lists/MinecraftVersionList.cpp
|
||||
logic/lists/LwjglVersionList.h
|
||||
logic/lists/LwjglVersionList.cpp
|
||||
logic/lists/ForgeVersionList.h
|
||||
logic/lists/ForgeVersionList.cpp
|
||||
logic/lists/JavaVersionList.h
|
||||
logic/lists/JavaVersionList.cpp
|
||||
logic/lists/LiteLoaderVersionList.h
|
||||
logic/lists/LiteLoaderVersionList.cpp
|
||||
|
||||
# the screenshots feature
|
||||
logic/screenshots/Screenshot.h
|
||||
logic/screenshots/Screenshot.cpp
|
||||
logic/screenshots/ScreenshotList.h
|
||||
logic/screenshots/ScreenshotList.cpp
|
||||
logic/screenshots/ImgurUpload.h
|
||||
logic/screenshots/ImgurUpload.cpp
|
||||
logic/screenshots/ImgurAlbumCreation.h
|
||||
logic/screenshots/ImgurAlbumCreation.cpp
|
||||
|
||||
# Icons
|
||||
logic/icons/MMCIcon.h
|
||||
logic/icons/MMCIcon.cpp
|
||||
logic/icons/IconList.h
|
||||
logic/icons/IconList.cpp
|
||||
|
||||
|
||||
# misc model/view
|
||||
logic/EnabledItemFilter.h
|
||||
logic/EnabledItemFilter.cpp
|
||||
|
||||
# Tasks
|
||||
logic/tasks/ProgressProvider.h
|
||||
logic/tasks/Task.h
|
||||
logic/tasks/Task.cpp
|
||||
logic/tasks/ThreadTask.h
|
||||
logic/tasks/ThreadTask.cpp
|
||||
logic/tasks/SequentialTask.h
|
||||
logic/tasks/SequentialTask.cpp
|
||||
|
||||
# Utilities
|
||||
logic/JavaChecker.h
|
||||
logic/JavaChecker.cpp
|
||||
logic/JavaUtils.h
|
||||
logic/JavaUtils.cpp
|
||||
logic/NagUtils.h
|
||||
logic/NagUtils.cpp
|
||||
logic/SkinUtils.h
|
||||
logic/SkinUtils.cpp
|
||||
logic/JavaCheckerJob.h
|
||||
logic/JavaCheckerJob.cpp
|
||||
|
||||
# Assets
|
||||
logic/assets/AssetsMigrateTask.h
|
||||
logic/assets/AssetsMigrateTask.cpp
|
||||
logic/assets/AssetsUtils.h
|
||||
logic/assets/AssetsUtils.cpp
|
||||
|
||||
# Tools
|
||||
logic/tools/BaseExternalTool.h
|
||||
logic/tools/BaseExternalTool.cpp
|
||||
logic/tools/MCEditTool.h
|
||||
logic/tools/MCEditTool.cpp
|
||||
logic/tools/BaseProfiler.h
|
||||
logic/tools/BaseProfiler.cpp
|
||||
logic/tools/JProfiler.h
|
||||
logic/tools/JProfiler.cpp
|
||||
logic/tools/JVisualVM.h
|
||||
logic/tools/JVisualVM.cpp
|
||||
)
|
||||
|
||||
|
||||
######## UIs ########
|
||||
SET(MULTIMC_UIS
|
||||
# Windows
|
||||
gui/MainWindow.ui
|
||||
gui/ConsoleWindow.ui
|
||||
|
||||
# Dialogs
|
||||
gui/dialogs/SettingsDialog.ui
|
||||
gui/dialogs/CopyInstanceDialog.ui
|
||||
gui/dialogs/NewInstanceDialog.ui
|
||||
gui/dialogs/AboutDialog.ui
|
||||
gui/dialogs/VersionSelectDialog.ui
|
||||
gui/dialogs/LwjglSelectDialog.ui
|
||||
gui/dialogs/InstanceSettings.ui
|
||||
gui/dialogs/ProgressDialog.ui
|
||||
gui/dialogs/IconPickerDialog.ui
|
||||
gui/dialogs/LegacyModEditDialog.ui
|
||||
gui/dialogs/OneSixModEditDialog.ui
|
||||
gui/dialogs/EditNotesDialog.ui
|
||||
gui/dialogs/AccountListDialog.ui
|
||||
gui/dialogs/AccountSelectDialog.ui
|
||||
gui/dialogs/EditAccountDialog.ui
|
||||
gui/dialogs/LoginDialog.ui
|
||||
gui/dialogs/UpdateDialog.ui
|
||||
gui/dialogs/ScreenshotDialog.ui
|
||||
gui/dialogs/NotificationDialog.ui
|
||||
|
||||
# Widgets/other
|
||||
gui/widgets/MCModInfoFrame.ui
|
||||
)
|
||||
|
||||
set(FILES_TO_TRANSLATE)
|
||||
foreach(file ${MULTIMC_SOURCES})
|
||||
get_filename_component(absfile "${file}" ABSOLUTE)
|
||||
list(APPEND FILES_TO_TRANSLATE "${absfile}")
|
||||
endforeach()
|
||||
|
||||
foreach(file ${MULTIMC_UIS})
|
||||
get_filename_component(absfile "${file}" ABSOLUTE)
|
||||
list(APPEND FILES_TO_TRANSLATE "${absfile}")
|
||||
endforeach()
|
||||
|
||||
set(MULTIMC_QRCS
|
||||
resources/backgrounds/backgrounds.qrc
|
||||
resources/multimc/multimc.qrc
|
||||
resources/instances/instances.qrc
|
||||
)
|
||||
|
||||
|
||||
######## Windows resource files ########
|
||||
if(WIN32)
|
||||
set(MULTIMC_RCS resources/multimc.rc)
|
||||
endif()
|
||||
|
||||
####### X11 Stuff #######
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(MultiMC_QT_ADDITIONAL_MODULES ${MultiMC_QT_ADDITIONAL_MODULES} X11Extras)
|
||||
set(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS} xcb)
|
||||
list(APPEND MULTIMC_SOURCES gui/Platform_X11.cpp)
|
||||
else()
|
||||
list(APPEND MULTIMC_SOURCES gui/Platform_Other.cpp)
|
||||
endif()
|
||||
|
||||
|
||||
################################ COMPILE ################################
|
||||
|
||||
# Link additional libraries
|
||||
if(WIN32)
|
||||
set(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS} Qt5::WinMain)
|
||||
endif(WIN32)
|
||||
|
||||
# Tell CMake that MultiMCLauncher.jar is generated.
|
||||
#SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/depends/launcher/MultiMCLauncher.jar GENERATED)
|
||||
#SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/depends/javacheck/JavaCheck.jar GENERATED)
|
||||
|
||||
# Qt 5 stuff
|
||||
qt5_wrap_ui(MULTIMC_UI ${MULTIMC_UIS})
|
||||
qt5_add_resources(MULTIMC_RESOURCES ${MULTIMC_QRCS})
|
||||
|
||||
# Add common library
|
||||
add_library(MultiMC_common STATIC ${MULTIMC_SOURCES} ${MULTIMC_UI} ${MULTIMC_RESOURCES})
|
||||
|
||||
# Add executable
|
||||
add_executable(MultiMC MACOSX_BUNDLE WIN32 main.cpp ${MULTIMC_RCS})
|
||||
|
||||
# Link
|
||||
target_link_libraries(MultiMC MultiMC_common)
|
||||
target_link_libraries(MultiMC_common xz-embedded unpack200 quazip libUtil libSettings ${MultiMC_LINK_ADDITIONAL_LIBS})
|
||||
qt5_use_modules(MultiMC Core Widgets Network Xml Concurrent ${MultiMC_QT_ADDITIONAL_MODULES})
|
||||
qt5_use_modules(MultiMC_common Core Widgets Network Xml Concurrent ${MultiMC_QT_ADDITIONAL_MODULES})
|
||||
|
||||
################################ INSTALLATION AND PACKAGING ################################
|
||||
|
||||
######## Install ########
|
||||
|
||||
#### Executable ####
|
||||
if(APPLE AND UNIX) ## OSX
|
||||
install(TARGETS MultiMC
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION MultiMC.app/Contents/MacOS COMPONENT Runtime
|
||||
)
|
||||
|
||||
elseif(UNIX) ## LINUX and similar
|
||||
install(TARGETS MultiMC
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION bin COMPONENT Runtime
|
||||
)
|
||||
install(PROGRAMS package/linux/MultiMC DESTINATION .)
|
||||
|
||||
elseif(WIN32) ## WINDOWS
|
||||
install(TARGETS MultiMC
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
LIBRARY DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION . COMPONENT Runtime
|
||||
)
|
||||
endif()
|
||||
|
||||
#### Dist package logic ####
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
# Image formats
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "tga|svg|tiff|mng" EXCLUDE
|
||||
)
|
||||
|
||||
# Platform plugins
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "minimal|linuxfb|offscreen" EXCLUDE
|
||||
)
|
||||
else()
|
||||
# Image formats
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "tga|svg|tiff|mng" EXCLUDE
|
||||
REGEX "d\\." EXCLUDE
|
||||
REGEX "_debug\\." EXCLUDE
|
||||
)
|
||||
|
||||
# Platform plugins
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "minimal|linuxfb|offscreen" EXCLUDE
|
||||
REGEX "d\\." EXCLUDE
|
||||
REGEX "_debug\\." EXCLUDE
|
||||
)
|
||||
if(APPLE)
|
||||
# Accessible plugin to make buttons look decent on osx
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/accessible"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "quick" EXCLUDE
|
||||
REGEX "d\\." EXCLUDE
|
||||
REGEX "_debug\\." EXCLUDE
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# qtconf
|
||||
install(
|
||||
CODE "
|
||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${QTCONF_DEST_DIR}/qt.conf\" \"\")
|
||||
"
|
||||
COMPONENT Runtime
|
||||
)
|
||||
|
||||
# ICNS file for OS X
|
||||
if(APPLE)
|
||||
install(FILES resources/MultiMC.icns DESTINATION MultiMC.app/Contents/Resources)
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/install_prereqs.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/install_prereqs.cmake"
|
||||
@ONLY
|
||||
)
|
||||
install(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/install_prereqs.cmake" COMPONENT Runtime)
|
||||
|
||||
|
||||
|
||||
######## Package ########
|
||||
|
||||
# Package with CPack
|
||||
if(UNIX)
|
||||
if(APPLE)
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
else()
|
||||
set(CPACK_GENERATOR "TGZ")
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
endif()
|
||||
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0)
|
||||
|
||||
set(CPACK_PACKAGE_NAME "MultiMC 5")
|
||||
set(CPACK_PACKAGE_VENDOR "")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MultiMC - Minecraft launcher and management tool.")
|
||||
set(CPACK_PACKAGE_VERSION "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${MultiMC_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${MultiMC_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${MultiMC_VERSION_REV})
|
||||
|
||||
if(CPACK_GENERATOR STREQUAL "NSIS")
|
||||
set(CPACK_PACKAGE_FILE_NAME "Setup-MultiMC")
|
||||
else()
|
||||
set(CPACK_PACKAGE_FILE_NAME "MultiMC")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "MultiMC 5")
|
||||
endif()
|
||||
|
||||
include(CPack)
|
||||
# Add the GUI -> Logic connection header
|
||||
add_subdirectory(depends/iconfix)
|
||||
include_directories(${ICONFIX_INCLUDE_DIR})
|
||||
|
||||
include(Coverity)
|
||||
|
||||
include_directories(${PROJECT_BINARY_DIR}/include)
|
||||
############################### Built Artifacts ###############################
|
||||
|
||||
# Translations
|
||||
add_subdirectory(translations)
|
||||
|
||||
# Tests
|
||||
add_subdirectory(tests)
|
||||
|
||||
add_subdirectory(logic)
|
||||
|
||||
add_subdirectory(application)
|
||||
|
||||
add_subdirectory(mmc_updater)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||

|
||||
|
||||
MultiMC 5 [](https://travis-ci.org/MultiMC/MultiMC5)
|
||||
MultiMC 5 [](https://travis-ci.org/MultiMC/MultiMC5) [](http://weblate.robotbrain.info/engage/multimc/?utm_source=widget) [](http://waffle.io/MultiMC/MultiMC5)
|
||||
=========
|
||||
|
||||
MultiMC is a custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once. It also allows you to easily install and remove mods by simply dragging and dropping.
|
||||
@@ -9,7 +9,7 @@ MultiMC is a custom launcher for Minecraft that allows you to easily manage mult
|
||||
Check [BUILD.md](BUILD.md) for build instructions.
|
||||
|
||||
## Contributing
|
||||
The repository is currently managed by @peterix and @drayshak - we're the ones likely to review pull requests. If you'd like to contribute to the project please talk to us on IRC (Esper/#MultiMC) first! This helps us organise ideas and keep in contact with you, and we're unlikely to accept anything blindly.
|
||||
The repository is currently managed by @peterix. If you'd like to contribute to the project please talk to us on IRC (Esper/#MultiMC) first! This helps us organise ideas and keep in contact with you, and we're unlikely to accept anything blindly.
|
||||
|
||||
We use [Clang Format](http://clang.llvm.org/docs/ClangFormat.html) to format the project. We highly recommend setting it up so the project stays well formatted, but there are issues with it on Windows. If you have trouble setting it up, check [.clang-format](.clang-format) manually. We don't accept pull requests with poor formatting. If you have questions, talk to us on IRC (Esper/#MultiMC) _before_ submitting a pull request.
|
||||
|
||||
@@ -22,7 +22,7 @@ Apache covers reasonable use for the name - a mention of the project's origins i
|
||||
|
||||
|
||||
## License
|
||||
Copyright © 2013 MultiMC Contributors
|
||||
Copyright © 2013-2015 MultiMC Contributors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this program except in compliance with the License. You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "BuildConfig.h"
|
||||
#include <QObject>
|
||||
|
||||
Config BuildConfig;
|
||||
|
||||
@@ -9,16 +10,7 @@ Config::Config()
|
||||
VERSION_MINOR = @MultiMC_VERSION_MINOR@;
|
||||
VERSION_HOTFIX = @MultiMC_VERSION_HOTFIX@;
|
||||
VERSION_BUILD = @MultiMC_VERSION_BUILD@;
|
||||
VERSION_TYPE = "@MultiMC_VERSION_TYPE@";
|
||||
|
||||
if(VERSION_TYPE == "Release")
|
||||
versionTypeEnum = Release;
|
||||
else if(VERSION_TYPE == "ReleaseCandidate")
|
||||
versionTypeEnum = ReleaseCandidate;
|
||||
else if(VERSION_TYPE == "Development")
|
||||
versionTypeEnum = Development;
|
||||
else
|
||||
versionTypeEnum = Custom;
|
||||
VERSION_CHANNEL = "@MultiMC_VERSION_CHANNEL@";
|
||||
BUILD_PLATFORM = "@MultiMC_BUILD_PLATFORM@";
|
||||
CHANLIST_URL = "@MultiMC_CHANLIST_URL@";
|
||||
@@ -33,22 +25,6 @@ Config::Config()
|
||||
NEWS_RSS_URL = "@MultiMC_NEWS_RSS_URL@";
|
||||
}
|
||||
|
||||
QString Config::versionTypeName() const
|
||||
{
|
||||
switch (versionTypeEnum)
|
||||
{
|
||||
case Release:
|
||||
return "Stable Release";
|
||||
case ReleaseCandidate:
|
||||
return "Release Candidate";
|
||||
case Development:
|
||||
return "Development";
|
||||
case Custom:
|
||||
default:
|
||||
return "Custom";
|
||||
}
|
||||
}
|
||||
|
||||
QString Config::printableVersionString() const
|
||||
{
|
||||
QString vstr = QString("%1.%2").arg(QString::number(VERSION_MAJOR), QString::number(VERSION_MINOR));
|
||||
@@ -56,8 +32,25 @@ QString Config::printableVersionString() const
|
||||
if (VERSION_HOTFIX > 0) vstr += "." + QString::number(VERSION_HOTFIX);
|
||||
|
||||
// If the build is a development build or release candidate, add that info to the end.
|
||||
if (versionTypeEnum == Development) vstr += "-dev" + QString::number(VERSION_BUILD);
|
||||
else if (versionTypeEnum == ReleaseCandidate) vstr += "-rc" + QString::number(VERSION_BUILD);
|
||||
|
||||
if(VERSION_CHANNEL == "stable")
|
||||
{
|
||||
return vstr;
|
||||
}
|
||||
else if(VERSION_CHANNEL == "develop")
|
||||
{
|
||||
vstr += "-dev-" + QString::number(VERSION_BUILD);
|
||||
}
|
||||
else if(VERSION_CHANNEL == "unstable")
|
||||
{
|
||||
vstr += "-nuke-" + QString::number(VERSION_BUILD);
|
||||
}
|
||||
else if(VERSION_CHANNEL == "custom")
|
||||
{
|
||||
vstr += "-local";
|
||||
}
|
||||
else
|
||||
{
|
||||
vstr += "-" + VERSION_CHANNEL + "-" + QString::number(VERSION_BUILD);
|
||||
}
|
||||
return vstr;
|
||||
}
|
||||
@@ -16,24 +16,6 @@ public:
|
||||
int VERSION_HOTFIX;
|
||||
/// The build number.
|
||||
int VERSION_BUILD;
|
||||
/// The build type, as specified at build time.
|
||||
QString VERSION_TYPE;
|
||||
|
||||
/// The build type, transformed.
|
||||
enum Type
|
||||
{
|
||||
/// Version type for stable release builds.
|
||||
Release,
|
||||
|
||||
/// Version type for release candidates.
|
||||
ReleaseCandidate,
|
||||
|
||||
/// Version type for development builds.
|
||||
Development,
|
||||
|
||||
/// Version type for custom builds. This is the default when no version type is specified.
|
||||
Custom
|
||||
} versionTypeEnum;
|
||||
|
||||
/**
|
||||
* The version channel
|
||||
@@ -76,11 +58,6 @@ public:
|
||||
* \return The version number in string format (major.minor.revision.build).
|
||||
*/
|
||||
QString printableVersionString() const;
|
||||
|
||||
/**
|
||||
* returns a string representation of the version channel type, suitable for printing.
|
||||
*/
|
||||
QString versionTypeName() const;
|
||||
};
|
||||
|
||||
extern Config BuildConfig;
|
||||
493
application/CMakeLists.txt
Normal file
493
application/CMakeLists.txt
Normal file
@@ -0,0 +1,493 @@
|
||||
project(MultiMC-Application)
|
||||
|
||||
######## Set URLs ########
|
||||
set(MultiMC_NEWS_RSS_URL "http://multimc.org/rss.xml" CACHE STRING "URL to fetch MultiMC's news RSS feed from.")
|
||||
|
||||
######## Set version numbers ########
|
||||
set(MultiMC_VERSION_MAJOR 0)
|
||||
set(MultiMC_VERSION_MINOR 4)
|
||||
set(MultiMC_VERSION_HOTFIX 6)
|
||||
|
||||
# Build number
|
||||
set(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
|
||||
|
||||
# Version type
|
||||
set(MultiMC_VERSION_TYPE "Custom" CACHE STRING "MultiMC's version type. This should be one of 'Custom', 'Release', 'ReleaseCandidate', or 'Development', depending on what type of version this is.")
|
||||
|
||||
# Build platform.
|
||||
set(MultiMC_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used by the notification system and to display in the about dialog.")
|
||||
|
||||
# Version channel
|
||||
set(MultiMC_VERSION_CHANNEL "" CACHE STRING "The current build's channel. Included in the version string.")
|
||||
|
||||
# Channel list URL
|
||||
set(MultiMC_CHANLIST_URL "" CACHE STRING "URL for the channel list.")
|
||||
|
||||
# Updater enabled?
|
||||
set(MultiMC_UPDATER false CACHE BOOL "Whether or not the update system is enabled. If this is enabled, you must also set MultiMC_CHANLIST_URL and MultiMC_VERSION_CHANNEL in order for it to work properly.")
|
||||
|
||||
# Notification URL
|
||||
set(MultiMC_NOTIFICATION_URL "" CACHE STRING "URL for checking for notifications.")
|
||||
|
||||
#### Check the current Git commit
|
||||
include(GitFunctions)
|
||||
git_run(COMMAND rev-parse HEAD DEFAULT "Unknown" OUTPUT_VAR MultiMC_GIT_COMMIT)
|
||||
message(STATUS "Git commit: ${MultiMC_GIT_COMMIT}")
|
||||
|
||||
set(MultiMC_RELEASE_VERSION_NAME "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}")
|
||||
if(MultiMC_VERSION_HOTFIX GREATER 0)
|
||||
set(MultiMC_RELEASE_VERSION_NAME "${MultiMC_RELEASE_VERSION_NAME}.${MultiMC_VERSION_HOTFIX}")
|
||||
endif()
|
||||
|
||||
# Build a version string to display in the configure logs.
|
||||
if(MultiMC_VERSION_TYPE STREQUAL "Custom")
|
||||
message(STATUS "Version Type: Custom")
|
||||
set(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}")
|
||||
elseif(MultiMC_VERSION_TYPE STREQUAL "Release")
|
||||
message(STATUS "Version Type: Stable Release")
|
||||
set(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}")
|
||||
elseif(MultiMC_VERSION_TYPE STREQUAL "Development")
|
||||
message(STATUS "Version Type: Development")
|
||||
set(MultiMC_VERSION_STRING "${MultiMC_RELEASE_VERSION_NAME}-dev${MultiMC_VERSION_BUILD}")
|
||||
else()
|
||||
message(ERROR "Invalid build type.")
|
||||
endif()
|
||||
|
||||
message(STATUS "MultiMC 5 Version: ${MultiMC_VERSION_STRING}")
|
||||
|
||||
#### Custom target to just print the version.
|
||||
add_custom_target(version echo "Version: ${MultiMC_VERSION_STRING}")
|
||||
|
||||
# If the update system is enabled, make sure MultiMC_CHANLIST_URL and MultiMC_VERSION_CHANNEL are set.
|
||||
if(MultiMC_UPDATER)
|
||||
if(MultiMC_VERSION_CHANNEL STREQUAL "")
|
||||
message(FATAL_ERROR "Update system is enabled, but MultiMC_VERSION_CHANNEL is not set.\n"
|
||||
"Please ensure the CMake variables MultiMC_VERSION_CHANNEL, MultiMC_CHANLIST_URL, and MultiMC_VERSION_BUILD are set.")
|
||||
endif()
|
||||
if(MultiMC_CHANLIST_URL STREQUAL "")
|
||||
message(FATAL_ERROR "Update system is enabled, but MultiMC_CHANLIST_URL is not set.\n"
|
||||
"Please ensure the CMake variables MultiMC_VERSION_CHANNEL, MultiMC_CHANLIST_URL, and MultiMC_VERSION_BUILD are set.")
|
||||
endif()
|
||||
if(MultiMC_VERSION_BUILD LESS 0)
|
||||
message(FATAL_ERROR "Update system is enabled, but MultiMC_VERSION_BUILD is not set.\n"
|
||||
"Please ensure the CMake variables MultiMC_VERSION_CHANNEL, MultiMC_CHANLIST_URL, and MultiMC_VERSION_BUILD are set.")
|
||||
endif()
|
||||
message(STATUS "Updater is enabled. Channel list URL: ${MultiMC_CHANLIST_URL}")
|
||||
endif()
|
||||
|
||||
#### Updater-related build config options ####
|
||||
option(MultiMC_UPDATER_DRY_RUN "Enable updater dry-run mode -- for updater development." OFF)
|
||||
option(MultiMC_UPDATER_FORCE_LOCAL "Do not download updated updater -- for updater development." OFF)
|
||||
|
||||
if(MultiMC_UPDATER_DRY_RUN)
|
||||
set(MultiMC_UPDATER_DRY_RUN_value "true")
|
||||
else()
|
||||
set(MultiMC_UPDATER_DRY_RUN_value "false")
|
||||
endif()
|
||||
|
||||
if(MultiMC_UPDATER_FORCE_LOCAL)
|
||||
set(MultiMC_UPDATER_FORCE_LOCAL_value "true")
|
||||
else()
|
||||
set(MultiMC_UPDATER_FORCE_LOCAL_value "false")
|
||||
endif()
|
||||
|
||||
######## Configure header ########
|
||||
configure_file("${PROJECT_SOURCE_DIR}/BuildConfig.cpp.in" "${PROJECT_BINARY_DIR}/BuildConfig.cpp")
|
||||
|
||||
######## Packaging/install paths setup ########
|
||||
|
||||
if(UNIX AND APPLE)
|
||||
set(BINARY_DEST_DIR MultiMC.app/Contents/MacOS)
|
||||
set(PLUGIN_DEST_DIR MultiMC.app/Contents/MacOS)
|
||||
set(QTCONF_DEST_DIR MultiMC.app/Contents/Resources)
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app")
|
||||
|
||||
set(MACOSX_BUNDLE_BUNDLE_NAME "MultiMC")
|
||||
set(MACOSX_BUNDLE_INFO_STRING "MultiMC Minecraft launcher and management utility.")
|
||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.multimc.MultiMC5")
|
||||
set(MACOSX_BUNDLE_BUNDLE_VERSION "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_HOTFIX}.${MultiMC_VERSION_BUILD}")
|
||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_HOTFIX}.${MultiMC_VERSION_BUILD}")
|
||||
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_HOTFIX}.${MultiMC_VERSION_BUILD}")
|
||||
set(MACOSX_BUNDLE_ICON_FILE MultiMC.icns)
|
||||
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2015 MultiMC Contributors")
|
||||
elseif(UNIX)
|
||||
set(BINARY_DEST_DIR bin)
|
||||
set(PLUGIN_DEST_DIR plugins)
|
||||
set(QTCONF_DEST_DIR .)
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC")
|
||||
elseif(WIN32)
|
||||
set(BINARY_DEST_DIR .)
|
||||
set(PLUGIN_DEST_DIR .)
|
||||
set(QTCONF_DEST_DIR .)
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.exe")
|
||||
endif()
|
||||
|
||||
# directories to look for dependencies
|
||||
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR})
|
||||
|
||||
################################ FILES ################################
|
||||
|
||||
######## Sources and headers ########
|
||||
SET(MULTIMC_SOURCES
|
||||
# Application base
|
||||
main.cpp
|
||||
MultiMC.h
|
||||
MultiMC.cpp
|
||||
BuildConfig.h
|
||||
${PROJECT_BINARY_DIR}/BuildConfig.cpp
|
||||
|
||||
# GUI - general utilities
|
||||
GuiUtil.h
|
||||
GuiUtil.cpp
|
||||
ColumnResizer.h
|
||||
ColumnResizer.cpp
|
||||
InstanceProxyModel.h
|
||||
InstanceProxyModel.cpp
|
||||
VersionProxyModel.h
|
||||
VersionProxyModel.cpp
|
||||
|
||||
# GUI - windows
|
||||
MainWindow.h
|
||||
MainWindow.cpp
|
||||
ConsoleWindow.h
|
||||
ConsoleWindow.cpp
|
||||
|
||||
# page provider for instances
|
||||
InstancePageProvider.h
|
||||
InstancePageProvider.cpp
|
||||
|
||||
# Common java checking UI
|
||||
JavaCommon.h
|
||||
JavaCommon.cpp
|
||||
|
||||
# GUI - page dialog pages
|
||||
pages/BasePage.h
|
||||
pages/VersionPage.cpp
|
||||
pages/VersionPage.h
|
||||
pages/TexturePackPage.h
|
||||
pages/ResourcePackPage.h
|
||||
pages/ModFolderPage.cpp
|
||||
pages/ModFolderPage.h
|
||||
pages/NotesPage.cpp
|
||||
pages/NotesPage.h
|
||||
pages/LogPage.cpp
|
||||
pages/LogPage.h
|
||||
pages/InstanceSettingsPage.cpp
|
||||
pages/InstanceSettingsPage.h
|
||||
pages/ScreenshotsPage.cpp
|
||||
pages/ScreenshotsPage.h
|
||||
pages/OtherLogsPage.cpp
|
||||
pages/OtherLogsPage.h
|
||||
pages/LegacyJarModPage.cpp
|
||||
pages/LegacyJarModPage.h
|
||||
pages/LegacyUpgradePage.cpp
|
||||
pages/LegacyUpgradePage.h
|
||||
|
||||
# GUI - global settings pages
|
||||
pages/global/AccountListPage.cpp
|
||||
pages/global/AccountListPage.h
|
||||
pages/global/ExternalToolsPage.cpp
|
||||
pages/global/ExternalToolsPage.h
|
||||
pages/global/JavaPage.cpp
|
||||
pages/global/JavaPage.h
|
||||
pages/global/MinecraftPage.cpp
|
||||
pages/global/MinecraftPage.h
|
||||
pages/global/MultiMCPage.cpp
|
||||
pages/global/MultiMCPage.h
|
||||
pages/global/ProxyPage.cpp
|
||||
pages/global/ProxyPage.h
|
||||
|
||||
# GUI - dialogs
|
||||
dialogs/AboutDialog.cpp
|
||||
dialogs/AboutDialog.h
|
||||
dialogs/AccountSelectDialog.cpp
|
||||
dialogs/AccountSelectDialog.h
|
||||
dialogs/CopyInstanceDialog.cpp
|
||||
dialogs/CopyInstanceDialog.h
|
||||
dialogs/CustomMessageBox.cpp
|
||||
dialogs/CustomMessageBox.h
|
||||
dialogs/EditAccountDialog.cpp
|
||||
dialogs/EditAccountDialog.h
|
||||
dialogs/ExportInstanceDialog.cpp
|
||||
dialogs/ExportInstanceDialog.h
|
||||
dialogs/IconPickerDialog.cpp
|
||||
dialogs/IconPickerDialog.h
|
||||
dialogs/LoginDialog.cpp
|
||||
dialogs/LoginDialog.h
|
||||
dialogs/ModEditDialogCommon.cpp
|
||||
dialogs/ModEditDialogCommon.h
|
||||
dialogs/NewInstanceDialog.cpp
|
||||
dialogs/NewInstanceDialog.h
|
||||
dialogs/NotificationDialog.cpp
|
||||
dialogs/NotificationDialog.h
|
||||
pagedialog/PageDialog.cpp
|
||||
pagedialog/PageDialog.h
|
||||
dialogs/ProgressDialog.cpp
|
||||
dialogs/ProgressDialog.h
|
||||
dialogs/UpdateDialog.cpp
|
||||
dialogs/UpdateDialog.h
|
||||
dialogs/VersionSelectDialog.cpp
|
||||
dialogs/VersionSelectDialog.h
|
||||
|
||||
|
||||
# GUI - widgets
|
||||
widgets/Common.cpp
|
||||
widgets/Common.h
|
||||
widgets/IconLabel.cpp
|
||||
widgets/IconLabel.h
|
||||
widgets/LabeledToolButton.cpp
|
||||
widgets/LabeledToolButton.h
|
||||
widgets/LineSeparator.cpp
|
||||
widgets/LineSeparator.h
|
||||
widgets/MCModInfoFrame.cpp
|
||||
widgets/MCModInfoFrame.h
|
||||
widgets/ModListView.cpp
|
||||
widgets/ModListView.h
|
||||
widgets/PageContainer.cpp
|
||||
widgets/PageContainer.h
|
||||
widgets/PageContainer_p.h
|
||||
widgets/ServerStatus.cpp
|
||||
widgets/ServerStatus.h
|
||||
widgets/VersionListView.cpp
|
||||
widgets/VersionListView.h
|
||||
|
||||
|
||||
# GUI - instance group view
|
||||
groupview/GroupedProxyModel.cpp
|
||||
groupview/GroupedProxyModel.h
|
||||
groupview/GroupView.cpp
|
||||
groupview/GroupView.h
|
||||
groupview/InstanceDelegate.cpp
|
||||
groupview/InstanceDelegate.h
|
||||
groupview/VisualGroup.cpp
|
||||
groupview/VisualGroup.h
|
||||
)
|
||||
|
||||
######## UIs ########
|
||||
SET(MULTIMC_UIS
|
||||
# Option pages
|
||||
pages/VersionPage.ui
|
||||
pages/ModFolderPage.ui
|
||||
pages/LogPage.ui
|
||||
pages/InstanceSettingsPage.ui
|
||||
pages/NotesPage.ui
|
||||
pages/ScreenshotsPage.ui
|
||||
pages/OtherLogsPage.ui
|
||||
pages/LegacyJarModPage.ui
|
||||
pages/LegacyUpgradePage.ui
|
||||
|
||||
# Global settings pages
|
||||
pages/global/AccountListPage.ui
|
||||
pages/global/ExternalToolsPage.ui
|
||||
pages/global/JavaPage.ui
|
||||
pages/global/MinecraftPage.ui
|
||||
pages/global/MultiMCPage.ui
|
||||
pages/global/ProxyPage.ui
|
||||
|
||||
# Dialogs
|
||||
dialogs/CopyInstanceDialog.ui
|
||||
dialogs/NewInstanceDialog.ui
|
||||
dialogs/AboutDialog.ui
|
||||
dialogs/VersionSelectDialog.ui
|
||||
dialogs/ProgressDialog.ui
|
||||
dialogs/IconPickerDialog.ui
|
||||
dialogs/AccountSelectDialog.ui
|
||||
dialogs/EditAccountDialog.ui
|
||||
dialogs/ExportInstanceDialog.ui
|
||||
dialogs/LoginDialog.ui
|
||||
dialogs/UpdateDialog.ui
|
||||
dialogs/NotificationDialog.ui
|
||||
|
||||
# Widgets/other
|
||||
widgets/MCModInfoFrame.ui
|
||||
)
|
||||
|
||||
set(MULTIMC_QRCS
|
||||
resources/backgrounds/backgrounds.qrc
|
||||
resources/multimc/multimc.qrc
|
||||
resources/pe_dark/pe_dark.qrc
|
||||
resources/pe_light/pe_light.qrc
|
||||
resources/pe_colored/pe_colored.qrc
|
||||
resources/pe_blue/pe_blue.qrc
|
||||
resources/OSX/OSX.qrc
|
||||
resources/iOS/iOS.qrc
|
||||
resources/instances/instances.qrc
|
||||
resources/versions/versions.qrc
|
||||
resources/certs/certs.qrc
|
||||
)
|
||||
|
||||
######## Windows resource files ########
|
||||
if(WIN32)
|
||||
set(MULTIMC_RCS resources/multimc.rc)
|
||||
endif()
|
||||
|
||||
####### X11 Stuff #######
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(Qt5X11Extras REQUIRED)
|
||||
set(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS} xcb Qt5::X11Extras)
|
||||
list(APPEND MULTIMC_SOURCES Platform_X11.cpp)
|
||||
else()
|
||||
list(APPEND MULTIMC_SOURCES Platform_Other.cpp)
|
||||
endif()
|
||||
|
||||
|
||||
# Link additional libraries
|
||||
if(WIN32)
|
||||
set(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS} Qt5::WinMain)
|
||||
endif(WIN32)
|
||||
|
||||
include_directories(../logic)
|
||||
|
||||
# Qt 5 stuff
|
||||
qt5_wrap_ui(MULTIMC_UI ${MULTIMC_UIS})
|
||||
qt5_add_resources(MULTIMC_RESOURCES ${MULTIMC_QRCS})
|
||||
|
||||
# Add executable
|
||||
add_executable(MultiMC MACOSX_BUNDLE WIN32 ${MULTIMC_SOURCES} ${MULTIMC_UI} ${MULTIMC_RESOURCES} ${MULTIMC_RCS})
|
||||
target_link_libraries(MultiMC MultiMC_logic xz-embedded unpack200 iconfix libUtil LogicalGui
|
||||
${QUAZIP_LIBRARIES} Qt5::Core Qt5::Xml Qt5::Widgets Qt5::Network Qt5::Concurrent
|
||||
hoedown
|
||||
${MultiMC_LINK_ADDITIONAL_LIBS})
|
||||
|
||||
################################ INSTALLATION AND PACKAGING ################################
|
||||
|
||||
######## Install ########
|
||||
|
||||
#### Executable ####
|
||||
if(APPLE AND UNIX) ## OSX
|
||||
install(TARGETS MultiMC
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION MultiMC.app/Contents/MacOS COMPONENT Runtime
|
||||
)
|
||||
|
||||
elseif(UNIX) ## LINUX and similar
|
||||
install(TARGETS MultiMC
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION bin COMPONENT Runtime
|
||||
)
|
||||
install(PROGRAMS package/linux/MultiMC DESTINATION .)
|
||||
|
||||
elseif(WIN32) ## WINDOWS
|
||||
install(TARGETS MultiMC
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
LIBRARY DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION . COMPONENT Runtime
|
||||
)
|
||||
endif()
|
||||
|
||||
#### Java bits ####
|
||||
install_jar(JavaCheck "${BINARY_DEST_DIR}/jars")
|
||||
install_jar(NewLaunch "${BINARY_DEST_DIR}/jars")
|
||||
|
||||
#### Dist package logic ####
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
# Image formats
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "tga|tiff|mng" EXCLUDE
|
||||
)
|
||||
# Icon engines
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "fontawesome" EXCLUDE
|
||||
)
|
||||
# Platform plugins
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "minimal|linuxfb|offscreen" EXCLUDE
|
||||
)
|
||||
else()
|
||||
# Image formats
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "tga|tiff|mng" EXCLUDE
|
||||
REGEX "d\\." EXCLUDE
|
||||
REGEX "_debug\\." EXCLUDE
|
||||
)
|
||||
# Icon engines
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "fontawesome" EXCLUDE
|
||||
REGEX "d\\." EXCLUDE
|
||||
REGEX "_debug\\." EXCLUDE
|
||||
)
|
||||
# Platform plugins
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "minimal|linuxfb|offscreen" EXCLUDE
|
||||
REGEX "d\\." EXCLUDE
|
||||
REGEX "_debug\\." EXCLUDE
|
||||
)
|
||||
if(APPLE)
|
||||
# Accessible plugin to make buttons look decent on osx
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/accessible"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "quick" EXCLUDE
|
||||
REGEX "d\\." EXCLUDE
|
||||
REGEX "_debug\\." EXCLUDE
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# qtconf
|
||||
install(
|
||||
CODE "
|
||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${QTCONF_DEST_DIR}/qt.conf\" \"\")
|
||||
"
|
||||
COMPONENT Runtime
|
||||
)
|
||||
|
||||
# ICNS file for OS X
|
||||
if(APPLE)
|
||||
install(FILES resources/MultiMC.icns DESTINATION MultiMC.app/Contents/Resources)
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/install_prereqs.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/install_prereqs.cmake"
|
||||
@ONLY
|
||||
)
|
||||
install(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/install_prereqs.cmake" COMPONENT Runtime)
|
||||
|
||||
|
||||
|
||||
######## Package ########
|
||||
|
||||
# Package with CPack
|
||||
if(UNIX)
|
||||
if(APPLE)
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
else()
|
||||
set(CPACK_GENERATOR "TGZ")
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
endif()
|
||||
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0)
|
||||
|
||||
set(CPACK_PACKAGE_NAME "MultiMC 5")
|
||||
set(CPACK_PACKAGE_VENDOR "")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MultiMC - Minecraft launcher and management tool.")
|
||||
set(CPACK_PACKAGE_VERSION "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${MultiMC_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${MultiMC_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${MultiMC_VERSION_REV})
|
||||
|
||||
set(CPACK_PACKAGE_FILE_NAME "MultiMC")
|
||||
|
||||
include(CPack)
|
||||
202
application/ColumnResizer.cpp
Normal file
202
application/ColumnResizer.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright 2011 Aurélien Gâteau <agateau@kde.org>
|
||||
* License: LGPL v2.1 or later (see COPYING)
|
||||
*/
|
||||
#include "ColumnResizer.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QEvent>
|
||||
#include <QFormLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
class FormLayoutWidgetItem : public QWidgetItem
|
||||
{
|
||||
public:
|
||||
FormLayoutWidgetItem(QWidget* widget, QFormLayout* formLayout, QFormLayout::ItemRole itemRole)
|
||||
: QWidgetItem(widget)
|
||||
, m_width(-1)
|
||||
, m_formLayout(formLayout)
|
||||
, m_itemRole(itemRole)
|
||||
{}
|
||||
|
||||
QSize sizeHint() const
|
||||
{
|
||||
QSize size = QWidgetItem::sizeHint();
|
||||
if (m_width != -1) {
|
||||
size.setWidth(m_width);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
QSize minimumSize() const
|
||||
{
|
||||
QSize size = QWidgetItem::minimumSize();
|
||||
if (m_width != -1) {
|
||||
size.setWidth(m_width);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
QSize maximumSize() const
|
||||
{
|
||||
QSize size = QWidgetItem::maximumSize();
|
||||
if (m_width != -1) {
|
||||
size.setWidth(m_width);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void setWidth(int width)
|
||||
{
|
||||
if (width != m_width) {
|
||||
m_width = width;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void setGeometry(const QRect& _rect)
|
||||
{
|
||||
QRect rect = _rect;
|
||||
int width = widget()->sizeHint().width();
|
||||
if (m_itemRole == QFormLayout::LabelRole && m_formLayout->labelAlignment() & Qt::AlignRight) {
|
||||
rect.setLeft(rect.right() - width);
|
||||
}
|
||||
QWidgetItem::setGeometry(rect);
|
||||
}
|
||||
|
||||
QFormLayout* formLayout() const
|
||||
{
|
||||
return m_formLayout;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_width;
|
||||
QFormLayout* m_formLayout;
|
||||
QFormLayout::ItemRole m_itemRole;
|
||||
};
|
||||
|
||||
typedef QPair<QGridLayout*, int> GridColumnInfo;
|
||||
|
||||
class ColumnResizerPrivate
|
||||
{
|
||||
public:
|
||||
ColumnResizerPrivate(ColumnResizer* q_ptr)
|
||||
: q(q_ptr)
|
||||
, m_updateTimer(new QTimer(q))
|
||||
{
|
||||
m_updateTimer->setSingleShot(true);
|
||||
m_updateTimer->setInterval(0);
|
||||
QObject::connect(m_updateTimer, SIGNAL(timeout()), q, SLOT(updateWidth()));
|
||||
}
|
||||
|
||||
void scheduleWidthUpdate()
|
||||
{
|
||||
m_updateTimer->start();
|
||||
}
|
||||
|
||||
ColumnResizer* q;
|
||||
QTimer* m_updateTimer;
|
||||
QList<QWidget*> m_widgets;
|
||||
QList<FormLayoutWidgetItem*> m_wrWidgetItemList;
|
||||
QList<GridColumnInfo> m_gridColumnInfoList;
|
||||
};
|
||||
|
||||
ColumnResizer::ColumnResizer(QObject* parent)
|
||||
: QObject(parent)
|
||||
, d(new ColumnResizerPrivate(this))
|
||||
{}
|
||||
|
||||
ColumnResizer::~ColumnResizer()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void ColumnResizer::addWidget(QWidget* widget)
|
||||
{
|
||||
d->m_widgets.append(widget);
|
||||
widget->installEventFilter(this);
|
||||
d->scheduleWidthUpdate();
|
||||
}
|
||||
|
||||
void ColumnResizer::updateWidth()
|
||||
{
|
||||
int width = 0;
|
||||
Q_FOREACH(QWidget* widget, d->m_widgets) {
|
||||
width = qMax(widget->sizeHint().width(), width);
|
||||
}
|
||||
Q_FOREACH(FormLayoutWidgetItem* item, d->m_wrWidgetItemList) {
|
||||
item->setWidth(width);
|
||||
item->formLayout()->update();
|
||||
}
|
||||
Q_FOREACH(GridColumnInfo info, d->m_gridColumnInfoList) {
|
||||
info.first->setColumnMinimumWidth(info.second, width);
|
||||
}
|
||||
}
|
||||
|
||||
bool ColumnResizer::eventFilter(QObject*, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::Resize) {
|
||||
d->scheduleWidthUpdate();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ColumnResizer::addWidgetsFromLayout(QLayout* layout, int column)
|
||||
{
|
||||
Q_ASSERT(column >= 0);
|
||||
QGridLayout* gridLayout = qobject_cast<QGridLayout*>(layout);
|
||||
QFormLayout* formLayout = qobject_cast<QFormLayout*>(layout);
|
||||
if (gridLayout) {
|
||||
addWidgetsFromGridLayout(gridLayout, column);
|
||||
} else if (formLayout) {
|
||||
if (column > QFormLayout::SpanningRole) {
|
||||
qCritical() << "column should not be more than" << QFormLayout::SpanningRole << "for QFormLayout";
|
||||
return;
|
||||
}
|
||||
QFormLayout::ItemRole role = static_cast<QFormLayout::ItemRole>(column);
|
||||
addWidgetsFromFormLayout(formLayout, role);
|
||||
} else {
|
||||
qCritical() << "Don't know how to handle layout" << layout;
|
||||
}
|
||||
}
|
||||
|
||||
void ColumnResizer::addWidgetsFromGridLayout(QGridLayout* layout, int column)
|
||||
{
|
||||
for (int row = 0; row < layout->rowCount(); ++row) {
|
||||
QLayoutItem* item = layout->itemAtPosition(row, column);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
QWidget* widget = item->widget();
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
addWidget(widget);
|
||||
}
|
||||
d->m_gridColumnInfoList << GridColumnInfo(layout, column);
|
||||
}
|
||||
|
||||
void ColumnResizer::addWidgetsFromFormLayout(QFormLayout* layout, QFormLayout::ItemRole role)
|
||||
{
|
||||
for (int row = 0; row < layout->rowCount(); ++row) {
|
||||
QLayoutItem* item = layout->itemAt(row, role);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
QWidget* widget = item->widget();
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
layout->removeItem(item);
|
||||
delete item;
|
||||
FormLayoutWidgetItem* newItem = new FormLayoutWidgetItem(widget, layout, role);
|
||||
layout->setItem(row, role, newItem);
|
||||
addWidget(widget);
|
||||
d->m_wrWidgetItemList << newItem;
|
||||
}
|
||||
}
|
||||
|
||||
#include <ColumnResizer.moc>
|
||||
// vi: ts=4 sw=4 et
|
||||
38
application/ColumnResizer.h
Normal file
38
application/ColumnResizer.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2011 Aurélien Gâteau <agateau@kde.org>
|
||||
* License: LGPL v2.1 or later (see COPYING)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QFormLayout>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QList>
|
||||
|
||||
class QEvent;
|
||||
class QGridLayout;
|
||||
class QLayout;
|
||||
class QWidget;
|
||||
|
||||
class ColumnResizerPrivate;
|
||||
class ColumnResizer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColumnResizer(QObject* parent = 0);
|
||||
~ColumnResizer();
|
||||
|
||||
void addWidget(QWidget* widget);
|
||||
void addWidgetsFromLayout(QLayout*, int column);
|
||||
void addWidgetsFromGridLayout(QGridLayout*, int column);
|
||||
void addWidgetsFromFormLayout(QFormLayout*, QFormLayout::ItemRole role);
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateWidth();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject*, QEvent* event);
|
||||
|
||||
private:
|
||||
ColumnResizerPrivate* const d;
|
||||
};
|
||||
260
application/ConsoleWindow.cpp
Normal file
260
application/ConsoleWindow.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ConsoleWindow.h"
|
||||
#include "MultiMC.h"
|
||||
|
||||
#include <QScrollBar>
|
||||
#include <QMessageBox>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <qlayoutitem.h>
|
||||
#include <QCloseEvent>
|
||||
|
||||
#include <Platform.h>
|
||||
#include <dialogs/CustomMessageBox.h>
|
||||
#include <dialogs/ProgressDialog.h>
|
||||
#include "widgets/PageContainer.h"
|
||||
#include "pages/LogPage.h"
|
||||
#include "InstancePageProvider.h"
|
||||
|
||||
#include "icons/IconList.h"
|
||||
|
||||
class LogPageProvider : public BasePageProvider
|
||||
{
|
||||
public:
|
||||
LogPageProvider(BasePageProviderPtr parent, BasePage * log_page)
|
||||
{
|
||||
m_parent = parent;
|
||||
m_log_page = log_page;
|
||||
}
|
||||
virtual QString dialogTitle() {return "Fake";};
|
||||
virtual QList<BasePage *> getPages()
|
||||
{
|
||||
auto pages = m_parent->getPages();
|
||||
pages.prepend(m_log_page);
|
||||
return pages;
|
||||
}
|
||||
private:
|
||||
BasePageProviderPtr m_parent;
|
||||
BasePage * m_log_page;
|
||||
};
|
||||
|
||||
ConsoleWindow::ConsoleWindow(BaseProcess *process, QWidget *parent)
|
||||
: QMainWindow(parent), m_proc(process)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
auto instance = m_proc->instance();
|
||||
auto icon = ENV.icons()->getIcon(instance->iconKey());
|
||||
QString windowTitle = tr("Console window for ") + instance->name();
|
||||
|
||||
// Set window properties
|
||||
{
|
||||
setWindowIcon(icon);
|
||||
setWindowTitle(windowTitle);
|
||||
}
|
||||
|
||||
// Add page container
|
||||
{
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
auto provider = std::make_shared<InstancePageProvider>(m_proc->instance());
|
||||
auto baseprovider = std::dynamic_pointer_cast<BasePageProvider>(provider);
|
||||
auto proxy_provider = std::make_shared<LogPageProvider>(baseprovider, new LogPage(m_proc));
|
||||
m_container = new PageContainer(proxy_provider, "console", this);
|
||||
mainLayout->addWidget(m_container);
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->setContentsMargins(0,0,0,0);
|
||||
setLayout(mainLayout);
|
||||
setCentralWidget(m_container);
|
||||
}
|
||||
|
||||
// Add custom buttons to the page container layout.
|
||||
{
|
||||
auto horizontalLayout = new QHBoxLayout();
|
||||
horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
|
||||
horizontalLayout->setContentsMargins(6, -1, 6, -1);
|
||||
|
||||
auto btnHelp = new QPushButton();
|
||||
btnHelp->setText(tr("Help"));
|
||||
horizontalLayout->addWidget(btnHelp);
|
||||
connect(btnHelp, SIGNAL(clicked(bool)), m_container, SLOT(help()));
|
||||
|
||||
auto spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
horizontalLayout->addSpacerItem(spacer);
|
||||
|
||||
m_killButton = new QPushButton();
|
||||
m_killButton->setText(tr("Kill Minecraft"));
|
||||
horizontalLayout->addWidget(m_killButton);
|
||||
connect(m_killButton, SIGNAL(clicked(bool)), SLOT(on_btnKillMinecraft_clicked()));
|
||||
|
||||
m_closeButton = new QPushButton();
|
||||
m_closeButton->setText(tr("Close"));
|
||||
horizontalLayout->addWidget(m_closeButton);
|
||||
connect(m_closeButton, SIGNAL(clicked(bool)), SLOT(on_closeButton_clicked()));
|
||||
|
||||
m_container->addButtons(horizontalLayout);
|
||||
}
|
||||
|
||||
// restore window state
|
||||
{
|
||||
auto base64State = MMC->settings()->get("ConsoleWindowState").toByteArray();
|
||||
restoreState(QByteArray::fromBase64(base64State));
|
||||
auto base64Geometry = MMC->settings()->get("ConsoleWindowGeometry").toByteArray();
|
||||
restoreGeometry(QByteArray::fromBase64(base64Geometry));
|
||||
}
|
||||
|
||||
// Set up tray icon
|
||||
{
|
||||
m_trayIcon = new QSystemTrayIcon(icon, this);
|
||||
m_trayIcon->setToolTip(windowTitle);
|
||||
|
||||
connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
|
||||
SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
|
||||
m_trayIcon->show();
|
||||
}
|
||||
|
||||
// Set up signal connections
|
||||
connect(m_proc, SIGNAL(ended(InstancePtr, int, QProcess::ExitStatus)), this,
|
||||
SLOT(onEnded(InstancePtr, int, QProcess::ExitStatus)));
|
||||
connect(m_proc, SIGNAL(prelaunch_failed(InstancePtr, int, QProcess::ExitStatus)), this,
|
||||
SLOT(onEnded(InstancePtr, int, QProcess::ExitStatus)));
|
||||
connect(m_proc, SIGNAL(launch_failed(InstancePtr)), this,
|
||||
SLOT(onLaunchFailed(InstancePtr)));
|
||||
|
||||
setMayClose(false);
|
||||
|
||||
if (m_proc->instance()->settings().get("ShowConsole").toBool())
|
||||
{
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
|
||||
{
|
||||
switch (reason)
|
||||
{
|
||||
case QSystemTrayIcon::Trigger:
|
||||
{
|
||||
toggleConsole();
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::on_closeButton_clicked()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void ConsoleWindow::setMayClose(bool mayclose)
|
||||
{
|
||||
if(mayclose)
|
||||
m_closeButton->setText(tr("Close"));
|
||||
else
|
||||
m_closeButton->setText(tr("Hide"));
|
||||
m_mayclose = mayclose;
|
||||
}
|
||||
|
||||
void ConsoleWindow::toggleConsole()
|
||||
{
|
||||
if (isVisible())
|
||||
{
|
||||
if(!isActiveWindow())
|
||||
{
|
||||
activateWindow();
|
||||
return;
|
||||
}
|
||||
hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if (!m_mayclose)
|
||||
{
|
||||
toggleConsole();
|
||||
event->ignore();
|
||||
}
|
||||
else if(m_container->requestClose(event))
|
||||
{
|
||||
MMC->settings()->set("ConsoleWindowState", saveState().toBase64());
|
||||
MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
|
||||
|
||||
emit isClosing();
|
||||
m_trayIcon->hide();
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::on_btnKillMinecraft_clicked()
|
||||
{
|
||||
m_killButton->setEnabled(false);
|
||||
auto response = CustomMessageBox::selectable(
|
||||
this, tr("Kill Minecraft?"),
|
||||
tr("This can cause the instance to get corrupted and should only be used if Minecraft "
|
||||
"is frozen for some reason"),
|
||||
QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec();
|
||||
if (response == QMessageBox::Yes)
|
||||
m_proc->killProcess();
|
||||
else
|
||||
m_killButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void ConsoleWindow::onEnded(InstancePtr instance, int code, QProcess::ExitStatus status)
|
||||
{
|
||||
bool peacefulExit = code == 0 && status != QProcess::CrashExit;
|
||||
m_killButton->setEnabled(false);
|
||||
setMayClose(true);
|
||||
if (instance->settings().get("AutoCloseConsole").toBool())
|
||||
{
|
||||
if (peacefulExit)
|
||||
{
|
||||
this->close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!isVisible())
|
||||
{
|
||||
show();
|
||||
}
|
||||
// Raise Window
|
||||
if (MMC->settings()->get("RaiseConsole").toBool())
|
||||
{
|
||||
raise();
|
||||
activateWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleWindow::onLaunchFailed(InstancePtr instance)
|
||||
{
|
||||
m_killButton->setEnabled(false);
|
||||
|
||||
setMayClose(true);
|
||||
|
||||
if (!isVisible())
|
||||
show();
|
||||
}
|
||||
ConsoleWindow::~ConsoleWindow()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,20 +17,17 @@
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QSystemTrayIcon>
|
||||
#include "logic/MinecraftProcess.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ConsoleWindow;
|
||||
}
|
||||
#include "BaseProcess.h"
|
||||
|
||||
class QPushButton;
|
||||
class PageContainer;
|
||||
class ConsoleWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConsoleWindow(MinecraftProcess *proc, QWidget *parent = 0);
|
||||
~ConsoleWindow();
|
||||
explicit ConsoleWindow(BaseProcess *proc, QWidget *parent = 0);
|
||||
virtual ~ConsoleWindow();
|
||||
|
||||
/**
|
||||
* @brief specify if the window is allowed to close
|
||||
@@ -39,57 +36,30 @@ public:
|
||||
*/
|
||||
void setMayClose(bool mayclose);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief write a colored paragraph
|
||||
* @param data the string
|
||||
* @param color the css color name
|
||||
* this will only insert a single paragraph.
|
||||
* \n are ignored. a real \n is always appended.
|
||||
*/
|
||||
void writeColor(QString text, const char *color, const char *background);
|
||||
|
||||
signals:
|
||||
void isClosing();
|
||||
void uploadScreenshots();
|
||||
|
||||
public
|
||||
slots:
|
||||
/**
|
||||
* @brief write a string
|
||||
* @param data the string
|
||||
* @param mode the WriteMode
|
||||
* lines have to be put through this as a whole!
|
||||
*/
|
||||
void write(QString data, MessageLevel::Enum level = MessageLevel::MultiMC);
|
||||
|
||||
/**
|
||||
* @brief clear the text widget
|
||||
*/
|
||||
void clear();
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_closeButton_clicked();
|
||||
void on_btnKillMinecraft_clicked();
|
||||
void onEnded(BaseInstance *instance, int code, QProcess::ExitStatus status);
|
||||
void onLaunchFailed(BaseInstance *instance);
|
||||
|
||||
void onEnded(InstancePtr instance, int code, QProcess::ExitStatus status);
|
||||
void onLaunchFailed(InstancePtr instance);
|
||||
|
||||
// FIXME: add handlers for the other MinecraftProcess signals (pre/post launch command
|
||||
// failures)
|
||||
|
||||
void on_btnPaste_clicked();
|
||||
void iconActivated(QSystemTrayIcon::ActivationReason);
|
||||
void toggleConsole();
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *);
|
||||
|
||||
private:
|
||||
Ui::ConsoleWindow *ui = nullptr;
|
||||
MinecraftProcess *proc = nullptr;
|
||||
BaseProcess *m_proc = nullptr;
|
||||
bool m_mayclose = true;
|
||||
int m_last_scroll_value = 0;
|
||||
bool m_scroll_active = true;
|
||||
QSystemTrayIcon *m_trayIcon = nullptr;
|
||||
int m_saved_offset = 0;
|
||||
PageContainer *m_container = nullptr;
|
||||
QPushButton *m_closeButton = nullptr;
|
||||
QPushButton *m_killButton = nullptr;
|
||||
};
|
||||
101
application/GuiUtil.cpp
Normal file
101
application/GuiUtil.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
#include "GuiUtil.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QDesktopServices>
|
||||
#include <QApplication>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "dialogs/ProgressDialog.h"
|
||||
#include "net/PasteUpload.h"
|
||||
#include "dialogs/CustomMessageBox.h"
|
||||
|
||||
#include "MultiMC.h"
|
||||
#include <settings/SettingsObject.h>
|
||||
|
||||
void GuiUtil::uploadPaste(const QString &text, QWidget *parentWidget)
|
||||
{
|
||||
ProgressDialog dialog(parentWidget);
|
||||
std::unique_ptr<PasteUpload> paste(new PasteUpload(parentWidget, text));
|
||||
|
||||
if (!paste->validateText())
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
parentWidget, QObject::tr("Upload failed"),
|
||||
QObject::tr("The log file is too big. You'll have to upload it manually."),
|
||||
QMessageBox::Warning)->exec();
|
||||
return;
|
||||
}
|
||||
|
||||
dialog.exec(paste.get());
|
||||
if (!paste->successful())
|
||||
{
|
||||
CustomMessageBox::selectable(parentWidget, QObject::tr("Upload failed"),
|
||||
paste->failReason(), QMessageBox::Critical)->exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
const QString link = paste->pasteLink();
|
||||
setClipboardText(link);
|
||||
QDesktopServices::openUrl(link);
|
||||
CustomMessageBox::selectable(
|
||||
parentWidget, QObject::tr("Upload finished"),
|
||||
QObject::tr("The <a href=\"%1\">link to the uploaded log</a> has been opened in "
|
||||
"the default "
|
||||
"browser and placed in your clipboard.").arg(link),
|
||||
QMessageBox::Information)->exec();
|
||||
}
|
||||
}
|
||||
|
||||
void GuiUtil::setClipboardText(const QString &text)
|
||||
{
|
||||
QApplication::clipboard()->setText(text);
|
||||
}
|
||||
|
||||
QStringList GuiUtil::BrowseForMods(QString context, QString caption, QString filter,
|
||||
QWidget *parentWidget)
|
||||
{
|
||||
static QMap<QString, QString> savedPaths;
|
||||
|
||||
QFileDialog w(parentWidget, caption);
|
||||
QSet<QString> locations;
|
||||
QString modsFolder = MMC->settings()->get("CentralModsDir").toString();
|
||||
auto f = [&](QStandardPaths::StandardLocation l)
|
||||
{
|
||||
QString location = QStandardPaths::writableLocation(l);
|
||||
QFileInfo finfo(location);
|
||||
if (!finfo.exists())
|
||||
return;
|
||||
locations.insert(location);
|
||||
};
|
||||
f(QStandardPaths::DesktopLocation);
|
||||
f(QStandardPaths::DocumentsLocation);
|
||||
f(QStandardPaths::DownloadLocation);
|
||||
f(QStandardPaths::HomeLocation);
|
||||
QList<QUrl> urls;
|
||||
for (auto location : locations)
|
||||
{
|
||||
urls.append(QUrl::fromLocalFile(location));
|
||||
}
|
||||
urls.append(QUrl::fromLocalFile(modsFolder));
|
||||
|
||||
w.setFileMode(QFileDialog::ExistingFiles);
|
||||
w.setAcceptMode(QFileDialog::AcceptOpen);
|
||||
w.setNameFilter(filter);
|
||||
if(savedPaths.contains(context))
|
||||
{
|
||||
w.setDirectory(savedPaths[context]);
|
||||
}
|
||||
else
|
||||
{
|
||||
w.setDirectory(modsFolder);
|
||||
}
|
||||
w.setSidebarUrls(urls);
|
||||
|
||||
if (w.exec())
|
||||
{
|
||||
savedPaths[context] = w.directory().absolutePath();
|
||||
return w.selectedFiles();
|
||||
}
|
||||
savedPaths[context] = w.directory().absolutePath();
|
||||
return {};
|
||||
}
|
||||
10
application/GuiUtil.h
Normal file
10
application/GuiUtil.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace GuiUtil
|
||||
{
|
||||
void uploadPaste(const QString &text, QWidget *parentWidget);
|
||||
void setClipboardText(const QString &text);
|
||||
QStringList BrowseForMods(QString context, QString caption, QString filter, QWidget *parentWidget);
|
||||
}
|
||||
0
application/InstancePageProvider.cpp
Normal file
0
application/InstancePageProvider.cpp
Normal file
73
application/InstancePageProvider.h
Normal file
73
application/InstancePageProvider.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
#include "minecraft/OneSixInstance.h"
|
||||
#include "minecraft/LegacyInstance.h"
|
||||
#include "pages/BasePage.h"
|
||||
#include "pages/VersionPage.h"
|
||||
#include "pages/ModFolderPage.h"
|
||||
#include "pages/ResourcePackPage.h"
|
||||
#include "pages/TexturePackPage.h"
|
||||
#include "pages/NotesPage.h"
|
||||
#include "pages/ScreenshotsPage.h"
|
||||
#include "pages/InstanceSettingsPage.h"
|
||||
#include "pages/OtherLogsPage.h"
|
||||
#include "pages/BasePageProvider.h"
|
||||
#include "pages/LegacyJarModPage.h"
|
||||
#include <pathutils.h>
|
||||
|
||||
|
||||
class InstancePageProvider : public QObject, public BasePageProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InstancePageProvider(InstancePtr parent)
|
||||
{
|
||||
inst = parent;
|
||||
}
|
||||
|
||||
virtual ~InstancePageProvider() {};
|
||||
virtual QList<BasePage *> getPages() override
|
||||
{
|
||||
QList<BasePage *> values;
|
||||
std::shared_ptr<OneSixInstance> onesix = std::dynamic_pointer_cast<OneSixInstance>(inst);
|
||||
if(onesix)
|
||||
{
|
||||
values.append(new VersionPage(onesix.get()));
|
||||
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods", tr("Loader mods"), "Loader-mods");
|
||||
modsPage->setFilter(tr("%1 (*.zip *.jar *.litemod)"));
|
||||
values.append(modsPage);
|
||||
values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList(), "coremods", "coremods", tr("Core mods"), "Core-mods"));
|
||||
values.append(new ResourcePackPage(onesix.get()));
|
||||
values.append(new TexturePackPage(onesix.get()));
|
||||
values.append(new NotesPage(onesix.get()));
|
||||
values.append(new ScreenshotsPage(PathCombine(onesix->minecraftRoot(), "screenshots")));
|
||||
values.append(new InstanceSettingsPage(onesix.get()));
|
||||
values.append(new OtherLogsPage(onesix->minecraftRoot()));
|
||||
}
|
||||
std::shared_ptr<LegacyInstance> legacy = std::dynamic_pointer_cast<LegacyInstance>(inst);
|
||||
if(legacy)
|
||||
{
|
||||
QList<BasePage *> values;
|
||||
// FIXME: actually implement the legacy instance upgrade, then enable this.
|
||||
//values.append(new LegacyUpgradePage(this));
|
||||
values.append(new LegacyJarModPage(legacy.get()));
|
||||
auto modsPage = new ModFolderPage(legacy.get(), legacy->loaderModList(), "mods", "loadermods", tr("Loader mods"), "Loader-mods");
|
||||
modsPage->setFilter(tr("%1 (*.zip *.jar *.litemod)"));
|
||||
values.append(modsPage);
|
||||
values.append(new ModFolderPage(legacy.get(), legacy->coreModList(), "coremods", "coremods", tr("Core mods"), "Loader-mods"));
|
||||
values.append(new TexturePackPage(legacy.get()));
|
||||
values.append(new NotesPage(legacy.get()));
|
||||
values.append(new ScreenshotsPage(PathCombine(legacy->minecraftRoot(), "screenshots")));
|
||||
values.append(new InstanceSettingsPage(legacy.get()));
|
||||
values.append(new OtherLogsPage(legacy->minecraftRoot()));
|
||||
return values;
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
virtual QString dialogTitle() override
|
||||
{
|
||||
return tr("Edit Instance (%1)").arg(inst->name());
|
||||
}
|
||||
protected:
|
||||
InstancePtr inst;
|
||||
};
|
||||
23
application/InstanceProxyModel.cpp
Normal file
23
application/InstanceProxyModel.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "InstanceProxyModel.h"
|
||||
#include "MultiMC.h"
|
||||
#include <BaseInstance.h>
|
||||
|
||||
InstanceProxyModel::InstanceProxyModel(QObject *parent) : GroupedProxyModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool InstanceProxyModel::subSortLessThan(const QModelIndex &left,
|
||||
const QModelIndex &right) const
|
||||
{
|
||||
BaseInstance *pdataLeft = static_cast<BaseInstance *>(left.internalPointer());
|
||||
BaseInstance *pdataRight = static_cast<BaseInstance *>(right.internalPointer());
|
||||
QString sortMode = MMC->settings()->get("InstSortMode").toString();
|
||||
if (sortMode == "LastLaunch")
|
||||
{
|
||||
return pdataLeft->lastLaunch() > pdataRight->lastLaunch();
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString::localeAwareCompare(pdataLeft->name(), pdataRight->name()) < 0;
|
||||
}
|
||||
}
|
||||
13
application/InstanceProxyModel.h
Normal file
13
application/InstanceProxyModel.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "groupview/GroupedProxyModel.h"
|
||||
|
||||
/**
|
||||
* A proxy model that is responsible for sorting instances into groups
|
||||
*/
|
||||
class InstanceProxyModel : public GroupedProxyModel
|
||||
{
|
||||
public:
|
||||
explicit InstanceProxyModel(QObject *parent = 0);
|
||||
|
||||
protected:
|
||||
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||
};
|
||||
107
application/JavaCommon.cpp
Normal file
107
application/JavaCommon.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "JavaCommon.h"
|
||||
#include "dialogs/CustomMessageBox.h"
|
||||
#include <MMCStrings.h>
|
||||
|
||||
bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget *parent)
|
||||
{
|
||||
if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegExp("-Xm[sx]")))
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
parent, QObject::tr("JVM arguments warning"),
|
||||
QObject::tr("You tried to manually set a JVM memory option (using "
|
||||
" \"-XX:PermSize\", \"-Xmx\" or \"-Xms\") - there"
|
||||
" are dedicated boxes for these in the settings (Java"
|
||||
" tab, in the Memory group at the top).\n"
|
||||
"Your manual settings will be overridden by the"
|
||||
" dedicated options.\n"
|
||||
"This message will be displayed until you remove them"
|
||||
" from the JVM arguments."),
|
||||
QMessageBox::Warning)->exec();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void JavaCommon::TestCheck::javaWasOk(JavaCheckResult result)
|
||||
{
|
||||
QString text;
|
||||
text += tr("Java test succeeded!<br />Platform reported: %1<br />Java version "
|
||||
"reported: %2<br />").arg(result.realPlatform, result.javaVersion);
|
||||
if (result.errorLog.size())
|
||||
{
|
||||
auto htmlError = result.errorLog;
|
||||
htmlError.replace('\n', "<br />");
|
||||
text += tr("<br />Warnings:<br /><font color=\"orange\">%1</font>").arg(htmlError);
|
||||
}
|
||||
CustomMessageBox::selectable(m_parent, tr("Java test success"), text,
|
||||
QMessageBox::Information)->show();
|
||||
}
|
||||
|
||||
void JavaCommon::TestCheck::javaArgsWereBad(JavaCheckResult result)
|
||||
{
|
||||
auto htmlError = result.errorLog;
|
||||
QString text;
|
||||
htmlError.replace('\n', "<br />");
|
||||
text += tr("The specified java binary didn't work with the arguments you provided:<br />");
|
||||
text += tr("<font color=\"red\">%1</font>").arg(htmlError);
|
||||
CustomMessageBox::selectable(m_parent, tr("Java test failure"), text, QMessageBox::Warning)
|
||||
->show();
|
||||
}
|
||||
|
||||
void JavaCommon::TestCheck::javaBinaryWasBad(JavaCheckResult result)
|
||||
{
|
||||
QString text;
|
||||
text += tr(
|
||||
"The specified java binary didn't work.<br />You should use the auto-detect feature, "
|
||||
"or set the path to the java executable.<br />");
|
||||
CustomMessageBox::selectable(m_parent, tr("Java test failure"), text, QMessageBox::Warning)
|
||||
->show();
|
||||
}
|
||||
|
||||
void JavaCommon::TestCheck::run()
|
||||
{
|
||||
if (!JavaCommon::checkJVMArgs(m_args, m_parent))
|
||||
{
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
checker.reset(new JavaChecker());
|
||||
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
|
||||
SLOT(checkFinished(JavaCheckResult)));
|
||||
checker->m_path = m_path;
|
||||
checker->performCheck();
|
||||
}
|
||||
|
||||
void JavaCommon::TestCheck::checkFinished(JavaCheckResult result)
|
||||
{
|
||||
if (!result.valid)
|
||||
{
|
||||
javaBinaryWasBad(result);
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
checker.reset(new JavaChecker());
|
||||
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
|
||||
SLOT(checkFinishedWithArgs(JavaCheckResult)));
|
||||
checker->m_path = m_path;
|
||||
checker->m_args = m_args;
|
||||
checker->m_minMem = m_minMem;
|
||||
checker->m_maxMem = m_maxMem;
|
||||
if (Strings::naturalCompare(result.javaVersion, "1.8", Qt::CaseInsensitive) < 0)
|
||||
{
|
||||
checker->m_permGen = m_permGen;
|
||||
}
|
||||
checker->performCheck();
|
||||
}
|
||||
|
||||
void JavaCommon::TestCheck::checkFinishedWithArgs(JavaCheckResult result)
|
||||
{
|
||||
if (result.valid)
|
||||
{
|
||||
javaWasOk(result);
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
javaArgsWereBad(result);
|
||||
emit finished();
|
||||
}
|
||||
46
application/JavaCommon.h
Normal file
46
application/JavaCommon.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
#include <java/JavaChecker.h>
|
||||
|
||||
class QWidget;
|
||||
|
||||
/**
|
||||
* Common UI bits for the java pages to use.
|
||||
*/
|
||||
namespace JavaCommon
|
||||
{
|
||||
bool checkJVMArgs(QString args, QWidget *parent);
|
||||
|
||||
class TestCheck : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestCheck(QWidget *parent, QString path, QString args, int minMem, int maxMem, int permGen)
|
||||
:m_parent(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen)
|
||||
{
|
||||
}
|
||||
virtual ~TestCheck() {};
|
||||
|
||||
void run();
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
|
||||
private:
|
||||
void javaBinaryWasBad(JavaCheckResult result);
|
||||
void javaArgsWereBad(JavaCheckResult result);
|
||||
void javaWasOk(JavaCheckResult result);
|
||||
|
||||
private slots:
|
||||
void checkFinished(JavaCheckResult result);
|
||||
void checkFinishedWithArgs(JavaCheckResult result);
|
||||
|
||||
private:
|
||||
std::shared_ptr<JavaChecker> checker;
|
||||
QWidget *m_parent = nullptr;
|
||||
QString m_path;
|
||||
QString m_args;
|
||||
int m_minMem = 0;
|
||||
int m_maxMem = 0;
|
||||
int m_permGen = 64;
|
||||
};
|
||||
}
|
||||
2000
application/MainWindow.cpp
Normal file
2000
application/MainWindow.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,18 +19,21 @@
|
||||
#include <QProcess>
|
||||
#include <QTimer>
|
||||
|
||||
#include "logic/lists/InstanceList.h"
|
||||
#include "logic/BaseInstance.h"
|
||||
|
||||
#include "logic/auth/MojangAccount.h"
|
||||
#include <logic/net/NetJob.h>
|
||||
#include "BaseInstance.h"
|
||||
#include "auth/MojangAccount.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "updater/GoUpdate.h"
|
||||
|
||||
class NewsChecker;
|
||||
class NotificationChecker;
|
||||
class QToolButton;
|
||||
class InstanceProxyModel;
|
||||
class LabeledToolButton;
|
||||
class QLabel;
|
||||
class MinecraftProcess;
|
||||
class ConsoleWindow;
|
||||
class BaseProfilerFactory;
|
||||
class GenericPageProvider;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@@ -51,7 +54,7 @@ public:
|
||||
void openWebPage(QUrl url);
|
||||
|
||||
void checkSetDefaultJava();
|
||||
void checkMigrateLegacyAssets();
|
||||
void checkInstancePathForProblems();
|
||||
|
||||
private
|
||||
slots:
|
||||
@@ -81,6 +84,8 @@ slots:
|
||||
|
||||
void on_actionSettings_triggered();
|
||||
|
||||
void on_actionInstanceSettings_triggered();
|
||||
|
||||
void on_actionManageAccounts_triggered();
|
||||
|
||||
void on_actionReportBug_triggered();
|
||||
@@ -101,16 +106,16 @@ slots:
|
||||
|
||||
void on_actionDeleteInstance_triggered();
|
||||
|
||||
void on_actionExportInstance_triggered();
|
||||
|
||||
void on_actionRenameInstance_triggered();
|
||||
|
||||
void on_actionMakeDesktopShortcut_triggered();
|
||||
|
||||
void on_actionChangeInstMCVersion_triggered();
|
||||
|
||||
void on_actionEditInstMods_triggered();
|
||||
void on_actionEditInstance_triggered();
|
||||
|
||||
void on_actionEditInstNotes_triggered();
|
||||
|
||||
void on_actionScreenshots_triggered();
|
||||
|
||||
/*!
|
||||
* Launches the currently selected instance with the default account.
|
||||
* If no default account is selected, prompts the user to pick an account.
|
||||
@@ -133,19 +138,13 @@ slots:
|
||||
void taskStart();
|
||||
void taskEnd();
|
||||
|
||||
void on_actionChangeInstLWJGLVersion_triggered();
|
||||
|
||||
void instanceEnded();
|
||||
|
||||
void on_actionInstanceSettings_triggered();
|
||||
|
||||
// called when an icon is changed in the icon model.
|
||||
void iconUpdated(QString);
|
||||
|
||||
void showInstanceContextMenu(const QPoint &);
|
||||
|
||||
void on_actionScreenshots_triggered();
|
||||
|
||||
void updateToolsMenu();
|
||||
|
||||
void skinJobFinished();
|
||||
@@ -155,11 +154,15 @@ slots:
|
||||
|
||||
void instanceChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
|
||||
void instanceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
|
||||
|
||||
void selectionBad();
|
||||
|
||||
void startTask(Task *task);
|
||||
|
||||
void updateAvailable(QString repo, QString versionName, int versionId);
|
||||
void updateAvailable(GoUpdate::Status status);
|
||||
|
||||
void updateNotAvailable();
|
||||
|
||||
void notificationsChanged();
|
||||
|
||||
@@ -171,16 +174,10 @@ slots:
|
||||
|
||||
void updateNewsLabel();
|
||||
|
||||
void updateStatusUI();
|
||||
|
||||
void updateStatusFailedUI();
|
||||
|
||||
void reloadStatus();
|
||||
|
||||
/*!
|
||||
* Runs the DownloadUpdateTask and installs updates.
|
||||
* Runs the DownloadTask and installs updates.
|
||||
*/
|
||||
void downloadUpdates(QString repo, int versionId, bool installOnExit = false);
|
||||
void downloadUpdates(GoUpdate::Status status, bool installOnExit = false);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *ev);
|
||||
@@ -189,6 +186,11 @@ protected:
|
||||
|
||||
void setSelectedInstanceById(const QString &id);
|
||||
|
||||
void waitForMinecraftVersions();
|
||||
void instanceFromVersion(QString instName, QString instGroup, QString instIcon, BaseVersionPtr version);
|
||||
void instanceFromZipPack(QString instName, QString instGroup, QString instIcon, QUrl url);
|
||||
void finalizeInstance(InstancePtr inst);
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
class GroupView *view;
|
||||
@@ -200,18 +202,19 @@ private:
|
||||
QToolButton *changeIconButton;
|
||||
QToolButton *newsLabel;
|
||||
|
||||
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
|
||||
std::shared_ptr<NewsChecker> m_newsChecker;
|
||||
std::shared_ptr<NotificationChecker> m_notificationChecker;
|
||||
|
||||
InstancePtr m_selectedInstance;
|
||||
QString m_currentInstIcon;
|
||||
|
||||
Task *m_versionLoadTask;
|
||||
|
||||
QLabel *m_statusLeft;
|
||||
QLabel *m_statusRight;
|
||||
QToolButton *m_statusRefresh;
|
||||
class ServerStatus *m_statusRight;
|
||||
|
||||
QMenu *accountMenu;
|
||||
QToolButton *accountMenuButton;
|
||||
QAction *manageAccountsAction;
|
||||
|
||||
QTimer statusTimer;
|
||||
};
|
||||
@@ -10,53 +10,48 @@
|
||||
#include <QMessageBox>
|
||||
#include <QStringList>
|
||||
#include <QDesktopServices>
|
||||
#include <QDebug>
|
||||
|
||||
#include "gui/dialogs/VersionSelectDialog.h"
|
||||
#include "logic/lists/InstanceList.h"
|
||||
#include "logic/auth/MojangAccountList.h"
|
||||
#include "logic/icons/IconList.h"
|
||||
#include "logic/lists/LwjglVersionList.h"
|
||||
#include "logic/lists/MinecraftVersionList.h"
|
||||
#include "logic/lists/ForgeVersionList.h"
|
||||
#include "logic/lists/LiteLoaderVersionList.h"
|
||||
#include "InstanceList.h"
|
||||
#include "auth/MojangAccountList.h"
|
||||
#include "icons/IconList.h"
|
||||
#include "minecraft/LwjglVersionList.h"
|
||||
#include "minecraft/MinecraftVersionList.h"
|
||||
#include "liteloader/LiteLoaderVersionList.h"
|
||||
|
||||
#include "logic/news/NewsChecker.h"
|
||||
#include "forge/ForgeVersionList.h"
|
||||
|
||||
#include "logic/status/StatusChecker.h"
|
||||
#include "net/HttpMetaCache.h"
|
||||
#include "net/URLConstants.h"
|
||||
#include "Env.h"
|
||||
|
||||
#include "logic/InstanceLauncher.h"
|
||||
#include "logic/net/HttpMetaCache.h"
|
||||
#include "logic/net/URLConstants.h"
|
||||
#include "java/JavaUtils.h"
|
||||
|
||||
#include "logic/JavaUtils.h"
|
||||
#include "updater/UpdateChecker.h"
|
||||
|
||||
#include "logic/updater/UpdateChecker.h"
|
||||
#include "logic/updater/NotificationChecker.h"
|
||||
|
||||
#include "logic/tools/JProfiler.h"
|
||||
#include "logic/tools/JVisualVM.h"
|
||||
#include "logic/tools/MCEditTool.h"
|
||||
#include "tools/JProfiler.h"
|
||||
#include "tools/JVisualVM.h"
|
||||
#include "tools/MCEditTool.h"
|
||||
|
||||
#include "pathutils.h"
|
||||
#include "cmdutils.h"
|
||||
#include <inisettingsobject.h>
|
||||
#include <setting.h>
|
||||
#include "logger/QsLog.h"
|
||||
#include <logger/QsLogDest.h>
|
||||
#include <xdgicon.h>
|
||||
#include "settings/INISettingsObject.h"
|
||||
#include "settings/Setting.h"
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
#include <windows.h>
|
||||
static const int APPDATA_BUFFER_SIZE = 1024;
|
||||
#endif
|
||||
#include "trans/TranslationDownloader.h"
|
||||
|
||||
#include "ftb/FTBPlugin.h"
|
||||
|
||||
using namespace Util::Commandline;
|
||||
|
||||
MultiMC::MultiMC(int &argc, char **argv, bool root_override)
|
||||
: QApplication(argc, argv)
|
||||
MultiMC::MultiMC(int &argc, char **argv, bool test_mode) : QApplication(argc, argv)
|
||||
{
|
||||
setOrganizationName("MultiMC");
|
||||
setApplicationName("MultiMC5");
|
||||
|
||||
startTime = QDateTime::currentDateTime();
|
||||
|
||||
setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
// Don't quit on hiding the last window
|
||||
this->setQuitOnLastWindowClosed(false);
|
||||
@@ -79,13 +74,7 @@ MultiMC::MultiMC(int &argc, char **argv, bool root_override)
|
||||
parser.addShortOpt("dir", 'd');
|
||||
parser.addDocumentation("dir", "use the supplied directory as MultiMC root instead of "
|
||||
"the binary location (use '.' for current)");
|
||||
// WARNING: disabled until further notice
|
||||
/*
|
||||
// --launch
|
||||
parser.addOption("launch");
|
||||
parser.addShortOpt("launch", 'l');
|
||||
parser.addDocumentation("launch", "tries to launch the given instance", "<inst>");
|
||||
*/
|
||||
|
||||
// parse the arguments
|
||||
try
|
||||
{
|
||||
@@ -117,8 +106,9 @@ MultiMC::MultiMC(int &argc, char **argv, bool root_override)
|
||||
return;
|
||||
}
|
||||
}
|
||||
origcwdPath = QDir::currentPath();
|
||||
binPath = applicationDirPath();
|
||||
|
||||
QString origcwdPath = QDir::currentPath();
|
||||
QString binPath = applicationDirPath();
|
||||
QString adjustedBy;
|
||||
// change directory
|
||||
QString dirParam = args["dir"].toString();
|
||||
@@ -135,119 +125,138 @@ MultiMC::MultiMC(int &argc, char **argv, bool root_override)
|
||||
adjustedBy += "Fallback to binary path " + dataPath;
|
||||
}
|
||||
|
||||
if(!ensureFolderPathExists(dataPath) || !QDir::setCurrent(dataPath))
|
||||
if (!ensureFolderPathExists(dataPath) || !QDir::setCurrent(dataPath))
|
||||
{
|
||||
// BAD STUFF. WHAT DO?
|
||||
initLogger();
|
||||
QLOG_ERROR() << "Failed to set work path. Will exit. NOW.";
|
||||
qCritical() << "Failed to set work path. Will exit. NOW.";
|
||||
m_status = MultiMC::Failed;
|
||||
return;
|
||||
}
|
||||
|
||||
if (root_override)
|
||||
// in test mode, root path is the same as the binary path.
|
||||
if (test_mode)
|
||||
{
|
||||
rootPath = binPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
#ifdef Q_OS_LINUX
|
||||
QDir foo(PathCombine(binPath, ".."));
|
||||
rootPath = foo.absolutePath();
|
||||
#elif defined(Q_OS_WIN32)
|
||||
#elif defined(Q_OS_WIN32)
|
||||
rootPath = binPath;
|
||||
#elif defined(Q_OS_MAC)
|
||||
#elif defined(Q_OS_MAC)
|
||||
QDir foo(PathCombine(binPath, "../.."));
|
||||
rootPath = foo.absolutePath();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
// static data paths... mostly just for translations
|
||||
#ifdef Q_OS_LINUX
|
||||
QDir foo(PathCombine(binPath, ".."));
|
||||
staticDataPath = foo.absolutePath();
|
||||
#elif defined(Q_OS_WIN32)
|
||||
staticDataPath = binPath;
|
||||
#elif defined(Q_OS_MAC)
|
||||
QDir foo(PathCombine(rootPath, "Contents/Resources"));
|
||||
staticDataPath = foo.absolutePath();
|
||||
#endif
|
||||
|
||||
// init the logger
|
||||
initLogger();
|
||||
|
||||
QLOG_INFO() << "MultiMC 5, (c) 2013 MultiMC Contributors";
|
||||
QLOG_INFO() << "Version : " << BuildConfig.VERSION_STR;
|
||||
QLOG_INFO() << "Git commit : " << BuildConfig.GIT_COMMIT;
|
||||
qDebug() << "MultiMC 5, (c) 2013-2015 MultiMC Contributors";
|
||||
qDebug() << "Version : " << BuildConfig.VERSION_STR;
|
||||
qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
|
||||
if (adjustedBy.size())
|
||||
{
|
||||
QLOG_INFO() << "Work dir before adjustment : " << origcwdPath;
|
||||
QLOG_INFO() << "Work dir after adjustment : " << QDir::currentPath();
|
||||
QLOG_INFO() << "Adjusted by : " << adjustedBy;
|
||||
qDebug() << "Work dir before adjustment : " << origcwdPath;
|
||||
qDebug() << "Work dir after adjustment : " << QDir::currentPath();
|
||||
qDebug() << "Adjusted by : " << adjustedBy;
|
||||
}
|
||||
else
|
||||
{
|
||||
QLOG_INFO() << "Work dir : " << QDir::currentPath();
|
||||
qDebug() << "Work dir : " << QDir::currentPath();
|
||||
}
|
||||
QLOG_INFO() << "Binary path : " << binPath;
|
||||
QLOG_INFO() << "Application root path : " << rootPath;
|
||||
qDebug() << "Binary path : " << binPath;
|
||||
qDebug() << "Application root path : " << rootPath;
|
||||
qDebug() << "Static data path : " << staticDataPath;
|
||||
|
||||
// load settings
|
||||
initGlobalSettings();
|
||||
initGlobalSettings(test_mode);
|
||||
|
||||
// load translations
|
||||
initTranslations();
|
||||
|
||||
// initialize the updater
|
||||
m_updateChecker.reset(new UpdateChecker());
|
||||
m_updateChecker.reset(new UpdateChecker(BuildConfig.CHANLIST_URL, BuildConfig.VERSION_CHANNEL, BuildConfig.VERSION_BUILD));
|
||||
|
||||
// initialize the notification checker
|
||||
m_notificationChecker.reset(new NotificationChecker());
|
||||
m_translationChecker.reset(new TranslationDownloader());
|
||||
|
||||
// initialize the news checker
|
||||
m_newsChecker.reset(new NewsChecker(BuildConfig.NEWS_RSS_URL));
|
||||
|
||||
// initialize the status checker
|
||||
m_statusChecker.reset(new StatusChecker());
|
||||
// load icons
|
||||
initIcons();
|
||||
|
||||
// and instances
|
||||
auto InstDirSetting = m_settings->getSetting("InstanceDir");
|
||||
m_instances.reset(new InstanceList(InstDirSetting->get().toString(), this));
|
||||
QLOG_INFO() << "Loading Instances...";
|
||||
// instance path: check for problems with '!' in instance path and warn the user in the log
|
||||
// and rememer that we have to show him a dialog when the gui starts (if it does so)
|
||||
QString instDir = m_settings->get("InstanceDir").toString();
|
||||
qDebug() << "Instance path : " << instDir;
|
||||
if (checkProblemticPathJava(QDir(instDir)))
|
||||
{
|
||||
qWarning()
|
||||
<< "Your instance path contains \'!\' and this is known to cause java problems";
|
||||
}
|
||||
m_instances.reset(new InstanceList(m_settings, InstDirSetting->get().toString(), this));
|
||||
qDebug() << "Loading Instances...";
|
||||
m_instances->loadList();
|
||||
connect(InstDirSetting.get(), SIGNAL(settingChanged(const Setting &, QVariant)),
|
||||
connect(InstDirSetting.get(), SIGNAL(SettingChanged(const Setting &, QVariant)),
|
||||
m_instances.get(), SLOT(on_InstFolderChanged(const Setting &, QVariant)));
|
||||
|
||||
// and accounts
|
||||
m_accounts.reset(new MojangAccountList(this));
|
||||
QLOG_INFO() << "Loading accounts...";
|
||||
qDebug() << "Loading accounts...";
|
||||
m_accounts->setListFilePath("accounts.json", true);
|
||||
m_accounts->loadList();
|
||||
|
||||
// init the http meta cache
|
||||
initHttpMetaCache();
|
||||
ENV.initHttpMetaCache(rootPath, staticDataPath);
|
||||
|
||||
// create the global network manager
|
||||
m_qnam.reset(new QNetworkAccessManager(this));
|
||||
ENV.m_qnam.reset(new QNetworkAccessManager(this));
|
||||
|
||||
// init proxy settings
|
||||
updateProxySettings();
|
||||
{
|
||||
QString proxyTypeStr = settings()->get("ProxyType").toString();
|
||||
QString addr = settings()->get("ProxyAddr").toString();
|
||||
int port = settings()->get("ProxyPort").value<qint16>();
|
||||
QString user = settings()->get("ProxyUser").toString();
|
||||
QString pass = settings()->get("ProxyPass").toString();
|
||||
ENV.updateProxySettings(proxyTypeStr, addr, port, user, pass);
|
||||
}
|
||||
|
||||
initSSL();
|
||||
|
||||
m_translationChecker->downloadTranslations();
|
||||
|
||||
//FIXME: what to do with these?
|
||||
m_profilers.insert("jprofiler",
|
||||
std::shared_ptr<BaseProfilerFactory>(new JProfilerFactory()));
|
||||
m_profilers.insert("jvisualvm",
|
||||
std::shared_ptr<BaseProfilerFactory>(new JVisualVMFactory()));
|
||||
for (auto profiler : m_profilers.values())
|
||||
{
|
||||
profiler->registerSettings(m_settings.get());
|
||||
}
|
||||
m_tools.insert("mcedit",
|
||||
std::shared_ptr<BaseDetachedToolFactory>(new MCEditFactory()));
|
||||
for (auto tool : m_tools.values())
|
||||
{
|
||||
tool->registerSettings(m_settings.get());
|
||||
profiler->registerSettings(m_settings);
|
||||
}
|
||||
|
||||
// launch instance, if that's what should be done
|
||||
// WARNING: disabled until further notice
|
||||
/*
|
||||
if (!args["launch"].isNull())
|
||||
//FIXME: what to do with these?
|
||||
m_tools.insert("mcedit", std::shared_ptr<BaseDetachedToolFactory>(new MCEditFactory()));
|
||||
for (auto tool : m_tools.values())
|
||||
{
|
||||
if (InstanceLauncher(args["launch"].toString()).launch())
|
||||
m_status = MultiMC::Succeeded;
|
||||
else
|
||||
m_status = MultiMC::Failed;
|
||||
return;
|
||||
tool->registerSettings(m_settings);
|
||||
}
|
||||
*/
|
||||
|
||||
connect(this, SIGNAL(aboutToQuit()), SLOT(onExit()));
|
||||
m_status = MultiMC::Initialized;
|
||||
}
|
||||
@@ -264,20 +273,31 @@ MultiMC::~MultiMC()
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMC::initSSL()
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
Q_INIT_RESOURCE(certs);
|
||||
QFile equifaxFile(":/certs/Equifax_Secure_Certificate_Authority.pem");
|
||||
equifaxFile.open(QIODevice::ReadOnly);
|
||||
QSslCertificate equifaxCert(equifaxFile.readAll(), QSsl::Pem);
|
||||
QSslSocket::addDefaultCaCertificate(equifaxCert);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MultiMC::initTranslations()
|
||||
{
|
||||
QLocale locale(m_settings->get("Language").toString());
|
||||
QLocale::setDefault(locale);
|
||||
QLOG_INFO() << "Your language is" << locale.bcp47Name();
|
||||
qDebug() << "Your language is" << locale.bcp47Name();
|
||||
m_qt_translator.reset(new QTranslator());
|
||||
if (m_qt_translator->load("qt_" + locale.bcp47Name(),
|
||||
QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
||||
{
|
||||
QLOG_DEBUG() << "Loading Qt Language File for"
|
||||
qDebug() << "Loading Qt Language File for"
|
||||
<< locale.bcp47Name().toLocal8Bit().constData() << "...";
|
||||
if (!installTranslator(m_qt_translator.get()))
|
||||
{
|
||||
QLOG_ERROR() << "Loading Qt Language File failed.";
|
||||
qCritical() << "Loading Qt Language File failed.";
|
||||
m_qt_translator.reset();
|
||||
}
|
||||
}
|
||||
@@ -287,13 +307,13 @@ void MultiMC::initTranslations()
|
||||
}
|
||||
|
||||
m_mmc_translator.reset(new QTranslator());
|
||||
if (m_mmc_translator->load("mmc_" + locale.bcp47Name(), MMC->root() + "/translations"))
|
||||
if (m_mmc_translator->load("mmc_" + locale.bcp47Name(), staticDataPath + "/translations"))
|
||||
{
|
||||
QLOG_DEBUG() << "Loading MMC Language File for"
|
||||
qDebug() << "Loading MMC Language File for"
|
||||
<< locale.bcp47Name().toLocal8Bit().constData() << "...";
|
||||
if (!installTranslator(m_mmc_translator.get()))
|
||||
{
|
||||
QLOG_ERROR() << "Loading MMC Language File failed.";
|
||||
qCritical() << "Loading MMC Language File failed.";
|
||||
m_mmc_translator.reset();
|
||||
}
|
||||
}
|
||||
@@ -303,12 +323,45 @@ void MultiMC::initTranslations()
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMC::initIcons()
|
||||
{
|
||||
auto setting = MMC->settings()->getSetting("IconsDir");
|
||||
ENV.m_icons.reset(new IconList(QString(":/icons/instances/"), setting->get().toString()));
|
||||
connect(setting.get(), &Setting::SettingChanged,[&](const Setting &, QVariant value)
|
||||
{
|
||||
ENV.m_icons->directoryChanged(value.toString());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void moveFile(const QString &oldName, const QString &newName)
|
||||
{
|
||||
QFile::remove(newName);
|
||||
QFile::copy(oldName, newName);
|
||||
QFile::remove(oldName);
|
||||
}
|
||||
|
||||
|
||||
void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||
{
|
||||
const char *levels = "DWCF";
|
||||
const QString format("%1 %2 %3\n");
|
||||
|
||||
qint64 msecstotal = MMC->timeSinceStart();
|
||||
qint64 seconds = msecstotal / 1000;
|
||||
qint64 msecs = msecstotal % 1000;
|
||||
QString foo;
|
||||
char buf[1025] = {0};
|
||||
::snprintf(buf, 1024, "%5lld.%03lld", seconds, msecs);
|
||||
|
||||
QString out = format.arg(buf).arg(levels[type]).arg(msg);
|
||||
|
||||
MMC->logFile->write(out.toUtf8());
|
||||
MMC->logFile->flush();
|
||||
QTextStream(stderr) << out.toLocal8Bit();
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
void MultiMC::initLogger()
|
||||
{
|
||||
static const QString logBase = "MultiMC-%0.log";
|
||||
@@ -318,85 +371,58 @@ void MultiMC::initLogger()
|
||||
moveFile(logBase.arg(1), logBase.arg(2));
|
||||
moveFile(logBase.arg(0), logBase.arg(1));
|
||||
|
||||
// init the logging mechanism
|
||||
QsLogging::Logger &logger = QsLogging::Logger::instance();
|
||||
logger.setLoggingLevel(QsLogging::TraceLevel);
|
||||
m_fileDestination = QsLogging::DestinationFactory::MakeFileDestination(logBase.arg(0));
|
||||
m_debugDestination = QsLogging::DestinationFactory::MakeQDebugDestination();
|
||||
logger.addDestination(m_fileDestination.get());
|
||||
logger.addDestination(m_debugDestination.get());
|
||||
// log all the things
|
||||
logger.setLoggingLevel(QsLogging::TraceLevel);
|
||||
qInstallMessageHandler(appDebugOutput);
|
||||
|
||||
logFile = std::make_shared<QFile>(logBase.arg(0));
|
||||
logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
|
||||
}
|
||||
|
||||
void MultiMC::initGlobalSettings()
|
||||
void MultiMC::initGlobalSettings(bool test_mode)
|
||||
{
|
||||
m_settings.reset(new INISettingsObject("multimc.cfg", this));
|
||||
// Updates
|
||||
m_settings->registerSetting("UpdateChannel", BuildConfig.VERSION_CHANNEL);
|
||||
m_settings->registerSetting("AutoUpdate", true);
|
||||
m_settings->registerSetting("IconTheme", QString("multimc"));
|
||||
|
||||
// Notifications
|
||||
m_settings->registerSetting("ShownNotifications", QString());
|
||||
|
||||
// FTB
|
||||
m_settings->registerSetting("TrackFTBInstances", false);
|
||||
#ifdef Q_OS_LINUX
|
||||
QString ftbDefault = QDir::home().absoluteFilePath(".ftblauncher");
|
||||
#elif defined(Q_OS_WIN32)
|
||||
wchar_t buf[APPDATA_BUFFER_SIZE];
|
||||
QString ftbDefault;
|
||||
if(!GetEnvironmentVariableW(L"APPDATA", buf, APPDATA_BUFFER_SIZE))
|
||||
// Remembered state
|
||||
m_settings->registerSetting("LastUsedGroupForNewInstance", QString());
|
||||
|
||||
QString defaultMonospace;
|
||||
int defaultSize = 11;
|
||||
#ifdef Q_OS_WIN32
|
||||
defaultMonospace = "Courier";
|
||||
defaultSize = 10;
|
||||
#elif defined(Q_OS_MAC)
|
||||
defaultMonospace = "Menlo";
|
||||
#else
|
||||
defaultMonospace = "Monospace";
|
||||
#endif
|
||||
if(!test_mode)
|
||||
{
|
||||
QLOG_FATAL() << "Your APPDATA folder is missing! If you are on windows, this means your system is broken. If you aren't on windows, how the **** are you running the windows build????";
|
||||
// resolve the font so the default actually matches
|
||||
QFont consoleFont;
|
||||
consoleFont.setFamily(defaultMonospace);
|
||||
consoleFont.setStyleHint(QFont::Monospace);
|
||||
consoleFont.setFixedPitch(true);
|
||||
QFontInfo consoleFontInfo(consoleFont);
|
||||
QString resolvedDefaultMonospace = consoleFontInfo.family();
|
||||
QFont resolvedFont(resolvedDefaultMonospace);
|
||||
qDebug() << "Detected default console font:" << resolvedDefaultMonospace
|
||||
<< ", substitutions:" << resolvedFont.substitutions().join(',');
|
||||
m_settings->registerSetting("ConsoleFont", resolvedDefaultMonospace);
|
||||
}
|
||||
else
|
||||
{
|
||||
ftbDefault = PathCombine(QString::fromWCharArray(buf), "ftblauncher");
|
||||
// in test mode, we don't have UI, so we don't do any font resolving
|
||||
m_settings->registerSetting("ConsoleFont", defaultMonospace);
|
||||
}
|
||||
#elif defined(Q_OS_MAC)
|
||||
QString ftbDefault =
|
||||
PathCombine(QDir::homePath(), "Library/Application Support/ftblauncher");
|
||||
#endif
|
||||
m_settings->registerSetting("FTBLauncherRoot", ftbDefault);
|
||||
m_settings->registerSetting("ConsoleFontSize", defaultSize);
|
||||
|
||||
m_settings->registerSetting("FTBRoot");
|
||||
if (m_settings->get("FTBRoot").isNull())
|
||||
{
|
||||
QString ftbRoot;
|
||||
QFile f(QDir(m_settings->get("FTBLauncherRoot").toString())
|
||||
.absoluteFilePath("ftblaunch.cfg"));
|
||||
QLOG_INFO() << "Attempting to read" << f.fileName();
|
||||
if (f.open(QFile::ReadOnly))
|
||||
{
|
||||
const QString data = QString::fromLatin1(f.readAll());
|
||||
QRegularExpression exp("installPath=(.*)");
|
||||
ftbRoot = QDir::cleanPath(exp.match(data).captured(1));
|
||||
#ifdef Q_OS_WIN32
|
||||
if (!ftbRoot.isEmpty())
|
||||
{
|
||||
if (ftbRoot.at(0).isLetter() && ftbRoot.size() > 1 && ftbRoot.at(1) == '/')
|
||||
{
|
||||
ftbRoot.remove(1, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (ftbRoot.isEmpty())
|
||||
{
|
||||
QLOG_INFO() << "Failed to get FTB root path";
|
||||
}
|
||||
else
|
||||
{
|
||||
QLOG_INFO() << "FTB is installed at" << ftbRoot;
|
||||
m_settings->set("FTBRoot", ftbRoot);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QLOG_WARN() << "Couldn't open" << f.fileName() << ":" << f.errorString();
|
||||
QLOG_WARN() << "This is perfectly normal if you don't have FTB installed";
|
||||
}
|
||||
}
|
||||
FTBPlugin::initialize(m_settings);
|
||||
|
||||
// Folders
|
||||
m_settings->registerSetting("InstanceDir", "instances");
|
||||
@@ -427,7 +453,7 @@ void MultiMC::initGlobalSettings()
|
||||
m_settings->registerSetting({"MinecraftWinHeight", "MCWindowHeight"}, 480);
|
||||
|
||||
// Proxy Settings
|
||||
m_settings->registerSetting("ProxyType", "Default");
|
||||
m_settings->registerSetting("ProxyType", "None");
|
||||
m_settings->registerSetting({"ProxyAddr", "ProxyHostName"}, "127.0.0.1");
|
||||
m_settings->registerSetting("ProxyPort", 8080);
|
||||
m_settings->registerSetting({"ProxyUser", "ProxyUsername"}, "");
|
||||
@@ -436,11 +462,14 @@ void MultiMC::initGlobalSettings()
|
||||
// Memory
|
||||
m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512);
|
||||
m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, 1024);
|
||||
m_settings->registerSetting("PermGen", 64);
|
||||
m_settings->registerSetting("PermGen", 128);
|
||||
|
||||
// Java Settings
|
||||
m_settings->registerSetting("JavaPath", "");
|
||||
m_settings->registerSetting("JavaTimestamp", 0);
|
||||
m_settings->registerSetting("JavaVersion", "");
|
||||
m_settings->registerSetting("LastHostname", "");
|
||||
m_settings->registerSetting("JavaDetectionHack", "");
|
||||
m_settings->registerSetting("JvmArgs", "");
|
||||
|
||||
// Custom Commands
|
||||
@@ -461,98 +490,8 @@ void MultiMC::initGlobalSettings()
|
||||
m_settings->registerSetting("ConsoleWindowGeometry", "");
|
||||
|
||||
m_settings->registerSetting("SettingsGeometry", "");
|
||||
}
|
||||
|
||||
void MultiMC::initHttpMetaCache()
|
||||
{
|
||||
m_metacache.reset(new HttpMetaCache("metacache"));
|
||||
m_metacache->addBase("asset_indexes", QDir("assets/indexes").absolutePath());
|
||||
m_metacache->addBase("asset_objects", QDir("assets/objects").absolutePath());
|
||||
m_metacache->addBase("versions", QDir("versions").absolutePath());
|
||||
m_metacache->addBase("libraries", QDir("libraries").absolutePath());
|
||||
m_metacache->addBase("minecraftforge", QDir("mods/minecraftforge").absolutePath());
|
||||
m_metacache->addBase("fmllibs", QDir("mods/minecraftforge/libs").absolutePath());
|
||||
m_metacache->addBase("liteloader", QDir("mods/liteloader").absolutePath());
|
||||
m_metacache->addBase("skins", QDir("accounts/skins").absolutePath());
|
||||
m_metacache->addBase("root", QDir(root()).absolutePath());
|
||||
m_metacache->Load();
|
||||
}
|
||||
|
||||
void MultiMC::updateProxySettings()
|
||||
{
|
||||
QString proxyTypeStr = settings()->get("ProxyType").toString();
|
||||
|
||||
// Get the proxy settings from the settings object.
|
||||
QString addr = settings()->get("ProxyAddr").toString();
|
||||
int port = settings()->get("ProxyPort").value<qint16>();
|
||||
QString user = settings()->get("ProxyUser").toString();
|
||||
QString pass = settings()->get("ProxyPass").toString();
|
||||
|
||||
// Set the application proxy settings.
|
||||
if (proxyTypeStr == "SOCKS5")
|
||||
{
|
||||
QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, addr, port, user, pass));
|
||||
}
|
||||
else if (proxyTypeStr == "HTTP")
|
||||
{
|
||||
QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, addr, port, user, pass));
|
||||
}
|
||||
else if (proxyTypeStr == "None")
|
||||
{
|
||||
// If we have no proxy set, set no proxy and return.
|
||||
QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::NoProxy));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we have "Default" selected, set Qt to use the system proxy settings.
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||
}
|
||||
|
||||
QLOG_INFO() << "Detecting proxy settings...";
|
||||
QNetworkProxy proxy = QNetworkProxy::applicationProxy();
|
||||
if (m_qnam.get()) m_qnam->setProxy(proxy);
|
||||
QString proxyDesc;
|
||||
if (proxy.type() == QNetworkProxy::NoProxy)
|
||||
{
|
||||
QLOG_INFO() << "Using no proxy is an option!";
|
||||
return;
|
||||
}
|
||||
switch (proxy.type())
|
||||
{
|
||||
case QNetworkProxy::DefaultProxy:
|
||||
proxyDesc = "Default proxy: ";
|
||||
break;
|
||||
case QNetworkProxy::Socks5Proxy:
|
||||
proxyDesc = "Socks5 proxy: ";
|
||||
break;
|
||||
case QNetworkProxy::HttpProxy:
|
||||
proxyDesc = "HTTP proxy: ";
|
||||
break;
|
||||
case QNetworkProxy::HttpCachingProxy:
|
||||
proxyDesc = "HTTP caching: ";
|
||||
break;
|
||||
case QNetworkProxy::FtpCachingProxy:
|
||||
proxyDesc = "FTP caching: ";
|
||||
break;
|
||||
default:
|
||||
proxyDesc = "DERP proxy: ";
|
||||
break;
|
||||
}
|
||||
proxyDesc += QString("%3@%1:%2 pass %4")
|
||||
.arg(proxy.hostName())
|
||||
.arg(proxy.port())
|
||||
.arg(proxy.user())
|
||||
.arg(proxy.password());
|
||||
QLOG_INFO() << proxyDesc;
|
||||
}
|
||||
|
||||
std::shared_ptr<IconList> MultiMC::icons()
|
||||
{
|
||||
if (!m_icons)
|
||||
{
|
||||
m_icons.reset(new IconList);
|
||||
}
|
||||
return m_icons;
|
||||
m_settings->registerSetting("PagedGeometry", "");
|
||||
}
|
||||
|
||||
std::shared_ptr<LWJGLVersionList> MultiMC::lwjgllist()
|
||||
@@ -560,6 +499,7 @@ std::shared_ptr<LWJGLVersionList> MultiMC::lwjgllist()
|
||||
if (!m_lwjgllist)
|
||||
{
|
||||
m_lwjgllist.reset(new LWJGLVersionList());
|
||||
ENV.registerVersionList("org.lwjgl.legacy", m_lwjgllist);
|
||||
}
|
||||
return m_lwjgllist;
|
||||
}
|
||||
@@ -569,6 +509,7 @@ std::shared_ptr<ForgeVersionList> MultiMC::forgelist()
|
||||
if (!m_forgelist)
|
||||
{
|
||||
m_forgelist.reset(new ForgeVersionList());
|
||||
ENV.registerVersionList("net.minecraftforge", m_forgelist);
|
||||
}
|
||||
return m_forgelist;
|
||||
}
|
||||
@@ -578,6 +519,7 @@ std::shared_ptr<LiteLoaderVersionList> MultiMC::liteloaderlist()
|
||||
if (!m_liteloaderlist)
|
||||
{
|
||||
m_liteloaderlist.reset(new LiteLoaderVersionList());
|
||||
ENV.registerVersionList("com.mumfrey.liteloader", m_liteloaderlist);
|
||||
}
|
||||
return m_liteloaderlist;
|
||||
}
|
||||
@@ -587,6 +529,7 @@ std::shared_ptr<MinecraftVersionList> MultiMC::minecraftlist()
|
||||
if (!m_minecraftlist)
|
||||
{
|
||||
m_minecraftlist.reset(new MinecraftVersionList());
|
||||
ENV.registerVersionList("net.minecraft", m_minecraftlist);
|
||||
}
|
||||
return m_minecraftlist;
|
||||
}
|
||||
@@ -596,6 +539,7 @@ std::shared_ptr<JavaVersionList> MultiMC::javalist()
|
||||
if (!m_javalist)
|
||||
{
|
||||
m_javalist.reset(new JavaVersionList());
|
||||
ENV.registerVersionList("com.java", m_javalist);
|
||||
}
|
||||
return m_javalist;
|
||||
}
|
||||
@@ -603,31 +547,31 @@ std::shared_ptr<JavaVersionList> MultiMC::javalist()
|
||||
void MultiMC::installUpdates(const QString updateFilesDir, UpdateFlags flags)
|
||||
{
|
||||
// if we are going to update on exit, save the params now
|
||||
if(flags & OnExit)
|
||||
if (flags & OnExit)
|
||||
{
|
||||
m_updateOnExitPath = updateFilesDir;
|
||||
m_updateOnExitFlags = flags & ~OnExit;
|
||||
return;
|
||||
}
|
||||
// otherwise if there already were some params for on exit update, clear them and continue
|
||||
else if(m_updateOnExitPath.size())
|
||||
else if (m_updateOnExitPath.size())
|
||||
{
|
||||
m_updateOnExitFlags = None;
|
||||
m_updateOnExitPath.clear();
|
||||
}
|
||||
QLOG_INFO() << "Installing updates.";
|
||||
#ifdef WINDOWS
|
||||
QString finishCmd = MMC->applicationFilePath();
|
||||
QString updaterBinary = PathCombine(bin(), "updater.exe");
|
||||
#elif LINUX
|
||||
QString finishCmd = PathCombine(root(), "MultiMC");
|
||||
QString updaterBinary = PathCombine(bin(), "updater");
|
||||
#elif OSX
|
||||
QString finishCmd = MMC->applicationFilePath();
|
||||
QString updaterBinary = PathCombine(bin(), "updater");
|
||||
#else
|
||||
#error Unsupported operating system.
|
||||
#endif
|
||||
qDebug() << "Installing updates.";
|
||||
#ifdef WINDOWS
|
||||
QString finishCmd = applicationFilePath();
|
||||
QString updaterBinary = PathCombine(applicationDirPath(), "updater.exe");
|
||||
#elif LINUX
|
||||
QString finishCmd = PathCombine(root(), "MultiMC");
|
||||
QString updaterBinary = PathCombine(applicationDirPath(), "updater");
|
||||
#elif OSX
|
||||
QString finishCmd = applicationFilePath();
|
||||
QString updaterBinary = PathCombine(applicationDirPath(), "updater");
|
||||
#else
|
||||
#error Unsupported operating system.
|
||||
#endif
|
||||
|
||||
QStringList args;
|
||||
// ./updater --install-dir $INSTALL_DIR --package-dir $UPDATEFILES_DIR --script
|
||||
@@ -635,33 +579,54 @@ void MultiMC::installUpdates(const QString updateFilesDir, UpdateFlags flags)
|
||||
args << "--install-dir" << root();
|
||||
args << "--package-dir" << updateFilesDir;
|
||||
args << "--script" << PathCombine(updateFilesDir, "file_list.xml");
|
||||
args << "--wait" << QString::number(MMC->applicationPid());
|
||||
if(flags & DryRun)
|
||||
args << "--wait" << QString::number(applicationPid());
|
||||
if (flags & DryRun)
|
||||
args << "--dry-run";
|
||||
if (flags & RestartOnFinish)
|
||||
{
|
||||
args << "--finish-cmd" << finishCmd;
|
||||
args << "--finish-dir" << data();
|
||||
args << "--finish-dir" << dataPath;
|
||||
}
|
||||
QLOG_INFO() << "Running updater with command" << updaterBinary << args.join(" ");
|
||||
qDebug() << "Running updater with command" << updaterBinary << args.join(" ");
|
||||
QFile::setPermissions(updaterBinary, (QFileDevice::Permission)0x7755);
|
||||
|
||||
if (!QProcess::startDetached(updaterBinary, args/*, root()*/))
|
||||
if (!QProcess::startDetached(updaterBinary, args /*, root()*/))
|
||||
{
|
||||
QLOG_ERROR() << "Failed to start the updater process!";
|
||||
qCritical() << "Failed to start the updater process!";
|
||||
return;
|
||||
}
|
||||
|
||||
ENV.destroy();
|
||||
// Now that we've started the updater, quit MultiMC.
|
||||
MMC->quit();
|
||||
quit();
|
||||
}
|
||||
|
||||
void MultiMC::setIconTheme(const QString& name)
|
||||
{
|
||||
XdgIcon::setThemeName(name);
|
||||
}
|
||||
|
||||
QIcon MultiMC::getThemedIcon(const QString& name)
|
||||
{
|
||||
return XdgIcon::fromTheme(name);
|
||||
}
|
||||
|
||||
void MultiMC::onExit()
|
||||
{
|
||||
if(m_updateOnExitPath.size())
|
||||
if(m_instances)
|
||||
{
|
||||
m_instances->saveGroupList();
|
||||
}
|
||||
if (m_updateOnExitPath.size())
|
||||
{
|
||||
installUpdates(m_updateOnExitPath, m_updateOnExitFlags);
|
||||
}
|
||||
ENV.destroy();
|
||||
if(logFile)
|
||||
{
|
||||
logFile->flush();
|
||||
logFile->close();
|
||||
}
|
||||
}
|
||||
|
||||
bool MultiMC::openJsonEditor(const QString &filename)
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
#include <QApplication>
|
||||
#include <memory>
|
||||
#include "logger/QsLog.h"
|
||||
#include "logger/QsLogDest.h"
|
||||
#include <QDebug>
|
||||
#include <QFlag>
|
||||
#include <QIcon>
|
||||
#include <QDateTime>
|
||||
|
||||
class QFile;
|
||||
class MinecraftVersionList;
|
||||
class LWJGLVersionList;
|
||||
class HttpMetaCache;
|
||||
@@ -18,26 +20,15 @@ class ForgeVersionList;
|
||||
class LiteLoaderVersionList;
|
||||
class JavaVersionList;
|
||||
class UpdateChecker;
|
||||
class NotificationChecker;
|
||||
class NewsChecker;
|
||||
class StatusChecker;
|
||||
class BaseProfilerFactory;
|
||||
class BaseDetachedToolFactory;
|
||||
class TranslationDownloader;
|
||||
|
||||
#if defined(MMC)
|
||||
#undef MMC
|
||||
#endif
|
||||
#define MMC (static_cast<MultiMC *>(QCoreApplication::instance()))
|
||||
|
||||
// FIXME: possibly move elsewhere
|
||||
enum InstSortMode
|
||||
{
|
||||
// Sort alphabetically by name.
|
||||
Sort_Name,
|
||||
// Sort by which instance was launched most recently.
|
||||
Sort_LastLaunch
|
||||
};
|
||||
|
||||
enum UpdateFlag
|
||||
{
|
||||
None = 0x0,
|
||||
@@ -50,6 +41,9 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(UpdateFlags);
|
||||
|
||||
class MultiMC : public QApplication
|
||||
{
|
||||
// friends for the purpose of limiting access to deprecated stuff
|
||||
friend class MultiMCPage;
|
||||
friend class MainWindow;
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Status
|
||||
@@ -60,115 +54,89 @@ public:
|
||||
};
|
||||
|
||||
public:
|
||||
MultiMC(int &argc, char **argv, bool root_override = false);
|
||||
MultiMC(int &argc, char **argv, bool test_mode = false);
|
||||
virtual ~MultiMC();
|
||||
|
||||
// InstanceList, IconList, OneSixFTBInstance, LegacyUpdate, LegacyInstance, MCEditTool, JVisualVM, MinecraftInstance, JProfiler, BaseInstance
|
||||
std::shared_ptr<SettingsObject> settings()
|
||||
{
|
||||
return m_settings;
|
||||
}
|
||||
|
||||
std::shared_ptr<InstanceList> instances()
|
||||
qint64 timeSinceStart() const
|
||||
{
|
||||
return m_instances;
|
||||
return startTime.msecsTo(QDateTime::currentDateTime());
|
||||
}
|
||||
|
||||
std::shared_ptr<MojangAccountList> accounts()
|
||||
{
|
||||
return m_accounts;
|
||||
}
|
||||
QIcon getThemedIcon(const QString& name);
|
||||
|
||||
std::shared_ptr<IconList> icons();
|
||||
|
||||
Status status()
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
std::shared_ptr<QNetworkAccessManager> qnam()
|
||||
{
|
||||
return m_qnam;
|
||||
}
|
||||
|
||||
std::shared_ptr<HttpMetaCache> metacache()
|
||||
{
|
||||
return m_metacache;
|
||||
}
|
||||
void setIconTheme(const QString& name);
|
||||
|
||||
// DownloadUpdateTask
|
||||
std::shared_ptr<UpdateChecker> updateChecker()
|
||||
{
|
||||
return m_updateChecker;
|
||||
}
|
||||
|
||||
std::shared_ptr<NotificationChecker> notificationChecker()
|
||||
{
|
||||
return m_notificationChecker;
|
||||
}
|
||||
|
||||
std::shared_ptr<NewsChecker> newsChecker()
|
||||
{
|
||||
return m_newsChecker;
|
||||
}
|
||||
|
||||
std::shared_ptr<StatusChecker> statusChecker()
|
||||
{
|
||||
return m_statusChecker;
|
||||
}
|
||||
|
||||
std::shared_ptr<LWJGLVersionList> lwjgllist();
|
||||
|
||||
std::shared_ptr<ForgeVersionList> forgelist();
|
||||
|
||||
std::shared_ptr<LiteLoaderVersionList> liteloaderlist();
|
||||
|
||||
std::shared_ptr<MinecraftVersionList> minecraftlist();
|
||||
|
||||
std::shared_ptr<LWJGLVersionList> lwjgllist();
|
||||
std::shared_ptr<ForgeVersionList> forgelist();
|
||||
std::shared_ptr<LiteLoaderVersionList> liteloaderlist();
|
||||
std::shared_ptr<JavaVersionList> javalist();
|
||||
|
||||
// APPLICATION ONLY
|
||||
std::shared_ptr<InstanceList> instances()
|
||||
{
|
||||
return m_instances;
|
||||
}
|
||||
|
||||
// APPLICATION ONLY
|
||||
std::shared_ptr<MojangAccountList> accounts()
|
||||
{
|
||||
return m_accounts;
|
||||
}
|
||||
|
||||
// APPLICATION ONLY
|
||||
Status status()
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
// APPLICATION ONLY
|
||||
QMap<QString, std::shared_ptr<BaseProfilerFactory>> profilers()
|
||||
{
|
||||
return m_profilers;
|
||||
}
|
||||
|
||||
// APPLICATION ONLY
|
||||
QMap<QString, std::shared_ptr<BaseDetachedToolFactory>> tools()
|
||||
{
|
||||
return m_tools;
|
||||
}
|
||||
|
||||
// APPLICATION ONLY
|
||||
void installUpdates(const QString updateFilesDir, UpdateFlags flags = None);
|
||||
|
||||
/*!
|
||||
* Updates the application proxy settings from the settings object.
|
||||
*/
|
||||
void updateProxySettings();
|
||||
|
||||
/*!
|
||||
* Opens a json file using either a system default editor, or, if note empty, the editor
|
||||
* specified in the settings
|
||||
*/
|
||||
bool openJsonEditor(const QString &filename);
|
||||
|
||||
protected: /* to be removed! */
|
||||
// FIXME: remove. used by MultiMCPage to enumerate translations.
|
||||
/// this is the static data. it stores things that don't move.
|
||||
const QString &staticData()
|
||||
{
|
||||
return staticDataPath;
|
||||
}
|
||||
|
||||
// FIXME: remove. used by MainWindow to create application update tasks
|
||||
/// this is the root of the 'installation'. Used for automatic updates
|
||||
const QString &root()
|
||||
{
|
||||
return rootPath;
|
||||
}
|
||||
/// this is the where the binary files reside
|
||||
const QString &bin()
|
||||
{
|
||||
return binPath;
|
||||
}
|
||||
/// this is the work/data path. All user data is here.
|
||||
const QString &data()
|
||||
{
|
||||
return dataPath;
|
||||
}
|
||||
/**
|
||||
* this is the original work path before it was changed by the adjustment mechanism
|
||||
*/
|
||||
const QString &origcwd()
|
||||
{
|
||||
return origcwdPath;
|
||||
}
|
||||
|
||||
private slots:
|
||||
/**
|
||||
@@ -179,45 +147,43 @@ private slots:
|
||||
private:
|
||||
void initLogger();
|
||||
|
||||
void initGlobalSettings();
|
||||
void initIcons();
|
||||
|
||||
void initHttpMetaCache();
|
||||
void initGlobalSettings(bool test_mode);
|
||||
|
||||
void initTranslations();
|
||||
void initSSL();
|
||||
|
||||
private:
|
||||
friend class UpdateCheckerTest;
|
||||
friend class DownloadUpdateTaskTest;
|
||||
friend class DownloadTaskTest;
|
||||
|
||||
QDateTime startTime;
|
||||
|
||||
std::shared_ptr<QTranslator> m_qt_translator;
|
||||
std::shared_ptr<QTranslator> m_mmc_translator;
|
||||
std::shared_ptr<SettingsObject> m_settings;
|
||||
std::shared_ptr<InstanceList> m_instances;
|
||||
std::shared_ptr<UpdateChecker> m_updateChecker;
|
||||
std::shared_ptr<NotificationChecker> m_notificationChecker;
|
||||
std::shared_ptr<NewsChecker> m_newsChecker;
|
||||
std::shared_ptr<StatusChecker> m_statusChecker;
|
||||
std::shared_ptr<MojangAccountList> m_accounts;
|
||||
std::shared_ptr<IconList> m_icons;
|
||||
std::shared_ptr<QNetworkAccessManager> m_qnam;
|
||||
std::shared_ptr<HttpMetaCache> m_metacache;
|
||||
std::shared_ptr<LWJGLVersionList> m_lwjgllist;
|
||||
std::shared_ptr<ForgeVersionList> m_forgelist;
|
||||
std::shared_ptr<LiteLoaderVersionList> m_liteloaderlist;
|
||||
std::shared_ptr<MinecraftVersionList> m_minecraftlist;
|
||||
std::shared_ptr<JavaVersionList> m_javalist;
|
||||
std::shared_ptr<TranslationDownloader> m_translationChecker;
|
||||
|
||||
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;
|
||||
QMap<QString, std::shared_ptr<BaseDetachedToolFactory>> m_tools;
|
||||
QsLogging::DestinationPtr m_fileDestination;
|
||||
QsLogging::DestinationPtr m_debugDestination;
|
||||
|
||||
QString m_updateOnExitPath;
|
||||
UpdateFlags m_updateOnExitFlags = None;
|
||||
|
||||
QString rootPath;
|
||||
QString binPath;
|
||||
QString staticDataPath;
|
||||
QString dataPath;
|
||||
QString origcwdPath;
|
||||
|
||||
Status m_status = MultiMC::Failed;
|
||||
public:
|
||||
std::shared_ptr<QFile> logFile;
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||
*
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||
*
|
||||
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <gui/Platform.h>
|
||||
#include <Platform.h>
|
||||
/**
|
||||
* Stub for non-X11 platforms
|
||||
* @brief MultiMCPlatform::fixWM_CLASS
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||
*
|
||||
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <gui/Platform.h>
|
||||
#include <Platform.h>
|
||||
#include <QtX11Extras/QX11Info>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
412
application/VersionProxyModel.cpp
Normal file
412
application/VersionProxyModel.cpp
Normal file
@@ -0,0 +1,412 @@
|
||||
#include "VersionProxyModel.h"
|
||||
#include "MultiMC.h"
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QPixmapCache>
|
||||
#include <modutils.h>
|
||||
|
||||
class VersionFilterModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VersionFilterModel(VersionProxyModel *parent) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
m_parent = parent;
|
||||
}
|
||||
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
const auto &filters = m_parent->filters();
|
||||
for (auto it = filters.begin(); it != filters.end(); ++it)
|
||||
{
|
||||
auto role = it.key();
|
||||
auto idx = sourceModel()->index(source_row, 0, source_parent);
|
||||
auto data = sourceModel()->data(idx, role);
|
||||
|
||||
switch(role)
|
||||
{
|
||||
case BaseVersionList::ParentGameVersionRole:
|
||||
case BaseVersionList::VersionIdRole:
|
||||
{
|
||||
auto versionString = data.toString();
|
||||
if(it.value().exact)
|
||||
{
|
||||
if (versionString != it.value().string)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!Util::versionIsInInterval(versionString, it.value().string))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
auto match = data.toString();
|
||||
if(it.value().exact)
|
||||
{
|
||||
if (match != it.value().string)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (match.contains(it.value().string))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
VersionProxyModel *m_parent;
|
||||
};
|
||||
|
||||
VersionProxyModel::VersionProxyModel(QObject *parent) : QAbstractProxyModel(parent)
|
||||
{
|
||||
filterModel = new VersionFilterModel(this);
|
||||
connect(filterModel, &QAbstractItemModel::dataChanged, this, &VersionProxyModel::sourceDataChanged);
|
||||
// FIXME: implement when needed
|
||||
/*
|
||||
connect(replacing, &QAbstractItemModel::rowsAboutToBeInserted, this, &VersionProxyModel::sourceRowsAboutToBeInserted);
|
||||
connect(replacing, &QAbstractItemModel::rowsInserted, this, &VersionProxyModel::sourceRowsInserted);
|
||||
connect(replacing, &QAbstractItemModel::rowsAboutToBeRemoved, this, &VersionProxyModel::sourceRowsAboutToBeRemoved);
|
||||
connect(replacing, &QAbstractItemModel::rowsRemoved, this, &VersionProxyModel::sourceRowsRemoved);
|
||||
connect(replacing, &QAbstractItemModel::rowsAboutToBeMoved, this, &VersionProxyModel::sourceRowsAboutToBeMoved);
|
||||
connect(replacing, &QAbstractItemModel::rowsMoved, this, &VersionProxyModel::sourceRowsMoved);
|
||||
connect(replacing, &QAbstractItemModel::layoutAboutToBeChanged, this, &VersionProxyModel::sourceLayoutAboutToBeChanged);
|
||||
connect(replacing, &QAbstractItemModel::layoutChanged, this, &VersionProxyModel::sourceLayoutChanged);
|
||||
*/
|
||||
connect(filterModel, &QAbstractItemModel::modelAboutToBeReset, this, &VersionProxyModel::sourceAboutToBeReset);
|
||||
connect(filterModel, &QAbstractItemModel::modelReset, this, &VersionProxyModel::sourceReset);
|
||||
|
||||
QAbstractProxyModel::setSourceModel(filterModel);
|
||||
}
|
||||
|
||||
QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if(section < 0 || section >= m_columns.size())
|
||||
return QVariant();
|
||||
if(orientation != Qt::Horizontal)
|
||||
return QVariant();
|
||||
auto column = m_columns[section];
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
return tr("Version");
|
||||
case ParentVersion:
|
||||
return tr("Minecraft"); //FIXME: this should come from metadata
|
||||
case Branch:
|
||||
return tr("Branch");
|
||||
case Type:
|
||||
return tr("Type");
|
||||
case Architecture:
|
||||
return tr("Architecture");
|
||||
case Path:
|
||||
return tr("Path");
|
||||
}
|
||||
}
|
||||
else if(role == Qt::ToolTipRole)
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
return tr("The name of the version.");
|
||||
case ParentVersion:
|
||||
return tr("Minecraft version"); //FIXME: this should come from metadata
|
||||
case Branch:
|
||||
return tr("The version's branch");
|
||||
case Type:
|
||||
return tr("The version's type");
|
||||
case Architecture:
|
||||
return tr("CPU Architecture");
|
||||
case Path:
|
||||
return tr("Filesystem path to this version");
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant VersionProxyModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
auto column = m_columns[index.column()];
|
||||
auto parentIndex = mapToSource(index);
|
||||
switch(role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::VersionRole);
|
||||
case ParentVersion:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::ParentGameVersionRole);
|
||||
case Branch:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::BranchRole);
|
||||
case Type:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::TypeRole);
|
||||
case Architecture:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::ArchitectureRole);
|
||||
case Path:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::PathRole);
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case Qt::ToolTipRole:
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
{
|
||||
if(hasRecommended)
|
||||
{
|
||||
auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole);
|
||||
if(value.toBool())
|
||||
{
|
||||
return tr("Recommended");
|
||||
}
|
||||
else if(hasLatest)
|
||||
{
|
||||
auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole);
|
||||
if(value.toBool())
|
||||
{
|
||||
return tr("Latest");
|
||||
}
|
||||
}
|
||||
else if(index.row() == 0)
|
||||
{
|
||||
return tr("Latest");
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
case Qt::DecorationRole:
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
{
|
||||
if(hasRecommended)
|
||||
{
|
||||
auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole);
|
||||
if(value.toBool())
|
||||
{
|
||||
return MMC->getThemedIcon("star");
|
||||
}
|
||||
else if(hasLatest)
|
||||
{
|
||||
auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole);
|
||||
if(value.toBool())
|
||||
{
|
||||
return MMC->getThemedIcon("bug");
|
||||
}
|
||||
}
|
||||
else if(index.row() == 0)
|
||||
{
|
||||
return MMC->getThemedIcon("bug");
|
||||
}
|
||||
auto pixmap = QPixmapCache::find("placeholder");
|
||||
if(!pixmap)
|
||||
{
|
||||
QPixmap px(16,16);
|
||||
px.fill(Qt::transparent);
|
||||
QPixmapCache::insert("placeholder", px);
|
||||
return px;
|
||||
}
|
||||
return *pixmap;
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
if(roles.contains((BaseVersionList::ModelRoles)role))
|
||||
{
|
||||
return sourceModel()->data(parentIndex, role);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
QModelIndex VersionProxyModel::parent(const QModelIndex &child) const
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex VersionProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
|
||||
{
|
||||
if(sourceIndex.isValid())
|
||||
{
|
||||
return index(sourceIndex.row(), 0);
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex VersionProxyModel::mapToSource(const QModelIndex &proxyIndex) const
|
||||
{
|
||||
if(proxyIndex.isValid())
|
||||
{
|
||||
return sourceModel()->index(proxyIndex.row(), 0);
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex VersionProxyModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
// no trees here... shoo
|
||||
if(parent.isValid())
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
if(row < 0 || row >= sourceModel()->rowCount())
|
||||
return QModelIndex();
|
||||
if(column < 0 || column >= columnCount())
|
||||
return QModelIndex();
|
||||
return QAbstractItemModel::createIndex(row, column);
|
||||
}
|
||||
|
||||
int VersionProxyModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return m_columns.size();
|
||||
}
|
||||
|
||||
int VersionProxyModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if(sourceModel())
|
||||
{
|
||||
return sourceModel()->rowCount();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VersionProxyModel::sourceDataChanged(const QModelIndex &source_top_left,
|
||||
const QModelIndex &source_bottom_right)
|
||||
{
|
||||
if(source_top_left.parent() != source_bottom_right.parent())
|
||||
return;
|
||||
|
||||
// whole row is getting changed
|
||||
auto topLeft = createIndex(source_top_left.row(), 0);
|
||||
auto bottomRight = createIndex(source_bottom_right.row(), columnCount() - 1);
|
||||
emit dataChanged(topLeft, bottomRight);
|
||||
}
|
||||
|
||||
void VersionProxyModel::setSourceModel(BaseVersionList *replacing)
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
if(!replacing)
|
||||
{
|
||||
m_columns.clear();
|
||||
roles.clear();
|
||||
filterModel->setSourceModel(replacing);
|
||||
return;
|
||||
}
|
||||
|
||||
roles = replacing->providesRoles();
|
||||
if(roles.contains(BaseVersionList::VersionRole))
|
||||
{
|
||||
m_columns.push_back(Name);
|
||||
}
|
||||
/*
|
||||
if(roles.contains(BaseVersionList::ParentGameVersionRole))
|
||||
{
|
||||
m_columns.push_back(ParentVersion);
|
||||
}
|
||||
*/
|
||||
if(roles.contains(BaseVersionList::ArchitectureRole))
|
||||
{
|
||||
m_columns.push_back(Architecture);
|
||||
}
|
||||
if(roles.contains(BaseVersionList::PathRole))
|
||||
{
|
||||
m_columns.push_back(Path);
|
||||
}
|
||||
if(roles.contains(BaseVersionList::BranchRole))
|
||||
{
|
||||
m_columns.push_back(Branch);
|
||||
}
|
||||
if(roles.contains(BaseVersionList::TypeRole))
|
||||
{
|
||||
m_columns.push_back(Type);
|
||||
}
|
||||
if(roles.contains(BaseVersionList::RecommendedRole))
|
||||
{
|
||||
hasRecommended = true;
|
||||
}
|
||||
if(roles.contains(BaseVersionList::LatestRole))
|
||||
{
|
||||
hasLatest = true;
|
||||
}
|
||||
filterModel->setSourceModel(replacing);
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QModelIndex VersionProxyModel::getRecommended() const
|
||||
{
|
||||
if(!roles.contains(BaseVersionList::RecommendedRole))
|
||||
{
|
||||
return index(0, 0);
|
||||
}
|
||||
int recommended = 0;
|
||||
for (int i = 0; i < rowCount(); i++)
|
||||
{
|
||||
auto value = sourceModel()->data(mapToSource(index(i, 0)), BaseVersionList::RecommendedRole);
|
||||
if (value.toBool())
|
||||
{
|
||||
recommended = i;
|
||||
}
|
||||
}
|
||||
return index(recommended, 0);
|
||||
}
|
||||
|
||||
void VersionProxyModel::clearFilters()
|
||||
{
|
||||
m_filters.clear();
|
||||
filterModel->invalidate();
|
||||
}
|
||||
|
||||
void VersionProxyModel::setFilter(const BaseVersionList::ModelRoles column, const QString &filter, const bool exact)
|
||||
{
|
||||
Filter f;
|
||||
f.string = filter;
|
||||
f.exact = exact;
|
||||
m_filters[column] = f;
|
||||
filterModel->invalidate();
|
||||
}
|
||||
|
||||
const VersionProxyModel::FilterMap &VersionProxyModel::filters() const
|
||||
{
|
||||
return m_filters;
|
||||
}
|
||||
|
||||
void VersionProxyModel::sourceAboutToBeReset()
|
||||
{
|
||||
beginResetModel();
|
||||
}
|
||||
|
||||
void VersionProxyModel::sourceReset()
|
||||
{
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
#include "VersionProxyModel.moc"
|
||||
58
application/VersionProxyModel.h
Normal file
58
application/VersionProxyModel.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
#include <QAbstractProxyModel>
|
||||
#include "BaseVersionList.h"
|
||||
|
||||
class VersionFilterModel;
|
||||
|
||||
class VersionProxyModel: public QAbstractProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
struct Filter
|
||||
{
|
||||
QString string;
|
||||
bool exact = false;
|
||||
};
|
||||
enum Column
|
||||
{
|
||||
Name,
|
||||
ParentVersion,
|
||||
Branch,
|
||||
Type,
|
||||
Architecture,
|
||||
Path
|
||||
};
|
||||
typedef QHash<BaseVersionList::ModelRoles, Filter> FilterMap;
|
||||
|
||||
public:
|
||||
VersionProxyModel ( QObject* parent = 0 );
|
||||
virtual ~VersionProxyModel() {};
|
||||
|
||||
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
|
||||
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
|
||||
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
virtual QModelIndex parent(const QModelIndex &child) const override;
|
||||
void setSourceModel(BaseVersionList *sourceModel);
|
||||
|
||||
const FilterMap &filters() const;
|
||||
void setFilter(const BaseVersionList::ModelRoles column, const QString &filter, const bool exact);
|
||||
void clearFilters();
|
||||
QModelIndex getRecommended() const;
|
||||
private slots:
|
||||
|
||||
void sourceDataChanged(const QModelIndex &source_top_left,const QModelIndex &source_bottom_right);
|
||||
void sourceAboutToBeReset();
|
||||
void sourceReset();
|
||||
|
||||
private:
|
||||
QList<Column> m_columns;
|
||||
FilterMap m_filters;
|
||||
BaseVersionList::RoleList roles;
|
||||
VersionFilterModel * filterModel;
|
||||
bool hasRecommended = false;
|
||||
bool hasLatest = false;
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,16 +17,16 @@
|
||||
#include "ui_AboutDialog.h"
|
||||
#include <QIcon>
|
||||
#include "MultiMC.h"
|
||||
#include "gui/Platform.h"
|
||||
#include "Platform.h"
|
||||
#include "BuildConfig.h"
|
||||
|
||||
#include <logic/net/NetJob.h>
|
||||
#include <net/NetJob.h>
|
||||
|
||||
// Credits
|
||||
// This is a hack, but I can't think of a better way to do this easily without screwing with QTextDocument...
|
||||
QString getCreditsHtml(QStringList patrons)
|
||||
{
|
||||
QString creditsHtml =
|
||||
QString creditsHtml = QObject::tr(
|
||||
"<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0//EN' 'http://www.w3.org/TR/REC-html40/strict.dtd'>"
|
||||
"<html>"
|
||||
""
|
||||
@@ -42,7 +42,7 @@ QString getCreditsHtml(QStringList patrons)
|
||||
"<h3>MultiMC Developers</h3>"
|
||||
"<p>Andrew Okin <<a href='mailto:forkk@forkk.net'>forkk@forkk.net</a>></p>"
|
||||
"<p>Petr Mrázek <<a href='mailto:peterix@gmail.com'>peterix@gmail.com</a>></p>"
|
||||
"<p>Sky <<a href='https://www.twitter.com/drayshak'>@drayshak</a>></p>"
|
||||
"<p>Sky Welch <<a href='mailto:multimc@bunnies.io'>multimc@bunnies.io</a>></p>"
|
||||
"<p>Jan (02JanDal) <<a href='mailto:02jandal@gmail.com'>02jandal@gmail.com</a>></p>"
|
||||
""
|
||||
"<h3>With thanks to</h3>"
|
||||
@@ -56,9 +56,9 @@ QString getCreditsHtml(QStringList patrons)
|
||||
"%1"
|
||||
""
|
||||
"</body>"
|
||||
"</html>";
|
||||
"</html>");
|
||||
if (patrons.isEmpty())
|
||||
return creditsHtml.arg("<p>Loading...</p>");
|
||||
return creditsHtml.arg(QObject::tr("<p>Loading...</p>"));
|
||||
else
|
||||
{
|
||||
QString patronsStr;
|
||||
@@ -81,11 +81,10 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia
|
||||
|
||||
ui->urlLabel->setOpenExternalLinks(true);
|
||||
|
||||
ui->icon->setPixmap(QIcon(":/icons/multimc/scalable/apps/multimc.svg").pixmap(64));
|
||||
ui->title->setText("MultiMC 5 " + BuildConfig.printableVersionString());
|
||||
ui->icon->setPixmap(MMC->getThemedIcon("multimc").pixmap(64));
|
||||
ui->title->setText("MultiMC 5");
|
||||
|
||||
ui->versionLabel->setText(tr("Version") +": " + BuildConfig.printableVersionString());
|
||||
ui->vtypeLabel->setText(tr("Version Type") +": " + BuildConfig.versionTypeName());
|
||||
ui->platformLabel->setText(tr("Platform") +": " + BuildConfig.BUILD_PLATFORM);
|
||||
|
||||
if (BuildConfig.VERSION_BUILD >= 0)
|
||||
@@ -100,7 +99,7 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia
|
||||
|
||||
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
|
||||
|
||||
MMC->connect(ui->aboutQt, SIGNAL(clicked()), SLOT(aboutQt()));
|
||||
connect(ui->aboutQt, &QPushButton::clicked, &QApplication::aboutQt);
|
||||
|
||||
loadPatronList();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include <logic/net/ByteArrayDownload.h>
|
||||
#include <net/ByteArrayDownload.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@@ -58,9 +58,6 @@
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../../resources/multimc/multimc.qrc">:/icons/multimc/scalable/apps/multimc.svg</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -96,15 +93,15 @@
|
||||
<item>
|
||||
<widget class="QToolBox" name="toolBox">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="aboutPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>689</width>
|
||||
<height>331</height>
|
||||
<width>695</width>
|
||||
<height>297</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@@ -121,16 +118,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="vtypeLabel">
|
||||
<property name="text">
|
||||
<string>Version Type:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="platformLabel">
|
||||
<property name="text">
|
||||
@@ -186,7 +173,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>© 2013 MultiMC Contributors</string>
|
||||
<string>© 2013-2015 MultiMC Contributors</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
@@ -228,8 +215,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>689</width>
|
||||
<height>331</height>
|
||||
<width>695</width>
|
||||
<height>297</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@@ -245,11 +232,11 @@
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||
</style></head><body style=" font-family:'Oxygen-Sans'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html></string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -270,8 +257,8 @@ p, li { white-space: pre-wrap; }
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>689</width>
|
||||
<height>331</height>
|
||||
<width>695</width>
|
||||
<height>297</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@@ -298,7 +285,7 @@ p, li { white-space: pre-wrap; }
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'DejaVu Sans Mono'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
</style></head><body style=" font-family:'DejaVu Sans Mono'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">MultiMC</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Copyright 2012-2014 MultiMC Contributors</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></p>
|
||||
@@ -359,7 +346,24 @@ p, li { white-space: pre-wrap; }
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Boston, MA 02110-1301, USA.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> */</span></p>
|
||||
<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">Batch icon set</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You are free to use Batch (the &quot;icon set&quot;) or any part thereof (the &quot;icons&quot;)</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">in any personal, open-source or commercial work without obligation of payment</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">(monetary or otherwise) or attribution. Do not sell the icon set, host</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">the icon set or rent the icon set (either in existing or modified form).</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">While attribution is optional, it is always appreciated.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Intellectual property rights are not transferred with the download of the icons.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL ADAM WHITCROFT</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THE USE OF THE ICONS,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://adamwhitcroft.com/batch/"><span style=" text-decoration: underline; color:#68a0df;">http://adamwhitcroft.com/batch/</span></a></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">Pack200</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The GNU General Public License (GPL)</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
@@ -422,7 +426,7 @@ p, li { white-space: pre-wrap; }
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> */</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">Java IconLoader class</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><br /></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Copyright (c) 2011, Chris Molini</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">All rights reserved.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
@@ -447,8 +451,16 @@ p, li { white-space: pre-wrap; }
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span></p>
|
||||
<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">ColumnResizer</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html></string>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">/*</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Copyright 2011 Aurélien Gâteau &lt;agateau@kde.org&gt;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * License: LGPL v2.1 or later (see COPYING)</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> */</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -459,8 +471,8 @@ p, li { white-space: pre-wrap; }
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>689</width>
|
||||
<height>331</height>
|
||||
<width>695</width>
|
||||
<height>297</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@@ -473,12 +485,12 @@ p, li { white-space: pre-wrap; }
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;">We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans'; font-size:11pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;">Part of the reason for using the Apache license is we don't want people using the &quot;MultiMC&quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &quot;MultiMC&quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans'; font-size:11pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;">The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork </span><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:600;">without</span><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;"> implying that you have our blessing.</span></p></body></html></string>
|
||||
</style></head><body style=" font-family:'Oxygen-Sans'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans';">We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans';"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans';">Part of the reason for using the Apache license is we don't want people using the &quot;MultiMC&quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &quot;MultiMC&quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans';"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans';">The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork </span><span style=" font-family:'Bitstream Vera Sans'; font-weight:600;">without</span><span style=" font-family:'Bitstream Vera Sans';"> implying that you have our blessing.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,9 +18,9 @@
|
||||
|
||||
#include <QItemSelectionModel>
|
||||
|
||||
#include <logger/QsLog.h>
|
||||
#include <QDebug>
|
||||
|
||||
#include <gui/dialogs/ProgressDialog.h>
|
||||
#include <dialogs/ProgressDialog.h>
|
||||
|
||||
#include <MultiMC.h>
|
||||
|
||||
@@ -40,10 +40,12 @@ AccountSelectDialog::AccountSelectDialog(const QString &message, int flags, QWid
|
||||
// Flags...
|
||||
ui->globalDefaultCheck->setVisible(flags & GlobalDefaultCheckbox);
|
||||
ui->instDefaultCheck->setVisible(flags & InstanceDefaultCheckbox);
|
||||
QLOG_DEBUG() << flags;
|
||||
qDebug() << flags;
|
||||
|
||||
// Select the first entry in the list.
|
||||
ui->listView->setCurrentIndex(ui->listView->model()->index(0, 0));
|
||||
|
||||
connect(ui->listView, SIGNAL(doubleClicked(QModelIndex)), SLOT(on_buttonBox_accepted()));
|
||||
}
|
||||
|
||||
AccountSelectDialog::~AccountSelectDialog()
|
||||
@@ -72,8 +74,7 @@ void AccountSelectDialog::on_buttonBox_accepted()
|
||||
if (selection.size() > 0)
|
||||
{
|
||||
QModelIndex selected = selection.first();
|
||||
MojangAccountPtr account = selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>();
|
||||
m_selected = account;
|
||||
m_selected = selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>();
|
||||
}
|
||||
close();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "logic/auth/MojangAccountList.h"
|
||||
#include "auth/MojangAccountList.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,17 +20,14 @@
|
||||
#include "CopyInstanceDialog.h"
|
||||
#include "ui_CopyInstanceDialog.h"
|
||||
|
||||
#include "gui/Platform.h"
|
||||
#include "gui/dialogs/VersionSelectDialog.h"
|
||||
#include "gui/dialogs/ProgressDialog.h"
|
||||
#include "gui/dialogs/IconPickerDialog.h"
|
||||
#include "Platform.h"
|
||||
#include "dialogs/IconPickerDialog.h"
|
||||
|
||||
#include "logic/InstanceFactory.h"
|
||||
#include "logic/BaseVersion.h"
|
||||
#include "logic/icons/IconList.h"
|
||||
#include "logic/lists/MinecraftVersionList.h"
|
||||
#include "logic/tasks/Task.h"
|
||||
#include "logic/BaseInstance.h"
|
||||
#include "BaseVersion.h"
|
||||
#include "icons/IconList.h"
|
||||
#include "tasks/Task.h"
|
||||
#include "BaseInstance.h"
|
||||
#include "InstanceList.h"
|
||||
|
||||
CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget *parent)
|
||||
:QDialog(parent), ui(new Ui::CopyInstanceDialog), m_original(original)
|
||||
@@ -41,9 +38,22 @@ CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget *parent)
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
||||
InstIconKey = original->iconKey();
|
||||
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
||||
ui->iconButton->setIcon(ENV.icons()->getIcon(InstIconKey));
|
||||
ui->instNameTextBox->setText(original->name());
|
||||
ui->instNameTextBox->setFocus();
|
||||
auto groups = MMC->instances()->getGroups().toSet();
|
||||
auto groupList = QStringList(groups.toList());
|
||||
groupList.sort(Qt::CaseInsensitive);
|
||||
groupList.removeOne("");
|
||||
groupList.push_front("");
|
||||
ui->groupBox->addItems(groupList);
|
||||
int index = groupList.indexOf(m_original->group());
|
||||
if(index == -1)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
ui->groupBox->setCurrentIndex(index);
|
||||
ui->groupBox->lineEdit()->setPlaceholderText(tr("No group"));
|
||||
}
|
||||
|
||||
CopyInstanceDialog::~CopyInstanceDialog()
|
||||
@@ -66,6 +76,11 @@ QString CopyInstanceDialog::iconKey() const
|
||||
return InstIconKey;
|
||||
}
|
||||
|
||||
QString CopyInstanceDialog::instGroup() const
|
||||
{
|
||||
return ui->groupBox->currentText();
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::on_iconButton_clicked()
|
||||
{
|
||||
IconPickerDialog dlg(this);
|
||||
@@ -74,7 +89,7 @@ void CopyInstanceDialog::on_iconButton_clicked()
|
||||
if (dlg.result() == QDialog::Accepted)
|
||||
{
|
||||
InstIconKey = dlg.selectedIconKey;
|
||||
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
||||
ui->iconButton->setIcon(ENV.icons()->getIcon(InstIconKey));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,8 +16,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include "logic/BaseVersion.h"
|
||||
#include <logic/BaseInstance.h>
|
||||
#include "BaseVersion.h"
|
||||
#include <BaseInstance.h>
|
||||
|
||||
class BaseInstance;
|
||||
|
||||
@@ -37,6 +37,7 @@ public:
|
||||
void updateDialogState();
|
||||
|
||||
QString instName() const;
|
||||
QString instGroup() const;
|
||||
QString iconKey() const;
|
||||
|
||||
private
|
||||
@@ -17,7 +17,7 @@
|
||||
<string>Copy Instance</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../graphics.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/icons/toolbar/copy</normaloff>:/icons/toolbar/copy</iconset>
|
||||
</property>
|
||||
<property name="modal">
|
||||
@@ -42,7 +42,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="iconButton">
|
||||
<property name="icon">
|
||||
<iconset resource="../../graphics.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/icons/instances/infinity</normaloff>:/icons/instances/infinity</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
@@ -82,6 +82,33 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelVersion_3">
|
||||
<property name="text">
|
||||
<string>Group</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>groupBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="groupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
434
application/dialogs/ExportInstanceDialog.cpp
Normal file
434
application/dialogs/ExportInstanceDialog.cpp
Normal file
@@ -0,0 +1,434 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ExportInstanceDialog.h"
|
||||
#include "ui_ExportInstanceDialog.h"
|
||||
#include <BaseInstance.h>
|
||||
#include <MMCZip.h>
|
||||
#include <pathutils.h>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <qfilesystemmodel.h>
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QDebug>
|
||||
#include <qstack.h>
|
||||
#include <QSaveFile>
|
||||
#include "MMCStrings.h"
|
||||
#include "SeparatorPrefixTree.h"
|
||||
|
||||
class PackIgnoreProxy : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PackIgnoreProxy(InstancePtr instance, QObject *parent) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
m_instance = instance;
|
||||
}
|
||||
// NOTE: Sadly, we have to do sorting ourselves.
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
QFileSystemModel *fsm = qobject_cast<QFileSystemModel *>(sourceModel());
|
||||
if (!fsm)
|
||||
{
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
}
|
||||
bool asc = sortOrder() == Qt::AscendingOrder ? true : false;
|
||||
|
||||
QFileInfo leftFileInfo = fsm->fileInfo(left);
|
||||
QFileInfo rightFileInfo = fsm->fileInfo(right);
|
||||
|
||||
if (!leftFileInfo.isDir() && rightFileInfo.isDir())
|
||||
{
|
||||
return !asc;
|
||||
}
|
||||
if (leftFileInfo.isDir() && !rightFileInfo.isDir())
|
||||
{
|
||||
return asc;
|
||||
}
|
||||
|
||||
// sort and proxy model breaks the original model...
|
||||
if (sortColumn() == 0)
|
||||
{
|
||||
return Strings::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(),
|
||||
Qt::CaseInsensitive) < 0;
|
||||
}
|
||||
if (sortColumn() == 1)
|
||||
{
|
||||
auto leftSize = leftFileInfo.size();
|
||||
auto rightSize = rightFileInfo.size();
|
||||
if ((leftSize == rightSize) || (leftFileInfo.isDir() && rightFileInfo.isDir()))
|
||||
{
|
||||
return Strings::naturalCompare(leftFileInfo.fileName(),
|
||||
rightFileInfo.fileName(),
|
||||
Qt::CaseInsensitive) < 0
|
||||
? asc
|
||||
: !asc;
|
||||
}
|
||||
return leftSize < rightSize;
|
||||
}
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
}
|
||||
|
||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return Qt::NoItemFlags;
|
||||
|
||||
auto sourceIndex = mapToSource(index);
|
||||
Qt::ItemFlags flags = sourceIndex.flags();
|
||||
if (index.column() == 0)
|
||||
{
|
||||
flags |= Qt::ItemIsUserCheckable;
|
||||
if (sourceIndex.model()->hasChildren(sourceIndex))
|
||||
{
|
||||
flags |= Qt::ItemIsTristate;
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
|
||||
{
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
|
||||
if (index.column() == 0 && role == Qt::CheckStateRole)
|
||||
{
|
||||
QFileSystemModel *fsm = qobject_cast<QFileSystemModel *>(sourceModel());
|
||||
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||
auto cover = blocked.cover(blockedPath);
|
||||
if (!cover.isNull())
|
||||
{
|
||||
return QVariant(Qt::Unchecked);
|
||||
}
|
||||
else if (blocked.exists(blockedPath))
|
||||
{
|
||||
return QVariant(Qt::PartiallyChecked);
|
||||
}
|
||||
else
|
||||
{
|
||||
return QVariant(Qt::Checked);
|
||||
}
|
||||
}
|
||||
|
||||
return sourceIndex.data(role);
|
||||
}
|
||||
|
||||
virtual bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole)
|
||||
{
|
||||
if (index.column() == 0 && role == Qt::CheckStateRole)
|
||||
{
|
||||
Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
|
||||
return setFilterState(index, state);
|
||||
}
|
||||
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
return QSortFilterProxyModel::sourceModel()->setData(sourceIndex, value, role);
|
||||
}
|
||||
|
||||
QString relPath(const QString &path) const
|
||||
{
|
||||
QString prefix = QDir().absoluteFilePath(m_instance->instanceRoot());
|
||||
prefix += '/';
|
||||
if (!path.startsWith(prefix))
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
return path.mid(prefix.size());
|
||||
}
|
||||
|
||||
bool setFilterState(QModelIndex index, Qt::CheckState state)
|
||||
{
|
||||
QFileSystemModel *fsm = qobject_cast<QFileSystemModel *>(sourceModel());
|
||||
|
||||
if (!fsm)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||
bool changed = false;
|
||||
if (state == Qt::Unchecked)
|
||||
{
|
||||
// blocking a path
|
||||
auto &node = blocked.insert(blockedPath);
|
||||
// get rid of all blocked nodes below
|
||||
node.clear();
|
||||
changed = true;
|
||||
}
|
||||
else if (state == Qt::Checked || state == Qt::PartiallyChecked)
|
||||
{
|
||||
if (!blocked.remove(blockedPath))
|
||||
{
|
||||
auto cover = blocked.cover(blockedPath);
|
||||
qDebug() << "Blocked by cover" << cover;
|
||||
// uncover
|
||||
blocked.remove(cover);
|
||||
// block all contents, except for any cover
|
||||
QModelIndex rootIndex =
|
||||
fsm->index(PathCombine(m_instance->instanceRoot(), cover));
|
||||
QModelIndex doing = rootIndex;
|
||||
int row = 0;
|
||||
QStack<QModelIndex> todo;
|
||||
while (1)
|
||||
{
|
||||
auto node = doing.child(row, 0);
|
||||
if (!node.isValid())
|
||||
{
|
||||
if (!todo.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
doing = todo.pop();
|
||||
row = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
auto relpath = relPath(fsm->filePath(node));
|
||||
if (blockedPath.startsWith(relpath)) // cover found?
|
||||
{
|
||||
// continue processing cover later
|
||||
todo.push(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
// or just block this one.
|
||||
blocked.insert(relpath);
|
||||
}
|
||||
row++;
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
if (changed)
|
||||
{
|
||||
// update the thing
|
||||
emit dataChanged(index, index, {Qt::CheckStateRole});
|
||||
// update everything above index
|
||||
QModelIndex up = index.parent();
|
||||
while (1)
|
||||
{
|
||||
if (!up.isValid())
|
||||
break;
|
||||
emit dataChanged(up, up, {Qt::CheckStateRole});
|
||||
up = up.parent();
|
||||
}
|
||||
// and everything below the index
|
||||
QModelIndex doing = index;
|
||||
int row = 0;
|
||||
QStack<QModelIndex> todo;
|
||||
while (1)
|
||||
{
|
||||
auto node = doing.child(row, 0);
|
||||
if (!node.isValid())
|
||||
{
|
||||
if (!todo.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
doing = todo.pop();
|
||||
row = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
emit dataChanged(node, node, {Qt::CheckStateRole});
|
||||
todo.push(node);
|
||||
row++;
|
||||
}
|
||||
// siblings and unrelated nodes are ignored
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool shouldExpand(QModelIndex index)
|
||||
{
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
QFileSystemModel *fsm = qobject_cast<QFileSystemModel *>(sourceModel());
|
||||
if (!fsm)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||
auto found = blocked.find(blockedPath);
|
||||
if(found)
|
||||
{
|
||||
return !found->leaf();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setBlockedPaths(QStringList paths)
|
||||
{
|
||||
beginResetModel();
|
||||
blocked.clear();
|
||||
blocked.insert(paths);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
const SeparatorPrefixTree<'/'> & blockedPaths() const
|
||||
{
|
||||
return blocked;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const
|
||||
{
|
||||
Q_UNUSED(source_parent)
|
||||
|
||||
// adjust the columns you want to filter out here
|
||||
// return false for those that will be hidden
|
||||
if (source_column == 2 || source_column == 3)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
InstancePtr m_instance;
|
||||
SeparatorPrefixTree<'/'> blocked;
|
||||
};
|
||||
|
||||
ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::ExportInstanceDialog), m_instance(instance)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
auto model = new QFileSystemModel(this);
|
||||
proxyModel = new PackIgnoreProxy(m_instance, this);
|
||||
loadPackIgnore();
|
||||
proxyModel->setSourceModel(model);
|
||||
auto root = instance->instanceRoot();
|
||||
ui->treeView->setModel(proxyModel);
|
||||
ui->treeView->setRootIndex(proxyModel->mapFromSource(model->index(root)));
|
||||
|
||||
connect(proxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(rowsInserted(QModelIndex,int,int)));
|
||||
|
||||
model->setRootPath(root);
|
||||
auto headerView = ui->treeView->header();
|
||||
headerView->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
headerView->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
ExportInstanceDialog::~ExportInstanceDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool ExportInstanceDialog::doExport()
|
||||
{
|
||||
auto name = RemoveInvalidFilenameChars(m_instance->name());
|
||||
|
||||
const QString output = QFileDialog::getSaveFileName(
|
||||
this, tr("Export %1").arg(m_instance->name()),
|
||||
PathCombine(QDir::homePath(), name + ".zip"), "Zip (*.zip)");
|
||||
if (output.isNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (QFile::exists(output))
|
||||
{
|
||||
int ret =
|
||||
QMessageBox::question(this, tr("Overwrite?"),
|
||||
tr("This file already exists. Do you want to overwrite it?"),
|
||||
QMessageBox::No, QMessageBox::Yes);
|
||||
if (ret == QMessageBox::No)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!MMCZip::compressDir(output, m_instance->instanceRoot(), name, &proxyModel->blockedPaths()))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Unable to export instance"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExportInstanceDialog::done(int result)
|
||||
{
|
||||
savePackIgnore();
|
||||
if (result == QDialog::Accepted)
|
||||
{
|
||||
if (doExport())
|
||||
{
|
||||
QDialog::done(QDialog::Accepted);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
QDialog::done(result);
|
||||
}
|
||||
|
||||
void ExportInstanceDialog::rowsInserted(QModelIndex parent, int top, int bottom)
|
||||
{
|
||||
//WARNING: possible off-by-one?
|
||||
for(int i = top; i < bottom; i++)
|
||||
{
|
||||
auto node = parent.child(i, 0);
|
||||
if(proxyModel->shouldExpand(node))
|
||||
{
|
||||
auto expNode = node.parent();
|
||||
if(!expNode.isValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ui->treeView->expand(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString ExportInstanceDialog::ignoreFileName()
|
||||
{
|
||||
return PathCombine(m_instance->instanceRoot(), ".packignore");
|
||||
}
|
||||
|
||||
void ExportInstanceDialog::loadPackIgnore()
|
||||
{
|
||||
auto filename = ignoreFileName();
|
||||
QFile ignoreFile(filename);
|
||||
if(!ignoreFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto data = ignoreFile.readAll();
|
||||
auto string = QString::fromUtf8(data);
|
||||
proxyModel->setBlockedPaths(string.split('\n', QString::SkipEmptyParts));
|
||||
}
|
||||
|
||||
void ExportInstanceDialog::savePackIgnore()
|
||||
{
|
||||
auto filename = ignoreFileName();
|
||||
QSaveFile ignoreFile(filename);
|
||||
if(!ignoreFile.open(QIODevice::WriteOnly))
|
||||
{
|
||||
ignoreFile.cancelWriting();
|
||||
}
|
||||
auto data = proxyModel->blockedPaths().toStringList().join('\n').toUtf8();
|
||||
ignoreFile.write(data);
|
||||
ignoreFile.commit();
|
||||
}
|
||||
|
||||
#include "ExportInstanceDialog.moc"
|
||||
54
application/dialogs/ExportInstanceDialog.h
Normal file
54
application/dialogs/ExportInstanceDialog.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QModelIndex>
|
||||
#include <memory>
|
||||
|
||||
class BaseInstance;
|
||||
class PackIgnoreProxy;
|
||||
typedef std::shared_ptr<BaseInstance> InstancePtr;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ExportInstanceDialog;
|
||||
}
|
||||
|
||||
class ExportInstanceDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExportInstanceDialog(InstancePtr instance, QWidget *parent = 0);
|
||||
~ExportInstanceDialog();
|
||||
|
||||
virtual void done(int result);
|
||||
|
||||
private:
|
||||
bool doExport();
|
||||
void loadPackIgnore();
|
||||
void savePackIgnore();
|
||||
QString ignoreFileName();
|
||||
|
||||
private:
|
||||
Ui::ExportInstanceDialog *ui;
|
||||
InstancePtr m_instance;
|
||||
PackIgnoreProxy * proxyModel;
|
||||
|
||||
private slots:
|
||||
void rowsInserted(QModelIndex parent, int top, int bottom);
|
||||
};
|
||||
@@ -1,30 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EditNotesDialog</class>
|
||||
<widget class="QDialog" name="EditNotesDialog">
|
||||
<class>ExportInstanceDialog</class>
|
||||
<widget class="QDialog" name="ExportInstanceDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>459</width>
|
||||
<height>399</height>
|
||||
<width>720</width>
|
||||
<height>625</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Edit Notes</string>
|
||||
<string>Export Instance</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="noteEditor">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
<widget class="QTreeView" name="treeView">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="acceptRichText">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextEditable|Qt::TextEditorInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -39,12 +42,15 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>treeView</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>EditNotesDialog</receiver>
|
||||
<receiver>ExportInstanceDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
@@ -60,7 +66,7 @@
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>EditNotesDialog</receiver>
|
||||
<receiver>ExportInstanceDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,10 +22,10 @@
|
||||
#include "IconPickerDialog.h"
|
||||
#include "ui_IconPickerDialog.h"
|
||||
|
||||
#include "gui/Platform.h"
|
||||
#include "gui/groupview/InstanceDelegate.h"
|
||||
#include "Platform.h"
|
||||
#include "groupview/InstanceDelegate.h"
|
||||
|
||||
#include "logic/icons/IconList.h"
|
||||
#include "icons/IconList.h"
|
||||
|
||||
IconPickerDialog::IconPickerDialog(QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::IconPickerDialog)
|
||||
@@ -59,7 +59,7 @@ IconPickerDialog::IconPickerDialog(QWidget *parent)
|
||||
|
||||
contentsWidget->installEventFilter(this);
|
||||
|
||||
contentsWidget->setModel(MMC->icons().get());
|
||||
contentsWidget->setModel(ENV.icons().get());
|
||||
|
||||
auto buttonAdd = ui->buttonBox->addButton(tr("Add Icon"), QDialogButtonBox::ResetRole);
|
||||
auto buttonRemove =
|
||||
@@ -104,12 +104,12 @@ void IconPickerDialog::addNewIcon()
|
||||
//: The type of icon files
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, selectIcons, QString(),
|
||||
tr("Icons") + "(*.png *.jpg *.jpeg *.ico)");
|
||||
MMC->icons()->installIcons(fileNames);
|
||||
ENV.icons()->installIcons(fileNames);
|
||||
}
|
||||
|
||||
void IconPickerDialog::removeSelectedIcon()
|
||||
{
|
||||
MMC->icons()->deleteIcon(selectedIconKey);
|
||||
ENV.icons()->deleteIcon(selectedIconKey);
|
||||
}
|
||||
|
||||
void IconPickerDialog::activated(QModelIndex index)
|
||||
@@ -130,7 +130,7 @@ void IconPickerDialog::selectionChanged(QItemSelection selected, QItemSelection
|
||||
|
||||
int IconPickerDialog::exec(QString selection)
|
||||
{
|
||||
auto list = MMC->icons();
|
||||
auto list = ENV.icons();
|
||||
auto contentsWidget = ui->iconView;
|
||||
selectedIconKey = selection;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2014 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "LoginDialog.h"
|
||||
#include "ui_LoginDialog.h"
|
||||
|
||||
#include "logic/auth/YggdrasilTask.h"
|
||||
#include "auth/YggdrasilTask.h"
|
||||
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
@@ -44,11 +44,11 @@ void LoginDialog::accept()
|
||||
// Setup the login task and start it
|
||||
m_account = MojangAccount::createFromUsername(ui->userTextBox->text());
|
||||
m_loginTask = m_account->login(nullptr, ui->passTextBox->text());
|
||||
connect(m_loginTask.get(), &ProgressProvider::failed, this, &LoginDialog::onTaskFailed);
|
||||
connect(m_loginTask.get(), &ProgressProvider::succeeded, this,
|
||||
connect(m_loginTask.get(), &Task::failed, this, &LoginDialog::onTaskFailed);
|
||||
connect(m_loginTask.get(), &Task::succeeded, this,
|
||||
&LoginDialog::onTaskSucceeded);
|
||||
connect(m_loginTask.get(), &ProgressProvider::status, this, &LoginDialog::onTaskStatus);
|
||||
connect(m_loginTask.get(), &ProgressProvider::progress, this, &LoginDialog::onTaskProgress);
|
||||
connect(m_loginTask.get(), &Task::status, this, &LoginDialog::onTaskStatus);
|
||||
connect(m_loginTask.get(), &Task::progress, this, &LoginDialog::onTaskProgress);
|
||||
m_loginTask->start();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2014 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtCore/QEventLoop>
|
||||
|
||||
#include "logic/auth/MojangAccount.h"
|
||||
#include "auth/MojangAccount.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@@ -1,27 +1,10 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ModEditDialogCommon.h"
|
||||
#include "CustomMessageBox.h"
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
bool lastfirst(QModelIndexList &list, int &first, int &last)
|
||||
{
|
||||
if (!list.size())
|
||||
if (list.isEmpty())
|
||||
return false;
|
||||
first = last = list[0].row();
|
||||
for (auto item : list)
|
||||
9
application/dialogs/ModEditDialogCommon.h
Normal file
9
application/dialogs/ModEditDialogCommon.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <QModelIndex>
|
||||
#include <QDesktopServices>
|
||||
#include <QWidget>
|
||||
#include <minecraft/Mod.h>
|
||||
|
||||
bool lastfirst(QModelIndexList &list, int &first, int &last);
|
||||
|
||||
void showWebsiteForMod(QWidget *parentDlg, Mod &m);
|
||||
207
application/dialogs/NewInstanceDialog.cpp
Normal file
207
application/dialogs/NewInstanceDialog.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "MultiMC.h"
|
||||
#include "NewInstanceDialog.h"
|
||||
#include "ui_NewInstanceDialog.h"
|
||||
|
||||
#include <BaseVersion.h>
|
||||
#include <icons/IconList.h>
|
||||
#include <minecraft/MinecraftVersionList.h>
|
||||
#include <tasks/Task.h>
|
||||
#include <InstanceList.h>
|
||||
|
||||
#include "Platform.h"
|
||||
#include "VersionSelectDialog.h"
|
||||
#include "ProgressDialog.h"
|
||||
#include "IconPickerDialog.h"
|
||||
|
||||
#include <QLayout>
|
||||
#include <QPushButton>
|
||||
#include <QFileDialog>
|
||||
#include <QValidator>
|
||||
|
||||
class UrlValidator : public QValidator
|
||||
{
|
||||
public:
|
||||
using QValidator::QValidator;
|
||||
|
||||
State validate(QString &in, int &pos) const
|
||||
{
|
||||
const QUrl url(in);
|
||||
if (url.isValid() && !url.isRelative() && !url.isEmpty())
|
||||
{
|
||||
return Acceptable;
|
||||
}
|
||||
else if (QFile::exists(in))
|
||||
{
|
||||
return Acceptable;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Intermediate;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
NewInstanceDialog::NewInstanceDialog(QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::NewInstanceDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
resize(minimumSizeHint());
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
||||
setSelectedVersion(MMC->minecraftlist()->getRecommended(), true);
|
||||
InstIconKey = "infinity";
|
||||
ui->iconButton->setIcon(ENV.icons()->getIcon(InstIconKey));
|
||||
|
||||
ui->modpackEdit->setValidator(new UrlValidator(ui->modpackEdit));
|
||||
connect(ui->modpackEdit, &QLineEdit::textChanged, this, &NewInstanceDialog::updateDialogState);
|
||||
connect(ui->modpackBox, &QRadioButton::clicked, this, &NewInstanceDialog::updateDialogState);
|
||||
connect(ui->versionBox, &QRadioButton::clicked, this, &NewInstanceDialog::updateDialogState);
|
||||
|
||||
auto groups = MMC->instances()->getGroups().toSet();
|
||||
auto groupList = QStringList(groups.toList());
|
||||
groupList.sort(Qt::CaseInsensitive);
|
||||
groupList.removeOne("");
|
||||
QString oldValue = MMC->settings()->get("LastUsedGroupForNewInstance").toString();
|
||||
groupList.push_front(oldValue);
|
||||
groupList.push_front("");
|
||||
ui->groupBox->addItems(groupList);
|
||||
int index = groupList.indexOf(oldValue);
|
||||
if(index == -1)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
ui->groupBox->setCurrentIndex(index);
|
||||
ui->groupBox->lineEdit()->setPlaceholderText(tr("No group"));
|
||||
}
|
||||
|
||||
NewInstanceDialog::~NewInstanceDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NewInstanceDialog::updateDialogState()
|
||||
{
|
||||
bool allowOK = !instName().isEmpty() &&
|
||||
(ui->versionBox->isChecked() && m_selectedVersion ||
|
||||
(ui->modpackBox->isChecked() && ui->modpackEdit->hasAcceptableInput()));
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(allowOK);
|
||||
}
|
||||
|
||||
void NewInstanceDialog::setSelectedVersion(BaseVersionPtr version, bool initial)
|
||||
{
|
||||
m_selectedVersion = version;
|
||||
|
||||
if (m_selectedVersion)
|
||||
{
|
||||
ui->versionTextBox->setText(version->name());
|
||||
if(ui->instNameTextBox->text().isEmpty() && !initial)
|
||||
{
|
||||
ui->instNameTextBox->setText(version->name());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->versionTextBox->setText("");
|
||||
}
|
||||
|
||||
updateDialogState();
|
||||
}
|
||||
|
||||
QString NewInstanceDialog::instName() const
|
||||
{
|
||||
return ui->instNameTextBox->text();
|
||||
}
|
||||
QString NewInstanceDialog::instGroup() const
|
||||
{
|
||||
return ui->groupBox->currentText();
|
||||
}
|
||||
QString NewInstanceDialog::iconKey() const
|
||||
{
|
||||
return InstIconKey;
|
||||
}
|
||||
QUrl NewInstanceDialog::modpackUrl() const
|
||||
{
|
||||
if (ui->modpackBox->isChecked())
|
||||
{
|
||||
const QUrl url(ui->modpackEdit->text());
|
||||
if (url.isValid() && !url.isRelative() && !url.host().isEmpty())
|
||||
{
|
||||
return url;
|
||||
}
|
||||
else
|
||||
{
|
||||
return QUrl::fromLocalFile(ui->modpackEdit->text());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return QUrl();
|
||||
}
|
||||
}
|
||||
|
||||
BaseVersionPtr NewInstanceDialog::selectedVersion() const
|
||||
{
|
||||
return m_selectedVersion;
|
||||
}
|
||||
|
||||
void NewInstanceDialog::on_btnChangeVersion_clicked()
|
||||
{
|
||||
VersionSelectDialog vselect(MMC->minecraftlist().get(), tr("Change Minecraft version"),
|
||||
this);
|
||||
vselect.exec();
|
||||
if (vselect.result() == QDialog::Accepted)
|
||||
{
|
||||
BaseVersionPtr version = vselect.selectedVersion();
|
||||
if (version)
|
||||
setSelectedVersion(version);
|
||||
}
|
||||
}
|
||||
|
||||
void NewInstanceDialog::on_iconButton_clicked()
|
||||
{
|
||||
IconPickerDialog dlg(this);
|
||||
dlg.exec(InstIconKey);
|
||||
|
||||
if (dlg.result() == QDialog::Accepted)
|
||||
{
|
||||
InstIconKey = dlg.selectedIconKey;
|
||||
ui->iconButton->setIcon(ENV.icons()->getIcon(InstIconKey));
|
||||
}
|
||||
}
|
||||
|
||||
void NewInstanceDialog::on_instNameTextBox_textChanged(const QString &arg1)
|
||||
{
|
||||
updateDialogState();
|
||||
}
|
||||
|
||||
void NewInstanceDialog::on_modpackBtn_clicked()
|
||||
{
|
||||
const QUrl url = QFileDialog::getOpenFileUrl(this, tr("Choose modpack"), modpackUrl(), tr("Zip (*.zip)"));
|
||||
if (url.isValid())
|
||||
{
|
||||
if (url.isLocalFile())
|
||||
{
|
||||
ui->modpackEdit->setText(url.toLocalFile());
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->modpackEdit->setText(url.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include "logic/BaseVersion.h"
|
||||
|
||||
#include "BaseVersion.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@@ -33,18 +34,21 @@ public:
|
||||
|
||||
void updateDialogState();
|
||||
|
||||
void setSelectedVersion(BaseVersionPtr version);
|
||||
void setSelectedVersion(BaseVersionPtr version, bool initial = false);
|
||||
|
||||
void loadVersionList();
|
||||
|
||||
QString instName() const;
|
||||
QString instGroup() const;
|
||||
QString iconKey() const;
|
||||
QUrl modpackUrl() const;
|
||||
BaseVersionPtr selectedVersion() const;
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_btnChangeVersion_clicked();
|
||||
void on_iconButton_clicked();
|
||||
void on_modpackBtn_clicked();
|
||||
void on_instNameTextBox_textChanged(const QString &arg1);
|
||||
|
||||
private:
|
||||
@@ -9,15 +9,15 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>220</width>
|
||||
<height>234</height>
|
||||
<width>277</width>
|
||||
<height>404</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>New Instance</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../graphics.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/icons/toolbar/new</normaloff>:/icons/toolbar/new</iconset>
|
||||
</property>
|
||||
<property name="modal">
|
||||
@@ -42,7 +42,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="iconButton">
|
||||
<property name="icon">
|
||||
<iconset resource="../../graphics.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/icons/instances/infinity</normaloff>:/icons/instances/infinity</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
@@ -85,26 +85,83 @@
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelVersion">
|
||||
<widget class="QLabel" name="labelVersion_3">
|
||||
<property name="text">
|
||||
<string>Version:</string>
|
||||
<string>&Group:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>groupBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="groupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="4" column="2">
|
||||
<widget class="QToolButton" name="modpackBtn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLineEdit" name="modpackEdit">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>http://</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QLineEdit" name="versionTextBox">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QToolButton" name="btnChangeVersion">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
<widget class="QRadioButton" name="modpackBox">
|
||||
<property name="text">
|
||||
<string>Impor&t Modpack (local file or link):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<widget class="QRadioButton" name="versionBox">
|
||||
<property name="text">
|
||||
<string>Vani&lla Minecraft (select version):</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@@ -139,9 +196,18 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../graphics.qrc"/>
|
||||
</resources>
|
||||
<tabstops>
|
||||
<tabstop>instNameTextBox</tabstop>
|
||||
<tabstop>groupBox</tabstop>
|
||||
<tabstop>versionBox</tabstop>
|
||||
<tabstop>versionTextBox</tabstop>
|
||||
<tabstop>btnChangeVersion</tabstop>
|
||||
<tabstop>modpackBox</tabstop>
|
||||
<tabstop>modpackEdit</tabstop>
|
||||
<tabstop>modpackBtn</tabstop>
|
||||
<tabstop>iconButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
@@ -150,8 +216,8 @@
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
<x>257</x>
|
||||
<y>333</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
@@ -166,8 +232,8 @@
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
<x>325</x>
|
||||
<y>333</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
@@ -175,5 +241,69 @@
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>modpackBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>modpackEdit</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>81</x>
|
||||
<y>229</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>236</x>
|
||||
<y>221</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>modpackBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>modpackBtn</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>129</x>
|
||||
<y>225</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>328</x>
|
||||
<y>229</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>versionBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>versionTextBox</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>93</x>
|
||||
<y>195</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>213</x>
|
||||
<y>191</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>versionBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>btnChangeVersion</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>104</x>
|
||||
<y>198</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>322</x>
|
||||
<y>192</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "logic/updater/NotificationChecker.h"
|
||||
#include "notifications/NotificationChecker.h"
|
||||
|
||||
namespace Ui {
|
||||
class NotificationDialog;
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "logic/tasks/Task.h"
|
||||
#include "gui/Platform.h"
|
||||
#include "tasks/Task.h"
|
||||
#include "Platform.h"
|
||||
|
||||
ProgressDialog::ProgressDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ProgressDialog)
|
||||
{
|
||||
@@ -54,7 +54,7 @@ void ProgressDialog::updateSize()
|
||||
resize(QSize(480, minimumSizeHint().height()));
|
||||
}
|
||||
|
||||
int ProgressDialog::exec(ProgressProvider *task)
|
||||
int ProgressDialog::exec(Task *task)
|
||||
{
|
||||
this->task = task;
|
||||
|
||||
@@ -71,10 +71,10 @@ int ProgressDialog::exec(ProgressProvider *task)
|
||||
if(task->isRunning())
|
||||
return QDialog::exec();
|
||||
else
|
||||
return 0;
|
||||
return QDialog::Accepted;
|
||||
}
|
||||
|
||||
ProgressProvider *ProgressDialog::getTask()
|
||||
Task *ProgressDialog::getTask()
|
||||
{
|
||||
return task;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class ProgressProvider;
|
||||
class Task;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@@ -34,10 +34,11 @@ public:
|
||||
|
||||
void updateSize();
|
||||
|
||||
int exec(ProgressProvider *task);
|
||||
int exec(Task *task);
|
||||
|
||||
void setSkipButton(bool present, QString label = QString());
|
||||
|
||||
ProgressProvider *getTask();
|
||||
Task *getTask();
|
||||
|
||||
public
|
||||
slots:
|
||||
@@ -60,5 +61,5 @@ protected:
|
||||
private:
|
||||
Ui::ProgressDialog *ui;
|
||||
|
||||
ProgressProvider *task;
|
||||
Task *task;
|
||||
};
|
||||
136
application/dialogs/UpdateDialog.cpp
Normal file
136
application/dialogs/UpdateDialog.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
#include "UpdateDialog.h"
|
||||
#include "ui_UpdateDialog.h"
|
||||
#include "Platform.h"
|
||||
#include <QDebug>
|
||||
#include "MultiMC.h"
|
||||
#include <settings/SettingsObject.h>
|
||||
|
||||
#include <hoedown/html.h>
|
||||
#include <hoedown/document.h>
|
||||
|
||||
UpdateDialog::UpdateDialog(bool hasUpdate, QWidget *parent) : QDialog(parent), ui(new Ui::UpdateDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
auto channel = MMC->settings()->get("UpdateChannel").toString();
|
||||
if(hasUpdate)
|
||||
{
|
||||
ui->label->setText(tr("A new %1 update is available!").arg(channel));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->label->setText(tr("No %1 updates found. You are running the latest version.").arg(channel));
|
||||
ui->btnUpdateNow->setDisabled(true);
|
||||
ui->btnUpdateOnExit->setDisabled(true);
|
||||
}
|
||||
loadChangelog();
|
||||
}
|
||||
|
||||
UpdateDialog::~UpdateDialog()
|
||||
{
|
||||
}
|
||||
|
||||
void UpdateDialog::loadChangelog()
|
||||
{
|
||||
auto channel = MMC->settings()->get("UpdateChannel").toString();
|
||||
dljob.reset(new NetJob("Changelog"));
|
||||
auto url = QString("https://raw.githubusercontent.com/MultiMC/MultiMC5/%1/changelog.md").arg(channel);
|
||||
changelogDownload = ByteArrayDownload::make(QUrl(url));
|
||||
dljob->addNetAction(changelogDownload);
|
||||
connect(dljob.get(), &NetJob::succeeded, this, &UpdateDialog::changelogLoaded);
|
||||
connect(dljob.get(), &NetJob::failed, this, &UpdateDialog::changelogFailed);
|
||||
dljob->start();
|
||||
}
|
||||
|
||||
/**
|
||||
* hoedown wrapper, because dealing with resource lifetime in C is stupid
|
||||
*/
|
||||
class HoeDown
|
||||
{
|
||||
public:
|
||||
class buffer
|
||||
{
|
||||
public:
|
||||
buffer(size_t unit = 4096)
|
||||
{
|
||||
buf = hoedown_buffer_new(unit);
|
||||
}
|
||||
~buffer()
|
||||
{
|
||||
hoedown_buffer_free(buf);
|
||||
}
|
||||
const char * cstr()
|
||||
{
|
||||
return hoedown_buffer_cstr(buf);
|
||||
}
|
||||
void put(QByteArray input)
|
||||
{
|
||||
hoedown_buffer_put(buf, (uint8_t *) input.data(), input.size());
|
||||
}
|
||||
const uint8_t * data() const
|
||||
{
|
||||
return buf->data;
|
||||
}
|
||||
size_t size() const
|
||||
{
|
||||
return buf->size;
|
||||
}
|
||||
hoedown_buffer * buf;
|
||||
} ib, ob;
|
||||
HoeDown()
|
||||
{
|
||||
renderer = hoedown_html_renderer_new((hoedown_html_flags) 0,0);
|
||||
document = hoedown_document_new(renderer, (hoedown_extensions) 0, 8);
|
||||
}
|
||||
~HoeDown()
|
||||
{
|
||||
hoedown_document_free(document);
|
||||
hoedown_html_renderer_free(renderer);
|
||||
}
|
||||
QString process(QByteArray input)
|
||||
{
|
||||
ib.put(input);
|
||||
hoedown_document_render(document, ob.buf, ib.data(), ib.size());
|
||||
return ob.cstr();
|
||||
}
|
||||
private:
|
||||
hoedown_document * document;
|
||||
hoedown_renderer * renderer;
|
||||
};
|
||||
|
||||
QString reprocessMarkdown(QByteArray markdown)
|
||||
{
|
||||
HoeDown hoedown;
|
||||
QString output = hoedown.process(markdown);
|
||||
|
||||
// HACK: easier than customizing hoedown
|
||||
output.replace(QRegExp("GH-([0-9]+)"), "<a href=\"https://github.com/MultiMC/MultiMC5/issues/\\1\">GH-\\1</a>");
|
||||
qDebug() << output;
|
||||
return output;
|
||||
}
|
||||
|
||||
void UpdateDialog::changelogLoaded()
|
||||
{
|
||||
auto html = reprocessMarkdown(changelogDownload->m_data);
|
||||
ui->changelogBrowser->setHtml(html);
|
||||
}
|
||||
|
||||
void UpdateDialog::changelogFailed(QString reason)
|
||||
{
|
||||
ui->changelogBrowser->setHtml(tr("<p align=\"center\" <span style=\"font-size:22pt;\">Failed to fetch changelog... Error: %1</span></p>").arg(reason));
|
||||
}
|
||||
|
||||
void UpdateDialog::on_btnUpdateLater_clicked()
|
||||
{
|
||||
reject();
|
||||
}
|
||||
|
||||
void UpdateDialog::on_btnUpdateNow_clicked()
|
||||
{
|
||||
done(UPDATE_NOW);
|
||||
}
|
||||
|
||||
void UpdateDialog::on_btnUpdateOnExit_clicked()
|
||||
{
|
||||
done(UPDATE_ONEXIT);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include "net/ByteArrayDownload.h"
|
||||
#include "net/NetJob.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@@ -34,7 +36,7 @@ class UpdateDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UpdateDialog(QWidget *parent = 0);
|
||||
explicit UpdateDialog(bool hasUpdate = true, QWidget *parent = 0);
|
||||
~UpdateDialog();
|
||||
|
||||
private:
|
||||
@@ -43,4 +45,17 @@ public slots:
|
||||
void on_btnUpdateNow_clicked();
|
||||
void on_btnUpdateOnExit_clicked();
|
||||
void on_btnUpdateLater_clicked();
|
||||
|
||||
/// Starts loading the changelog
|
||||
void loadChangelog();
|
||||
|
||||
/// Slot for when the chengelog loads successfully.
|
||||
void changelogLoaded();
|
||||
|
||||
/// Slot for when the chengelog fails to load...
|
||||
void changelogFailed(QString reason);
|
||||
|
||||
private:
|
||||
ByteArrayDownloadPtr changelogDownload;
|
||||
NetJobPtr dljob;
|
||||
};
|
||||
106
application/dialogs/UpdateDialog.ui
Normal file
106
application/dialogs/UpdateDialog.ui
Normal file
@@ -0,0 +1,106 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UpdateDialog</class>
|
||||
<widget class="QDialog" name="UpdateDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>657</width>
|
||||
<height>673</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MultiMC Update</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset>
|
||||
<normaloff>:/icons/toolbar/checkupdate</normaloff>:/icons/toolbar/checkupdate</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>changelogBrowser</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="changelogBrowser">
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:22pt;">Loading changelog...</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnUpdateNow">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update now</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnUpdateOnExit">
|
||||
<property name="text">
|
||||
<string>Update after MultiMC closes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnUpdateLater">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Don't update yet</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>changelogBrowser</tabstop>
|
||||
<tabstop>btnUpdateNow</tabstop>
|
||||
<tabstop>btnUpdateOnExit</tabstop>
|
||||
<tabstop>btnUpdateLater</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../resources/multimc/multimc.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
194
application/dialogs/VersionSelectDialog.cpp
Normal file
194
application/dialogs/VersionSelectDialog.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "VersionSelectDialog.h"
|
||||
#include "ui_VersionSelectDialog.h"
|
||||
|
||||
#include <QHeaderView>
|
||||
|
||||
#include <dialogs/ProgressDialog.h>
|
||||
#include "CustomMessageBox.h"
|
||||
#include "Platform.h"
|
||||
|
||||
#include <BaseVersion.h>
|
||||
#include <BaseVersionList.h>
|
||||
#include <tasks/Task.h>
|
||||
#include <modutils.h>
|
||||
#include <QDebug>
|
||||
#include "MultiMC.h"
|
||||
#include <VersionProxyModel.h>
|
||||
|
||||
VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent,
|
||||
bool cancelable)
|
||||
: QDialog(parent), ui(new Ui::VersionSelectDialog)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
ui->setupUi(this);
|
||||
setWindowModality(Qt::WindowModal);
|
||||
setWindowTitle(title);
|
||||
|
||||
m_vlist = vlist;
|
||||
|
||||
m_proxyModel = new VersionProxyModel(this);
|
||||
m_proxyModel->setSourceModel(vlist);
|
||||
|
||||
ui->listView->setModel(m_proxyModel);
|
||||
ui->listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch);
|
||||
ui->sneakyProgressBar->setHidden(true);
|
||||
|
||||
if (!cancelable)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setEmptyString(QString emptyString)
|
||||
{
|
||||
ui->listView->setEmptyString(emptyString);
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setEmptyErrorString(QString emptyErrorString)
|
||||
{
|
||||
ui->listView->setEmptyErrorString(emptyErrorString);
|
||||
}
|
||||
|
||||
VersionSelectDialog::~VersionSelectDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setResizeOn(int column)
|
||||
{
|
||||
ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::ResizeToContents);
|
||||
resizeOnColumn = column;
|
||||
ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
int VersionSelectDialog::exec()
|
||||
{
|
||||
QDialog::open();
|
||||
if (!m_vlist->isLoaded())
|
||||
{
|
||||
loadList();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_proxyModel->rowCount() == 0)
|
||||
{
|
||||
ui->listView->setEmptyMode(VersionListView::String);
|
||||
}
|
||||
preselect();
|
||||
}
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
void VersionSelectDialog::closeEvent(QCloseEvent * event)
|
||||
{
|
||||
if(loadTask)
|
||||
{
|
||||
loadTask->abort();
|
||||
loadTask->deleteLater();
|
||||
loadTask = nullptr;
|
||||
}
|
||||
QDialog::closeEvent(event);
|
||||
}
|
||||
|
||||
void VersionSelectDialog::loadList()
|
||||
{
|
||||
if(loadTask)
|
||||
{
|
||||
return;
|
||||
}
|
||||
loadTask = m_vlist->getLoadTask();
|
||||
if (!loadTask)
|
||||
{
|
||||
return;
|
||||
}
|
||||
connect(loadTask, &Task::finished, this, &VersionSelectDialog::onTaskFinished);
|
||||
connect(loadTask, &Task::progress, this, &VersionSelectDialog::changeProgress);
|
||||
loadTask->start();
|
||||
ui->sneakyProgressBar->setHidden(false);
|
||||
}
|
||||
|
||||
void VersionSelectDialog::onTaskFinished()
|
||||
{
|
||||
if (!loadTask->successful())
|
||||
{
|
||||
CustomMessageBox::selectable(this, tr("Error"),
|
||||
tr("List update failed:\n%1").arg(loadTask->failReason()),
|
||||
QMessageBox::Warning)->show();
|
||||
if (m_proxyModel->rowCount() == 0)
|
||||
{
|
||||
ui->listView->setEmptyMode(VersionListView::ErrorString);
|
||||
}
|
||||
}
|
||||
else if (m_proxyModel->rowCount() == 0)
|
||||
{
|
||||
ui->listView->setEmptyMode(VersionListView::String);
|
||||
}
|
||||
ui->sneakyProgressBar->setHidden(true);
|
||||
loadTask->deleteLater();
|
||||
loadTask = nullptr;
|
||||
preselect();
|
||||
}
|
||||
|
||||
void VersionSelectDialog::changeProgress(qint64 current, qint64 total)
|
||||
{
|
||||
ui->sneakyProgressBar->setMaximum(total);
|
||||
ui->sneakyProgressBar->setValue(current);
|
||||
}
|
||||
|
||||
void VersionSelectDialog::preselect()
|
||||
{
|
||||
if(preselectedAlready)
|
||||
return;
|
||||
preselectedAlready = true;
|
||||
selectRecommended();
|
||||
}
|
||||
|
||||
void VersionSelectDialog::selectRecommended()
|
||||
{
|
||||
auto idx = m_proxyModel->getRecommended();
|
||||
if(idx.isValid())
|
||||
{
|
||||
ui->listView->selectionModel()->setCurrentIndex(idx,QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
||||
ui->listView->scrollTo(idx, QAbstractItemView::PositionAtCenter);
|
||||
}
|
||||
}
|
||||
|
||||
BaseVersionPtr VersionSelectDialog::selectedVersion() const
|
||||
{
|
||||
auto currentIndex = ui->listView->selectionModel()->currentIndex();
|
||||
auto variant = m_proxyModel->data(currentIndex, BaseVersionList::VersionPointerRole);
|
||||
return variant.value<BaseVersionPtr>();
|
||||
}
|
||||
|
||||
void VersionSelectDialog::on_refreshButton_clicked()
|
||||
{
|
||||
loadList();
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setExactFilter(BaseVersionList::ModelRoles role, QString filter)
|
||||
{
|
||||
m_proxyModel->setFilter(role, filter, true);
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter)
|
||||
{
|
||||
m_proxyModel->setFilter(role, filter, false);
|
||||
}
|
||||
|
||||
#include "VersionSelectDialog.moc"
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,15 +18,15 @@
|
||||
#include <QDialog>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include "logic/BaseVersion.h"
|
||||
|
||||
class BaseVersionList;
|
||||
#include "BaseVersionList.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class VersionSelectDialog;
|
||||
}
|
||||
|
||||
class VersionProxyModel;
|
||||
|
||||
class VersionSelectDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -43,21 +43,37 @@ public:
|
||||
|
||||
BaseVersionPtr selectedVersion() const;
|
||||
|
||||
void setFuzzyFilter(int column, QString filter);
|
||||
void setExactFilter(int column, QString filter);
|
||||
void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter);
|
||||
void setExactFilter(BaseVersionList::ModelRoles role, QString filter);
|
||||
void setEmptyString(QString emptyString);
|
||||
void setEmptyErrorString(QString emptyErrorString);
|
||||
void setResizeOn(int column);
|
||||
void setUseLatest(const bool useLatest);
|
||||
|
||||
protected:
|
||||
virtual void closeEvent ( QCloseEvent* );
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_refreshButton_clicked();
|
||||
|
||||
void onTaskFinished();
|
||||
void changeProgress(qint64 current, qint64 total);
|
||||
|
||||
private:
|
||||
Ui::VersionSelectDialog *ui;
|
||||
void preselect();
|
||||
void selectRecommended();
|
||||
|
||||
BaseVersionList *m_vlist;
|
||||
private:
|
||||
Ui::VersionSelectDialog *ui = nullptr;
|
||||
|
||||
QSortFilterProxyModel *m_proxyModel;
|
||||
BaseVersionList *m_vlist = nullptr;
|
||||
|
||||
VersionProxyModel *m_proxyModel = nullptr;
|
||||
|
||||
int resizeOnColumn = 0;
|
||||
|
||||
Task * loadTask = nullptr;
|
||||
|
||||
bool preselectedAlready = false;
|
||||
};
|
||||
@@ -39,6 +39,16 @@
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="sneakyProgressBar">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string notr="true">%p%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
@@ -69,7 +79,7 @@
|
||||
<customwidget>
|
||||
<class>VersionListView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>gui/widgets/VersionListView.h</header>
|
||||
<header>widgets/VersionListView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
@@ -3,15 +3,16 @@
|
||||
#include <QPainter>
|
||||
#include <QApplication>
|
||||
#include <QtMath>
|
||||
#include <QDebug>
|
||||
#include <QMouseEvent>
|
||||
#include <QListView>
|
||||
#include <QPersistentModelIndex>
|
||||
#include <QDrag>
|
||||
#include <QMimeData>
|
||||
#include <QCache>
|
||||
#include <QScrollBar>
|
||||
|
||||
#include "Group.h"
|
||||
#include "VisualGroup.h"
|
||||
#include <QDebug>
|
||||
|
||||
template <typename T> bool listsIntersect(const QList<T> &l1, const QList<T> t2)
|
||||
{
|
||||
@@ -26,17 +27,12 @@ template <typename T> bool listsIntersect(const QList<T> &l1, const QList<T> t2)
|
||||
}
|
||||
|
||||
GroupView::GroupView(QWidget *parent)
|
||||
: QAbstractItemView(parent), m_leftMargin(5), m_rightMargin(5), m_bottomMargin(5),
|
||||
m_categoryMargin(5) //, m_updatesDisabled(false), m_categoryEditor(0), m_editedCategory(0)
|
||||
: QAbstractItemView(parent)
|
||||
{
|
||||
// setViewMode(IconMode);
|
||||
// setMovement(Snap);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
// setWordWrap(true);
|
||||
// setDragDropMode(QListView::InternalMove);
|
||||
setAcceptDrops(true);
|
||||
m_spacing = 5;
|
||||
setAutoScroll(true);
|
||||
}
|
||||
|
||||
GroupView::~GroupView()
|
||||
@@ -66,11 +62,28 @@ void GroupView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e
|
||||
scheduleDelayedItemsLayout();
|
||||
}
|
||||
|
||||
class LocaleString : public QString
|
||||
{
|
||||
public:
|
||||
LocaleString(const char *s) : QString(s)
|
||||
{
|
||||
}
|
||||
LocaleString(const QString &s) : QString(s)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator<(const LocaleString &lhs, const LocaleString &rhs)
|
||||
{
|
||||
return (QString::localeAwareCompare(lhs, rhs) < 0);
|
||||
}
|
||||
|
||||
void GroupView::updateGeometries()
|
||||
{
|
||||
geometryCache.clear();
|
||||
int previousScroll = verticalScrollBar()->value();
|
||||
|
||||
QMap<QString, Group *> cats;
|
||||
QMap<LocaleString, VisualGroup *> cats;
|
||||
|
||||
for (int i = 0; i < model()->rowCount(); ++i)
|
||||
{
|
||||
@@ -78,14 +91,14 @@ void GroupView::updateGeometries()
|
||||
model()->index(i, 0).data(GroupViewRoles::GroupRole).toString();
|
||||
if (!cats.contains(groupName))
|
||||
{
|
||||
Group *old = this->category(groupName);
|
||||
VisualGroup *old = this->category(groupName);
|
||||
if (old)
|
||||
{
|
||||
cats.insert(groupName, new Group(old));
|
||||
cats.insert(groupName, new VisualGroup(old));
|
||||
}
|
||||
else
|
||||
{
|
||||
cats.insert(groupName, new Group(groupName, this));
|
||||
cats.insert(groupName, new VisualGroup(groupName, this));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,7 +160,7 @@ void GroupView::modelReset()
|
||||
|
||||
bool GroupView::isIndexHidden(const QModelIndex &index) const
|
||||
{
|
||||
Group *cat = category(index);
|
||||
VisualGroup *cat = category(index);
|
||||
if (cat)
|
||||
{
|
||||
return cat->collapsed;
|
||||
@@ -158,12 +171,12 @@ bool GroupView::isIndexHidden(const QModelIndex &index) const
|
||||
}
|
||||
}
|
||||
|
||||
Group *GroupView::category(const QModelIndex &index) const
|
||||
VisualGroup *GroupView::category(const QModelIndex &index) const
|
||||
{
|
||||
return category(index.data(GroupViewRoles::GroupRole).toString());
|
||||
}
|
||||
|
||||
Group *GroupView::category(const QString &cat) const
|
||||
VisualGroup *GroupView::category(const QString &cat) const
|
||||
{
|
||||
for (auto group : m_groups)
|
||||
{
|
||||
@@ -175,11 +188,11 @@ Group *GroupView::category(const QString &cat) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Group *GroupView::categoryAt(const QPoint &pos) const
|
||||
VisualGroup *GroupView::categoryAt(const QPoint &pos) const
|
||||
{
|
||||
for (auto group : m_groups)
|
||||
{
|
||||
if(group->hitScan(pos) & Group::CheckboxHit)
|
||||
if(group->hitScan(pos) & VisualGroup::CheckboxHit)
|
||||
{
|
||||
return group;
|
||||
}
|
||||
@@ -187,7 +200,7 @@ Group *GroupView::categoryAt(const QPoint &pos) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int GroupView::itemsPerRow() const
|
||||
int GroupView::calculateItemsPerRow() const
|
||||
{
|
||||
return qFloor((qreal)(contentWidth()) / (qreal)(itemWidth() + m_spacing));
|
||||
}
|
||||
@@ -199,77 +212,7 @@ int GroupView::contentWidth() const
|
||||
|
||||
int GroupView::itemWidth() const
|
||||
{
|
||||
return itemDelegate()
|
||||
->sizeHint(viewOptions(), model()->index(model()->rowCount() - 1, 0))
|
||||
.width();
|
||||
}
|
||||
|
||||
int GroupView::categoryRowHeight(const QModelIndex &index) const
|
||||
{
|
||||
QModelIndexList indices;
|
||||
int internalRow = categoryInternalPosition(index).second;
|
||||
for (auto &i : category(index)->items())
|
||||
{
|
||||
if (categoryInternalPosition(i).second == internalRow)
|
||||
{
|
||||
indices.append(i);
|
||||
}
|
||||
}
|
||||
|
||||
int largestHeight = 0;
|
||||
for (auto &i : indices)
|
||||
{
|
||||
largestHeight =
|
||||
qMax(largestHeight, itemDelegate()->sizeHint(viewOptions(), i).height());
|
||||
}
|
||||
return largestHeight + m_spacing;
|
||||
}
|
||||
|
||||
QPair<int, int> GroupView::categoryInternalPosition(const QModelIndex &index) const
|
||||
{
|
||||
QList<QModelIndex> indices = category(index)->items();
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
const int perRow = itemsPerRow();
|
||||
for (int i = 0; i < indices.size(); ++i)
|
||||
{
|
||||
if (indices.at(i) == index)
|
||||
{
|
||||
break;
|
||||
}
|
||||
++x;
|
||||
if (x == perRow)
|
||||
{
|
||||
x = 0;
|
||||
++y;
|
||||
}
|
||||
}
|
||||
return qMakePair(x, y);
|
||||
}
|
||||
|
||||
int GroupView::categoryInternalRowTop(const QModelIndex &index) const
|
||||
{
|
||||
Group *cat = category(index);
|
||||
int categoryInternalRow = categoryInternalPosition(index).second;
|
||||
int result = 0;
|
||||
for (int i = 0; i < categoryInternalRow; ++i)
|
||||
{
|
||||
result += cat->rowHeights.at(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int GroupView::itemHeightForCategoryRow(const Group *category, const int internalRow) const
|
||||
{
|
||||
for (auto &i : category->items())
|
||||
{
|
||||
QPair<int, int> pos = categoryInternalPosition(i);
|
||||
if (pos.second == internalRow)
|
||||
{
|
||||
return categoryRowHeight(i);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return m_itemWidth;
|
||||
}
|
||||
|
||||
void GroupView::mousePressEvent(QMouseEvent *event)
|
||||
@@ -283,7 +226,6 @@ void GroupView::mousePressEvent(QMouseEvent *event)
|
||||
|
||||
m_pressedIndex = index;
|
||||
m_pressedAlreadySelected = selectionModel()->isSelected(m_pressedIndex);
|
||||
QItemSelectionModel::SelectionFlags selection_flags = selectionCommand(index, event);
|
||||
m_pressedPosition = geometryPos;
|
||||
|
||||
m_pressedCategory = categoryAt(geometryPos);
|
||||
@@ -296,13 +238,19 @@ void GroupView::mousePressEvent(QMouseEvent *event)
|
||||
|
||||
if (index.isValid() && (index.flags() & Qt::ItemIsEnabled))
|
||||
{
|
||||
if(index != currentIndex())
|
||||
{
|
||||
// FIXME: better!
|
||||
m_currentCursorColumn = -1;
|
||||
}
|
||||
// we disable scrollTo for mouse press so the item doesn't change position
|
||||
// when the user is interacting with it (ie. clicking on it)
|
||||
bool autoScroll = hasAutoScroll();
|
||||
setAutoScroll(false);
|
||||
selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
|
||||
|
||||
setAutoScroll(autoScroll);
|
||||
QRect rect(geometryPos, geometryPos);
|
||||
QRect rect(visualPos, visualPos);
|
||||
setSelection(rect, QItemSelectionModel::ClearAndSelect);
|
||||
|
||||
// signal handlers may change the model
|
||||
@@ -359,7 +307,7 @@ void GroupView::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
setState(DragSelectingState);
|
||||
|
||||
setSelection(QRect(geometryPos, geometryPos), QItemSelectionModel::ClearAndSelect);
|
||||
setSelection(QRect(visualPos, visualPos), QItemSelectionModel::ClearAndSelect);
|
||||
QModelIndex index = indexAt(visualPos);
|
||||
|
||||
// set at the end because it might scroll the view
|
||||
@@ -452,7 +400,7 @@ void GroupView::paintEvent(QPaintEvent *event)
|
||||
option.rect.setWidth(wpWidth);
|
||||
for (int i = 0; i < m_groups.size(); ++i)
|
||||
{
|
||||
Group *category = m_groups.at(i);
|
||||
VisualGroup *category = m_groups.at(i);
|
||||
int y = category->verticalPosition();
|
||||
y -= verticalOffset();
|
||||
QRect backup = option.rect;
|
||||
@@ -528,16 +476,13 @@ void GroupView::paintEvent(QPaintEvent *event)
|
||||
|
||||
void GroupView::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
// QListView::resizeEvent(event);
|
||||
|
||||
// if (m_categoryEditor)
|
||||
// {
|
||||
// m_categoryEditor->resize(qMax(contentWidth() / 2,
|
||||
// m_editedCategory->textRect.width()),
|
||||
// m_categoryEditor->height());
|
||||
// }
|
||||
|
||||
updateGeometries();
|
||||
int newItemsPerRow = calculateItemsPerRow();
|
||||
if(newItemsPerRow != m_currentItemsPerRow)
|
||||
{
|
||||
m_currentCursorColumn = -1;
|
||||
m_currentItemsPerRow = newItemsPerRow;
|
||||
updateGeometries();
|
||||
}
|
||||
}
|
||||
|
||||
void GroupView::dragEnterEvent(QDragEnterEvent *event)
|
||||
@@ -580,8 +525,8 @@ void GroupView::dropEvent(QDropEvent *event)
|
||||
return;
|
||||
}
|
||||
|
||||
QPair<Group *, int> dropPos = rowDropPos(event->pos() + offset());
|
||||
const Group *category = dropPos.first;
|
||||
QPair<VisualGroup *, int> dropPos = rowDropPos(event->pos() + offset());
|
||||
const VisualGroup *category = dropPos.first;
|
||||
const int row = dropPos.second;
|
||||
|
||||
if (row == -1)
|
||||
@@ -605,44 +550,44 @@ void GroupView::dropEvent(QDropEvent *event)
|
||||
void GroupView::startDrag(Qt::DropActions supportedActions)
|
||||
{
|
||||
QModelIndexList indexes = selectionModel()->selectedIndexes();
|
||||
if (indexes.count() > 0)
|
||||
{
|
||||
QMimeData *data = model()->mimeData(indexes);
|
||||
if (!data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
QRect rect;
|
||||
QPixmap pixmap = renderToPixmap(indexes, &rect);
|
||||
//rect.translate(offset());
|
||||
// rect.adjust(horizontalOffset(), verticalOffset(), 0, 0);
|
||||
QDrag *drag = new QDrag(this);
|
||||
drag->setPixmap(pixmap);
|
||||
drag->setMimeData(data);
|
||||
Qt::DropAction defaultDropAction = Qt::IgnoreAction;
|
||||
if (this->defaultDropAction() != Qt::IgnoreAction &&
|
||||
(supportedActions & this->defaultDropAction()))
|
||||
{
|
||||
defaultDropAction = this->defaultDropAction();
|
||||
}
|
||||
if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction)
|
||||
{
|
||||
const QItemSelection selection = selectionModel()->selection();
|
||||
if(indexes.count() == 0)
|
||||
return;
|
||||
|
||||
for (auto it = selection.constBegin(); it != selection.constEnd(); ++it)
|
||||
QMimeData *data = model()->mimeData(indexes);
|
||||
if (!data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
QRect rect;
|
||||
QPixmap pixmap = renderToPixmap(indexes, &rect);
|
||||
//rect.translate(offset());
|
||||
// rect.adjust(horizontalOffset(), verticalOffset(), 0, 0);
|
||||
QDrag *drag = new QDrag(this);
|
||||
drag->setPixmap(pixmap);
|
||||
drag->setMimeData(data);
|
||||
Qt::DropAction defaultDropAction = Qt::IgnoreAction;
|
||||
if (this->defaultDropAction() != Qt::IgnoreAction &&
|
||||
(supportedActions & this->defaultDropAction()))
|
||||
{
|
||||
defaultDropAction = this->defaultDropAction();
|
||||
}
|
||||
if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction)
|
||||
{
|
||||
const QItemSelection selection = selectionModel()->selection();
|
||||
|
||||
for (auto it = selection.constBegin(); it != selection.constEnd(); ++it)
|
||||
{
|
||||
QModelIndex parent = (*it).parent();
|
||||
if ((*it).left() != 0)
|
||||
{
|
||||
QModelIndex parent = (*it).parent();
|
||||
if ((*it).left() != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ((*it).right() != (model()->columnCount(parent) - 1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int count = (*it).bottom() - (*it).top() + 1;
|
||||
model()->removeRows((*it).top(), count, parent);
|
||||
continue;
|
||||
}
|
||||
if ((*it).right() != (model()->columnCount(parent) - 1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int count = (*it).bottom() - (*it).top() + 1;
|
||||
model()->removeRows((*it).top(), count, parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -659,58 +604,25 @@ QRect GroupView::geometryRect(const QModelIndex &index) const
|
||||
return QRect();
|
||||
}
|
||||
|
||||
const Group *cat = category(index);
|
||||
QPair<int, int> pos = categoryInternalPosition(index);
|
||||
int row = index.row();
|
||||
if(geometryCache.contains(row))
|
||||
{
|
||||
return *geometryCache[row];
|
||||
}
|
||||
|
||||
const VisualGroup *cat = category(index);
|
||||
QPair<int, int> pos = cat->positionOf(index);
|
||||
int x = pos.first;
|
||||
// int y = pos.second;
|
||||
|
||||
QRect out;
|
||||
out.setTop(cat->verticalPosition() + cat->headerHeight() + 5 + categoryInternalRowTop(index));
|
||||
out.setTop(cat->verticalPosition() + cat->headerHeight() + 5 + cat->rowTopOf(index));
|
||||
out.setLeft(m_spacing + x * (itemWidth() + m_spacing));
|
||||
out.setSize(itemDelegate()->sizeHint(viewOptions(), index));
|
||||
|
||||
geometryCache.insert(row, new QRect(out));
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
void CategorizedView::startCategoryEditor(Category *category)
|
||||
{
|
||||
if (m_categoryEditor != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_editedCategory = category;
|
||||
m_categoryEditor = new QLineEdit(m_editedCategory->text, this);
|
||||
QRect rect = m_editedCategory->textRect;
|
||||
rect.setWidth(qMax(contentWidth() / 2, rect.width()));
|
||||
m_categoryEditor->setGeometry(rect);
|
||||
m_categoryEditor->show();
|
||||
m_categoryEditor->setFocus();
|
||||
connect(m_categoryEditor, &QLineEdit::returnPressed, this,
|
||||
&CategorizedView::endCategoryEditor);
|
||||
}
|
||||
|
||||
void CategorizedView::endCategoryEditor()
|
||||
{
|
||||
if (m_categoryEditor == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_editedCategory->text = m_categoryEditor->text();
|
||||
m_updatesDisabled = true;
|
||||
foreach (const QModelIndex &index, itemsForCategory(m_editedCategory))
|
||||
{
|
||||
const_cast<QAbstractItemModel *>(index.model())->setData(index,
|
||||
m_categoryEditor->text(), CategoryRole);
|
||||
}
|
||||
m_updatesDisabled = false;
|
||||
delete m_categoryEditor;
|
||||
m_categoryEditor = 0;
|
||||
m_editedCategory = 0;
|
||||
updateGeometries();
|
||||
}
|
||||
*/
|
||||
|
||||
QModelIndex GroupView::indexAt(const QPoint &point) const
|
||||
{
|
||||
for (int i = 0; i < model()->rowCount(); ++i)
|
||||
@@ -724,21 +636,19 @@ QModelIndex GroupView::indexAt(const QPoint &point) const
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
// FIXME: is rect supposed to be geometry or visual coords?
|
||||
void GroupView::setSelection(const QRect &rect,
|
||||
const QItemSelectionModel::SelectionFlags commands)
|
||||
{
|
||||
for (int i = 0; i < model()->rowCount(); ++i)
|
||||
{
|
||||
QModelIndex index = model()->index(i, 0);
|
||||
QRect itemRect = geometryRect(index);
|
||||
QRect itemRect = visualRect(index);
|
||||
if (itemRect.intersects(rect))
|
||||
{
|
||||
selectionModel()->select(index, commands);
|
||||
update(itemRect.translated(-offset()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QPixmap GroupView::renderToPixmap(const QModelIndexList &indices, QRect *r) const
|
||||
@@ -781,33 +691,23 @@ QList<QPair<QRect, QModelIndex>> GroupView::draggablePaintPairs(const QModelInde
|
||||
|
||||
bool GroupView::isDragEventAccepted(QDropEvent *event)
|
||||
{
|
||||
if (event->source() != this)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!listsIntersect(event->mimeData()->formats(), model()->mimeTypes()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!model()->canDropMimeData(event->mimeData(), event->dropAction(),
|
||||
rowDropPos(event->pos()).second, 0, QModelIndex()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
QPair<Group *, int> GroupView::rowDropPos(const QPoint &pos)
|
||||
QPair<VisualGroup *, int> GroupView::rowDropPos(const QPoint &pos)
|
||||
{
|
||||
return qMakePair<VisualGroup*, int>(nullptr, -1);
|
||||
// FIXME: PIXIE DUST.
|
||||
/*
|
||||
// check that we aren't on a category header and calculate which category we're in
|
||||
Group *category = 0;
|
||||
VisualGroup *category = 0;
|
||||
{
|
||||
int y = 0;
|
||||
for (auto cat : m_groups)
|
||||
{
|
||||
if (pos.y() > y && pos.y() < (y + cat->headerHeight()))
|
||||
{
|
||||
return qMakePair<Group*, int>(nullptr, -1);
|
||||
return qMakePair<VisualGroup*, int>(nullptr, -1);
|
||||
}
|
||||
y += cat->totalHeight() + m_categoryMargin;
|
||||
if (pos.y() < y)
|
||||
@@ -818,7 +718,7 @@ QPair<Group *, int> GroupView::rowDropPos(const QPoint &pos)
|
||||
}
|
||||
if (category == 0)
|
||||
{
|
||||
return qMakePair<Group*, int>(nullptr, -1);
|
||||
return qMakePair<VisualGroup*, int>(nullptr, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -834,7 +734,7 @@ QPair<Group *, int> GroupView::rowDropPos(const QPoint &pos)
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0, c = 0; i < contentWidth(); i += itemWidth + 10 /*spacing()*/, ++c)
|
||||
for (int i = 0, c = 0; i < contentWidth(); i += itemWidth + 10 , ++c)
|
||||
{
|
||||
if (pos.x() > (i - itemWidth / 2) && pos.x() <= (i + itemWidth / 2))
|
||||
{
|
||||
@@ -845,7 +745,7 @@ QPair<Group *, int> GroupView::rowDropPos(const QPoint &pos)
|
||||
}
|
||||
if (internalColumn == -1)
|
||||
{
|
||||
return qMakePair<Group*, int>(nullptr, -1);
|
||||
return qMakePair<VisualGroup*, int>(nullptr, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -865,13 +765,13 @@ QPair<Group *, int> GroupView::rowDropPos(const QPoint &pos)
|
||||
}
|
||||
if (internalRow == -1)
|
||||
{
|
||||
return qMakePair<Group*, int>(nullptr, -1);
|
||||
return qMakePair<VisualGroup*, int>(nullptr, -1);
|
||||
}
|
||||
// this happens if we're in the margin between a one category and another
|
||||
// categories header
|
||||
if (internalRow > (indices.size() / itemsPerRow()))
|
||||
{
|
||||
return qMakePair<Group*, int>(nullptr, -1);
|
||||
return qMakePair<VisualGroup*, int>(nullptr, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -885,6 +785,7 @@ QPair<Group *, int> GroupView::rowDropPos(const QPoint &pos)
|
||||
}
|
||||
|
||||
return qMakePair(category, indices.at(categoryRow).row());
|
||||
*/
|
||||
}
|
||||
|
||||
QPoint GroupView::offset() const
|
||||
@@ -912,34 +813,191 @@ QRegion GroupView::visualRegionForSelection(const QItemSelection &selection) con
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
QModelIndex GroupView::moveCursor(QAbstractItemView::CursorAction cursorAction,
|
||||
Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
auto current = currentIndex();
|
||||
if(!current.isValid())
|
||||
{
|
||||
qDebug() << "model row: invalid";
|
||||
return current;
|
||||
}
|
||||
qDebug() << "model row: " << current.row();
|
||||
auto cat = category(current);
|
||||
int i = m_groups.indexOf(cat);
|
||||
if(i >= 0)
|
||||
int group_index = m_groups.indexOf(cat);
|
||||
if(group_index < 0)
|
||||
return current;
|
||||
|
||||
auto real_group = m_groups[group_index];
|
||||
int beginning_row = 0;
|
||||
for(auto group: m_groups)
|
||||
{
|
||||
// this is a pile of something foul
|
||||
auto real_group = m_groups[i];
|
||||
int beginning_row = 0;
|
||||
for(auto group: m_groups)
|
||||
if(group == real_group)
|
||||
break;
|
||||
beginning_row += group->numRows();
|
||||
}
|
||||
|
||||
QPair<int, int> pos = cat->positionOf(current);
|
||||
int column = pos.first;
|
||||
int row = pos.second;
|
||||
if(m_currentCursorColumn < 0)
|
||||
{
|
||||
m_currentCursorColumn = column;
|
||||
}
|
||||
switch(cursorAction)
|
||||
{
|
||||
case MoveUp:
|
||||
{
|
||||
if(group == real_group)
|
||||
break;
|
||||
beginning_row += group->numRows();
|
||||
if(row == 0)
|
||||
{
|
||||
int prevgroupindex = group_index-1;
|
||||
while(prevgroupindex >= 0)
|
||||
{
|
||||
auto prevgroup = m_groups[prevgroupindex];
|
||||
if(prevgroup->collapsed)
|
||||
{
|
||||
prevgroupindex--;
|
||||
continue;
|
||||
}
|
||||
int newRow = prevgroup->numRows() - 1;
|
||||
int newRowSize = prevgroup->rows[newRow].size();
|
||||
int newColumn = m_currentCursorColumn;
|
||||
if (m_currentCursorColumn >= newRowSize)
|
||||
{
|
||||
newColumn = newRowSize - 1;
|
||||
}
|
||||
return prevgroup->rows[newRow][newColumn];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int newRow = row - 1;
|
||||
int newRowSize = cat->rows[newRow].size();
|
||||
int newColumn = m_currentCursorColumn;
|
||||
if (m_currentCursorColumn >= newRowSize)
|
||||
{
|
||||
newColumn = newRowSize - 1;
|
||||
}
|
||||
return cat->rows[newRow][newColumn];
|
||||
}
|
||||
return current;
|
||||
}
|
||||
qDebug() << "category: " << real_group->text;
|
||||
QPair<int, int> pos = categoryInternalPosition(current);
|
||||
int row = beginning_row + pos.second;
|
||||
qDebug() << "row: " << row;
|
||||
qDebug() << "column: " << pos.first;
|
||||
case MoveDown:
|
||||
{
|
||||
if(row == cat->rows.size() - 1)
|
||||
{
|
||||
int nextgroupindex = group_index+1;
|
||||
while (nextgroupindex < m_groups.size())
|
||||
{
|
||||
auto nextgroup = m_groups[nextgroupindex];
|
||||
if(nextgroup->collapsed)
|
||||
{
|
||||
nextgroupindex++;
|
||||
continue;
|
||||
}
|
||||
int newRowSize = nextgroup->rows[0].size();
|
||||
int newColumn = m_currentCursorColumn;
|
||||
if (m_currentCursorColumn >= newRowSize)
|
||||
{
|
||||
newColumn = newRowSize - 1;
|
||||
}
|
||||
return nextgroup->rows[0][newColumn];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int newRow = row + 1;
|
||||
int newRowSize = cat->rows[newRow].size();
|
||||
int newColumn = m_currentCursorColumn;
|
||||
if (m_currentCursorColumn >= newRowSize)
|
||||
{
|
||||
newColumn = newRowSize - 1;
|
||||
}
|
||||
return cat->rows[newRow][newColumn];
|
||||
}
|
||||
return current;
|
||||
}
|
||||
case MoveLeft:
|
||||
{
|
||||
if(column > 0)
|
||||
{
|
||||
m_currentCursorColumn = column - 1;
|
||||
return cat->rows[row][column - 1];
|
||||
}
|
||||
// TODO: moving to previous line
|
||||
return current;
|
||||
}
|
||||
case MoveRight:
|
||||
{
|
||||
if(column < cat->rows[row].size() - 1)
|
||||
{
|
||||
m_currentCursorColumn = column + 1;
|
||||
return cat->rows[row][column + 1];
|
||||
}
|
||||
// TODO: moving to next line
|
||||
return current;
|
||||
}
|
||||
case MoveHome:
|
||||
{
|
||||
m_currentCursorColumn = 0;
|
||||
return cat->rows[row][0];
|
||||
}
|
||||
case MoveEnd:
|
||||
{
|
||||
auto last = cat->rows[row].size() - 1;
|
||||
m_currentCursorColumn = last;
|
||||
return cat->rows[row][last];
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
int GroupView::horizontalOffset() const
|
||||
{
|
||||
return horizontalScrollBar()->value();
|
||||
}
|
||||
|
||||
int GroupView::verticalOffset() const
|
||||
{
|
||||
return verticalScrollBar()->value();
|
||||
}
|
||||
|
||||
void GroupView::scrollContentsBy(int dx, int dy)
|
||||
{
|
||||
scrollDirtyRegion(dx, dy);
|
||||
viewport()->scroll(dx, dy);
|
||||
}
|
||||
|
||||
void GroupView::scrollTo(const QModelIndex &index, ScrollHint hint)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
const QRect rect = visualRect(index);
|
||||
if (hint == EnsureVisible && viewport()->rect().contains(rect))
|
||||
{
|
||||
viewport()->update(rect);
|
||||
return;
|
||||
}
|
||||
|
||||
verticalScrollBar()->setValue(verticalScrollToValue(index, rect, hint));
|
||||
}
|
||||
|
||||
int GroupView::verticalScrollToValue(const QModelIndex &index, const QRect &rect,
|
||||
QListView::ScrollHint hint) const
|
||||
{
|
||||
const QRect area = viewport()->rect();
|
||||
const bool above = (hint == QListView::EnsureVisible && rect.top() < area.top());
|
||||
const bool below = (hint == QListView::EnsureVisible && rect.bottom() > area.bottom());
|
||||
|
||||
int verticalValue = verticalScrollBar()->value();
|
||||
QRect adjusted = rect.adjusted(-spacing(), -spacing(), spacing(), spacing());
|
||||
if (hint == QListView::PositionAtTop || above)
|
||||
verticalValue += adjusted.top();
|
||||
else if (hint == QListView::PositionAtBottom || below)
|
||||
verticalValue += qMin(adjusted.top(), adjusted.bottom() - area.height() + 1);
|
||||
else if (hint == QListView::PositionAtCenter)
|
||||
verticalValue += adjusted.top() - ((area.height() - adjusted.height()) / 2);
|
||||
return verticalValue;
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <QListView>
|
||||
#include <QLineEdit>
|
||||
#include <QScrollBar>
|
||||
#include <QCache>
|
||||
|
||||
struct GroupViewRoles
|
||||
{
|
||||
@@ -14,7 +15,7 @@ struct GroupViewRoles
|
||||
};
|
||||
};
|
||||
|
||||
struct Group;
|
||||
struct VisualGroup;
|
||||
|
||||
class GroupView : public QAbstractItemView
|
||||
{
|
||||
@@ -35,35 +36,20 @@ public:
|
||||
void setSelection(const QRect &rect,
|
||||
const QItemSelectionModel::SelectionFlags commands) override;
|
||||
|
||||
virtual int horizontalOffset() const override
|
||||
{
|
||||
return horizontalScrollBar()->value();
|
||||
}
|
||||
|
||||
virtual int verticalOffset() const override
|
||||
{
|
||||
return verticalScrollBar()->value();
|
||||
}
|
||||
|
||||
virtual void scrollContentsBy(int dx, int dy) override
|
||||
{
|
||||
scrollDirtyRegion(dx, dy);
|
||||
viewport()->scroll(dx, dy);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO!
|
||||
*/
|
||||
virtual void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override
|
||||
{
|
||||
return;
|
||||
}
|
||||
virtual int horizontalOffset() const override;
|
||||
virtual int verticalOffset() const override;
|
||||
virtual void scrollContentsBy(int dx, int dy) override;
|
||||
virtual void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override;
|
||||
|
||||
virtual QModelIndex moveCursor(CursorAction cursorAction,
|
||||
Qt::KeyboardModifiers modifiers) override;
|
||||
|
||||
virtual QRegion visualRegionForSelection(const QItemSelection &selection) const override;
|
||||
|
||||
int spacing() const
|
||||
{
|
||||
return m_spacing;
|
||||
};
|
||||
protected
|
||||
slots:
|
||||
virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
||||
@@ -90,57 +76,50 @@ protected:
|
||||
void startDrag(Qt::DropActions supportedActions) override;
|
||||
|
||||
private:
|
||||
friend struct Group;
|
||||
friend struct VisualGroup;
|
||||
QList<VisualGroup *> m_groups;
|
||||
|
||||
QList<Group *> m_groups;
|
||||
// geometry
|
||||
int m_leftMargin = 5;
|
||||
int m_rightMargin = 5;
|
||||
int m_bottomMargin = 5;
|
||||
int m_categoryMargin = 5;
|
||||
int m_spacing = 5;
|
||||
int m_itemWidth = 100;
|
||||
int m_currentItemsPerRow = -1;
|
||||
int m_currentCursorColumn= -1;
|
||||
mutable QCache<int, QRect> geometryCache;
|
||||
|
||||
int m_leftMargin;
|
||||
int m_rightMargin;
|
||||
int m_bottomMargin;
|
||||
int m_categoryMargin;
|
||||
|
||||
// bool m_updatesDisabled;
|
||||
|
||||
Group *category(const QModelIndex &index) const;
|
||||
Group *category(const QString &cat) const;
|
||||
Group *categoryAt(const QPoint &pos) const;
|
||||
|
||||
int itemsPerRow() const;
|
||||
int contentWidth() const;
|
||||
|
||||
private:
|
||||
int itemWidth() const;
|
||||
int categoryRowHeight(const QModelIndex &index) const;
|
||||
|
||||
/*QLineEdit *m_categoryEditor;
|
||||
Category *m_editedCategory;
|
||||
void startCategoryEditor(Category *category);
|
||||
|
||||
private slots:
|
||||
void endCategoryEditor();*/
|
||||
|
||||
private: /* variables */
|
||||
/// point where the currently active mouse action started in geometry coordinates
|
||||
// point where the currently active mouse action started in geometry coordinates
|
||||
QPoint m_pressedPosition;
|
||||
QPersistentModelIndex m_pressedIndex;
|
||||
bool m_pressedAlreadySelected;
|
||||
Group *m_pressedCategory;
|
||||
VisualGroup *m_pressedCategory;
|
||||
QItemSelectionModel::SelectionFlag m_ctrlDragSelectionFlag;
|
||||
QPoint m_lastDragPosition;
|
||||
int m_spacing = 5;
|
||||
|
||||
VisualGroup *category(const QModelIndex &index) const;
|
||||
VisualGroup *category(const QString &cat) const;
|
||||
VisualGroup *categoryAt(const QPoint &pos) const;
|
||||
|
||||
int itemsPerRow() const
|
||||
{
|
||||
return m_currentItemsPerRow;
|
||||
};
|
||||
int contentWidth() const;
|
||||
|
||||
private: /* methods */
|
||||
QPair<int, int> categoryInternalPosition(const QModelIndex &index) const;
|
||||
int categoryInternalRowTop(const QModelIndex &index) const;
|
||||
int itemHeightForCategoryRow(const Group *category, const int internalRow) const;
|
||||
|
||||
int itemWidth() const;
|
||||
int calculateItemsPerRow() const;
|
||||
int verticalScrollToValue(const QModelIndex &index, const QRect &rect,
|
||||
QListView::ScrollHint hint) const;
|
||||
QPixmap renderToPixmap(const QModelIndexList &indices, QRect *r) const;
|
||||
QList<QPair<QRect, QModelIndex>> draggablePaintPairs(const QModelIndexList &indices,
|
||||
QRect *r) const;
|
||||
|
||||
bool isDragEventAccepted(QDropEvent *event);
|
||||
|
||||
QPair<Group *, int> rowDropPos(const QPoint &pos);
|
||||
QPair<VisualGroup *, int> rowDropPos(const QPoint &pos);
|
||||
|
||||
QPoint offset() const;
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "GroupedProxyModel.h"
|
||||
|
||||
#include "GroupView.h"
|
||||
#include <QDebug>
|
||||
|
||||
GroupedProxyModel::GroupedProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
@@ -16,7 +17,13 @@ bool GroupedProxyModel::lessThan(const QModelIndex &left, const QModelIndex &rig
|
||||
}
|
||||
else
|
||||
{
|
||||
return leftCategory < rightCategory;
|
||||
// FIXME: real group sorting happens in GroupView::updateGeometries(), see LocaleString
|
||||
auto result = leftCategory.localeAwareCompare(rightCategory);
|
||||
if(result == 0)
|
||||
{
|
||||
return subSortLessThan(left, right);
|
||||
}
|
||||
return result < 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,8 +21,8 @@
|
||||
#include <QtMath>
|
||||
|
||||
#include "GroupView.h"
|
||||
#include "logic/BaseInstance.h"
|
||||
#include "logic/lists/InstanceList.h"
|
||||
#include "BaseInstance.h"
|
||||
#include "InstanceList.h"
|
||||
|
||||
QCache<QString, QPixmap> ListViewDelegate::m_pixmapCache;
|
||||
|
||||
@@ -113,14 +113,14 @@ void drawProgressOverlay(QPainter *painter, const QStyleOptionViewItemV4 &option
|
||||
void drawBadges(QPainter *painter, const QStyleOptionViewItemV4 &option, BaseInstance *instance)
|
||||
{
|
||||
QList<QString> pixmaps;
|
||||
for (auto flag : instance->flags())
|
||||
const BaseInstance::InstanceFlags flags = instance->flags();
|
||||
if (flags & BaseInstance::VersionBrokenFlag)
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
case BaseInstance::VersionBrokenFlag:
|
||||
pixmaps.append("broken");
|
||||
break;
|
||||
}
|
||||
pixmaps.append("broken");
|
||||
}
|
||||
if (flags & BaseInstance::UpdateAvailable)
|
||||
{
|
||||
pixmaps.append("updateavailable");
|
||||
}
|
||||
|
||||
// begin easter eggs
|
||||
@@ -158,7 +158,7 @@ void drawBadges(QPainter *painter, const QStyleOptionViewItemV4 &option, BaseIns
|
||||
{
|
||||
return;
|
||||
}
|
||||
const QPixmap pixmap = ListViewDelegate::requestPixmap(it.next()).scaled(
|
||||
const QPixmap pixmap = ListViewDelegate::requestBadgePixmap(it.next()).scaled(
|
||||
itemSide, itemSide, Qt::KeepAspectRatio, Qt::FastTransformation);
|
||||
painter->drawPixmap(option.rect.width() - x * itemSide + qMax(x - 1, 0) * spacing - itemSide,
|
||||
y * itemSide + qMax(y - 1, 0) * spacing, itemSide, itemSide,
|
||||
@@ -352,7 +352,7 @@ QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem &option,
|
||||
return sz;
|
||||
}
|
||||
|
||||
QPixmap ListViewDelegate::requestPixmap(const QString &key)
|
||||
QPixmap ListViewDelegate::requestBadgePixmap(const QString &key)
|
||||
{
|
||||
if (!m_pixmapCache.contains(key))
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,7 +23,7 @@ class ListViewDelegate : public QStyledItemDelegate
|
||||
public:
|
||||
explicit ListViewDelegate(QObject *parent = 0);
|
||||
|
||||
static QPixmap requestPixmap(const QString &key);
|
||||
static QPixmap requestBadgePixmap(const QString &key);
|
||||
|
||||
protected:
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "Group.h"
|
||||
#include "VisualGroup.h"
|
||||
|
||||
#include <QModelIndex>
|
||||
#include <QPainter>
|
||||
@@ -7,30 +7,83 @@
|
||||
|
||||
#include "GroupView.h"
|
||||
|
||||
Group::Group(const QString &text, GroupView *view) : view(view), text(text), collapsed(false)
|
||||
VisualGroup::VisualGroup(const QString &text, GroupView *view) : view(view), text(text), collapsed(false)
|
||||
{
|
||||
}
|
||||
|
||||
Group::Group(const Group *other)
|
||||
VisualGroup::VisualGroup(const VisualGroup *other)
|
||||
: view(other->view), text(other->text), collapsed(other->collapsed)
|
||||
{
|
||||
}
|
||||
|
||||
void Group::update()
|
||||
void VisualGroup::update()
|
||||
{
|
||||
firstItemIndex = firstItem().row();
|
||||
auto temp_items = items();
|
||||
auto itemsPerRow = view->itemsPerRow();
|
||||
|
||||
rowHeights = QVector<int>(numRows());
|
||||
for (int i = 0; i < numRows(); ++i)
|
||||
int numRows = qMax(1, qCeil((qreal)temp_items.size() / (qreal)itemsPerRow));
|
||||
rows = QVector<VisualRow>(numRows);
|
||||
|
||||
int maxRowHeight = 0;
|
||||
int positionInRow = 0;
|
||||
int currentRow = 0;
|
||||
int offsetFromTop = 0;
|
||||
for (auto item: temp_items)
|
||||
{
|
||||
rowHeights[i] = view->categoryRowHeight(
|
||||
view->model()->index(i * view->itemsPerRow() + firstItemIndex, 0));
|
||||
if(positionInRow == itemsPerRow)
|
||||
{
|
||||
rows[currentRow].height = maxRowHeight;
|
||||
rows[currentRow].top = offsetFromTop;
|
||||
currentRow ++;
|
||||
offsetFromTop += maxRowHeight + 5;
|
||||
positionInRow = 0;
|
||||
maxRowHeight = 0;
|
||||
}
|
||||
auto itemHeight = view->itemDelegate()->sizeHint(view->viewOptions(), item).height();
|
||||
if(itemHeight > maxRowHeight)
|
||||
{
|
||||
maxRowHeight = itemHeight;
|
||||
}
|
||||
rows[currentRow].items.append(item);
|
||||
positionInRow++;
|
||||
}
|
||||
rows[currentRow].height = maxRowHeight;
|
||||
rows[currentRow].top = offsetFromTop;
|
||||
}
|
||||
|
||||
Group::HitResults Group::hitScan(const QPoint &pos) const
|
||||
QPair<int, int> VisualGroup::positionOf(const QModelIndex &index) const
|
||||
{
|
||||
Group::HitResults results = Group::NoHit;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
for (auto & row: rows)
|
||||
{
|
||||
for(auto x = 0; x < row.items.size(); x++)
|
||||
{
|
||||
if(row.items[x] == index)
|
||||
{
|
||||
return qMakePair(x,y);
|
||||
}
|
||||
}
|
||||
y++;
|
||||
}
|
||||
return qMakePair(x, y);
|
||||
}
|
||||
|
||||
int VisualGroup::rowTopOf(const QModelIndex &index) const
|
||||
{
|
||||
auto position = positionOf(index);
|
||||
return rows[position.second].top;
|
||||
}
|
||||
|
||||
int VisualGroup::rowHeightOf(const QModelIndex &index) const
|
||||
{
|
||||
auto position = positionOf(index);
|
||||
return rows[position.second].height;
|
||||
}
|
||||
|
||||
VisualGroup::HitResults VisualGroup::hitScan(const QPoint &pos) const
|
||||
{
|
||||
VisualGroup::HitResults results = VisualGroup::NoHit;
|
||||
int y_start = verticalPosition();
|
||||
int body_start = y_start + headerHeight();
|
||||
int body_end = body_start + contentHeight() + 5; // FIXME: wtf is this 5?
|
||||
@@ -38,28 +91,28 @@ Group::HitResults Group::hitScan(const QPoint &pos) const
|
||||
// int x = pos.x();
|
||||
if (y < y_start)
|
||||
{
|
||||
results = Group::NoHit;
|
||||
results = VisualGroup::NoHit;
|
||||
}
|
||||
else if (y < body_start)
|
||||
{
|
||||
results = Group::HeaderHit;
|
||||
results = VisualGroup::HeaderHit;
|
||||
int collapseSize = headerHeight() - 4;
|
||||
|
||||
// the icon
|
||||
QRect iconRect = QRect(view->m_leftMargin + 2, 2 + y_start, collapseSize, collapseSize);
|
||||
if (iconRect.contains(pos))
|
||||
{
|
||||
results |= Group::CheckboxHit;
|
||||
results |= VisualGroup::CheckboxHit;
|
||||
}
|
||||
}
|
||||
else if (y < body_end)
|
||||
{
|
||||
results |= Group::BodyHit;
|
||||
results |= VisualGroup::BodyHit;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
void Group::drawHeader(QPainter *painter, const QStyleOptionViewItem &option)
|
||||
void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &option)
|
||||
{
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
@@ -190,12 +243,12 @@ void Group::drawHeader(QPainter *painter, const QStyleOptionViewItem &option)
|
||||
//END: text
|
||||
}
|
||||
|
||||
int Group::totalHeight() const
|
||||
int VisualGroup::totalHeight() const
|
||||
{
|
||||
return headerHeight() + 5 + contentHeight(); // FIXME: wtf is that '5'?
|
||||
}
|
||||
|
||||
int Group::headerHeight() const
|
||||
int VisualGroup::headerHeight() const
|
||||
{
|
||||
QFont font(QApplication::font());
|
||||
font.setBold(true);
|
||||
@@ -213,31 +266,27 @@ int Group::headerHeight() const
|
||||
*/
|
||||
}
|
||||
|
||||
int Group::contentHeight() const
|
||||
int VisualGroup::contentHeight() const
|
||||
{
|
||||
if (collapsed)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int result = 0;
|
||||
for (int i = 0; i < rowHeights.size(); ++i)
|
||||
{
|
||||
result += rowHeights[i];
|
||||
}
|
||||
return result;
|
||||
auto last = rows[numRows() - 1];
|
||||
return last.top + last.height;
|
||||
}
|
||||
|
||||
int Group::numRows() const
|
||||
int VisualGroup::numRows() const
|
||||
{
|
||||
return qMax(1, qCeil((qreal)numItems() / (qreal)view->itemsPerRow()));
|
||||
return rows.size();
|
||||
}
|
||||
|
||||
int Group::verticalPosition() const
|
||||
int VisualGroup::verticalPosition() const
|
||||
{
|
||||
return m_verticalPosition;
|
||||
}
|
||||
|
||||
QList<QModelIndex> Group::items() const
|
||||
QList<QModelIndex> VisualGroup::items() const
|
||||
{
|
||||
QList<QModelIndex> indices;
|
||||
for (int i = 0; i < view->model()->rowCount(); ++i)
|
||||
@@ -250,20 +299,3 @@ QList<QModelIndex> Group::items() const
|
||||
}
|
||||
return indices;
|
||||
}
|
||||
|
||||
int Group::numItems() const
|
||||
{
|
||||
return items().size();
|
||||
}
|
||||
|
||||
QModelIndex Group::firstItem() const
|
||||
{
|
||||
QList<QModelIndex> indices = items();
|
||||
return indices.isEmpty() ? QModelIndex() : indices.first();
|
||||
}
|
||||
|
||||
QModelIndex Group::lastItem() const
|
||||
{
|
||||
QList<QModelIndex> indices = items();
|
||||
return indices.isEmpty() ? QModelIndex() : indices.last();
|
||||
}
|
||||
@@ -9,22 +9,37 @@ class GroupView;
|
||||
class QPainter;
|
||||
class QModelIndex;
|
||||
|
||||
struct Group
|
||||
struct VisualRow
|
||||
{
|
||||
QList<QModelIndex> items;
|
||||
int height = 0;
|
||||
int top = 0;
|
||||
inline int size() const
|
||||
{
|
||||
return items.size();
|
||||
}
|
||||
inline QModelIndex &operator[](int i)
|
||||
{
|
||||
return items[i];
|
||||
}
|
||||
};
|
||||
|
||||
struct VisualGroup
|
||||
{
|
||||
/* constructors */
|
||||
Group(const QString &text, GroupView *view);
|
||||
Group(const Group *other);
|
||||
VisualGroup(const QString &text, GroupView *view);
|
||||
VisualGroup(const VisualGroup *other);
|
||||
|
||||
/* data */
|
||||
GroupView *view = nullptr;
|
||||
QString text;
|
||||
bool collapsed = false;
|
||||
QVector<int> rowHeights;
|
||||
QVector<VisualRow> rows;
|
||||
int firstItemIndex = 0;
|
||||
int m_verticalPosition = 0;
|
||||
|
||||
/* logic */
|
||||
/// do stuff. and things. TODO: redo.
|
||||
/// update the internal list of items and flow them into the rows.
|
||||
void update();
|
||||
|
||||
/// draw the header at y-position.
|
||||
@@ -42,9 +57,21 @@ struct Group
|
||||
/// the number of visual rows this group has
|
||||
int numRows() const;
|
||||
|
||||
/// actually calculate the above value
|
||||
int calculateNumRows() const;
|
||||
|
||||
/// the height at which this group starts, in pixels
|
||||
int verticalPosition() const;
|
||||
|
||||
/// relative geometry - top of the row of the given item
|
||||
int rowTopOf(const QModelIndex &index) const;
|
||||
|
||||
/// height of the row of the given item
|
||||
int rowHeightOf(const QModelIndex &index) const;
|
||||
|
||||
/// x/y position of the given item inside the group (in items!)
|
||||
QPair<int, int> positionOf(const QModelIndex &index) const;
|
||||
|
||||
enum HitResult
|
||||
{
|
||||
NoHit = 0x0,
|
||||
@@ -58,12 +85,7 @@ struct Group
|
||||
/// shoot! BANG! what did we hit?
|
||||
HitResults hitScan (const QPoint &pos) const;
|
||||
|
||||
/// super derpy thing.
|
||||
QList<QModelIndex> items() const;
|
||||
/// I don't even
|
||||
int numItems() const;
|
||||
QModelIndex firstItem() const;
|
||||
QModelIndex lastItem() const;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Group::HitResults)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(VisualGroup::HitResults)
|
||||
@@ -1,16 +1,16 @@
|
||||
#include "MultiMC.h"
|
||||
#include "gui/MainWindow.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
int main_gui(MultiMC &app)
|
||||
{
|
||||
// show main window
|
||||
QIcon::setThemeName("multimc");
|
||||
app.setIconTheme(MMC->settings()->get("IconTheme").toString());
|
||||
MainWindow mainWin;
|
||||
mainWin.restoreState(QByteArray::fromBase64(MMC->settings()->get("MainWindowState").toByteArray()));
|
||||
mainWin.restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("MainWindowGeometry").toByteArray()));
|
||||
mainWin.show();
|
||||
mainWin.checkMigrateLegacyAssets();
|
||||
mainWin.checkSetDefaultJava();
|
||||
mainWin.checkInstancePathForProblems();
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
@@ -22,6 +22,14 @@ int main(int argc, char *argv[])
|
||||
Q_INIT_RESOURCE(instances);
|
||||
Q_INIT_RESOURCE(multimc);
|
||||
Q_INIT_RESOURCE(backgrounds);
|
||||
Q_INIT_RESOURCE(versions);
|
||||
|
||||
Q_INIT_RESOURCE(pe_dark);
|
||||
Q_INIT_RESOURCE(pe_light);
|
||||
Q_INIT_RESOURCE(pe_blue);
|
||||
Q_INIT_RESOURCE(pe_colored);
|
||||
Q_INIT_RESOURCE(OSX);
|
||||
Q_INIT_RESOURCE(iOS);
|
||||
|
||||
switch (app.status())
|
||||
{
|
||||
@@ -37,6 +37,10 @@ if [ "x$DEPS_LIST" = "x" ]; then
|
||||
# Run MultiMC in valgrind
|
||||
# valgrind --log-file="valgrind.log" --leak-check=full --track-origins=yes "${MMC_DIR}/bin/MultiMC" -d "${MMC_DIR}" $@
|
||||
|
||||
# Run MultiMC with callgrind, delay instrumentation
|
||||
# valgrind --log-file="valgrind.log" --tool=callgrind --instr-atstart=no "${MMC_DIR}/bin/MultiMC" -d "${MMC_DIR}" $@
|
||||
# use callgrind_control -i on/off to profile actions
|
||||
|
||||
# Exit with MultiMC's exit code.
|
||||
exit $?
|
||||
else
|
||||
62
application/pagedialog/PageDialog.cpp
Normal file
62
application/pagedialog/PageDialog.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "PageDialog.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "MultiMC.h"
|
||||
#include "settings/SettingsObject.h"
|
||||
#include "Platform.h"
|
||||
#include "widgets/IconLabel.h"
|
||||
#include "widgets/PageContainer.h"
|
||||
|
||||
PageDialog::PageDialog(BasePageProviderPtr pageProvider, QString defaultId, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
MultiMCPlatform::fixWM_CLASS(this);
|
||||
setWindowTitle(pageProvider->dialogTitle());
|
||||
m_container = new PageContainer(pageProvider, defaultId, this);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(m_container);
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(mainLayout);
|
||||
|
||||
QDialogButtonBox *buttons =
|
||||
new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Close);
|
||||
buttons->button(QDialogButtonBox::Close)->setDefault(true);
|
||||
m_container->addButtons(buttons);
|
||||
|
||||
connect(buttons->button(QDialogButtonBox::Close), SIGNAL(clicked()), this, SLOT(close()));
|
||||
connect(buttons->button(QDialogButtonBox::Help), SIGNAL(clicked()), m_container,
|
||||
SLOT(help()));
|
||||
|
||||
restoreGeometry(
|
||||
QByteArray::fromBase64(MMC->settings()->get("PagedGeometry").toByteArray()));
|
||||
}
|
||||
|
||||
void PageDialog::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if (m_container->requestClose(event))
|
||||
{
|
||||
MMC->settings()->set("PagedGeometry", saveGeometry().toBase64());
|
||||
QDialog::closeEvent(event);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,29 +16,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include "pages/BasePageProvider.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class LWJGLSelectDialog;
|
||||
}
|
||||
|
||||
class LWJGLSelectDialog : public QDialog
|
||||
class PageContainer;
|
||||
class PageDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LWJGLSelectDialog(QWidget *parent = 0);
|
||||
~LWJGLSelectDialog();
|
||||
|
||||
QString selectedVersion() const;
|
||||
explicit PageDialog(BasePageProviderPtr pageProvider, QString defaultId = QString(),
|
||||
QWidget *parent = 0);
|
||||
virtual ~PageDialog() {}
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_refreshButton_clicked();
|
||||
|
||||
void loadingStateUpdated(bool loading);
|
||||
void loadingFailed(QString error);
|
||||
virtual void closeEvent(QCloseEvent *event);
|
||||
|
||||
private:
|
||||
Ui::LWJGLSelectDialog *ui;
|
||||
PageContainer * m_container;
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013 MultiMC Contributors
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,19 +14,25 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <settingsobject.h>
|
||||
#include <QIcon>
|
||||
#include <memory>
|
||||
|
||||
#include "BaseInstance_p.h"
|
||||
#include "ModList.h"
|
||||
|
||||
class LegacyInstancePrivate : public BaseInstancePrivate
|
||||
class BasePage
|
||||
{
|
||||
public:
|
||||
virtual ~LegacyInstancePrivate() {};
|
||||
std::shared_ptr<ModList> jar_mod_list;
|
||||
std::shared_ptr<ModList> core_mod_list;
|
||||
std::shared_ptr<ModList> loader_mod_list;
|
||||
std::shared_ptr<ModList> texture_pack_list;
|
||||
virtual ~BasePage() {}
|
||||
virtual QString id() const = 0;
|
||||
virtual QString displayName() const = 0;
|
||||
virtual QIcon icon() const = 0;
|
||||
virtual bool apply() { return true; }
|
||||
virtual bool shouldDisplay() const { return true; }
|
||||
virtual QString helpPage() const { return QString(); }
|
||||
virtual void opened() {}
|
||||
virtual void closed() {}
|
||||
int stackIndex = -1;
|
||||
int listIndex = -1;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<BasePage> BasePagePtr;
|
||||
69
application/pages/BasePageProvider.h
Normal file
69
application/pages/BasePageProvider.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BasePage.h"
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
class BasePageProvider
|
||||
{
|
||||
public:
|
||||
virtual QList<BasePage *> getPages() = 0;
|
||||
virtual QString dialogTitle() = 0;
|
||||
};
|
||||
|
||||
class GenericPageProvider : public BasePageProvider
|
||||
{
|
||||
typedef std::function<BasePage *()> PageCreator;
|
||||
public:
|
||||
explicit GenericPageProvider(const QString &dialogTitle)
|
||||
: m_dialogTitle(dialogTitle)
|
||||
{
|
||||
}
|
||||
|
||||
QList<BasePage *> getPages() override
|
||||
{
|
||||
QList<BasePage *> pages;
|
||||
for (PageCreator creator : m_creators)
|
||||
{
|
||||
pages.append(creator());
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
QString dialogTitle() override { return m_dialogTitle; }
|
||||
|
||||
void setDialogTitle(const QString &title)
|
||||
{
|
||||
m_dialogTitle = title;
|
||||
}
|
||||
void addPageCreator(PageCreator page)
|
||||
{
|
||||
m_creators.append(page);
|
||||
}
|
||||
|
||||
template<typename PageClass>
|
||||
void addPage()
|
||||
{
|
||||
addPageCreator([](){return new PageClass();});
|
||||
}
|
||||
|
||||
private:
|
||||
QList<PageCreator> m_creators;
|
||||
QString m_dialogTitle;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<BasePageProvider> BasePageProviderPtr;
|
||||
205
application/pages/InstanceSettingsPage.cpp
Normal file
205
application/pages/InstanceSettingsPage.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
#include "InstanceSettingsPage.h"
|
||||
#include "ui_InstanceSettingsPage.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "dialogs/VersionSelectDialog.h"
|
||||
#include "JavaCommon.h"
|
||||
#include "MultiMC.h"
|
||||
|
||||
#include <java/JavaVersionList.h>
|
||||
|
||||
InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::InstanceSettingsPage), m_instance(inst)
|
||||
{
|
||||
m_settings = &(inst->settings());
|
||||
ui->setupUi(this);
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
bool InstanceSettingsPage::shouldDisplay() const
|
||||
{
|
||||
return !m_instance->isRunning();
|
||||
}
|
||||
|
||||
InstanceSettingsPage::~InstanceSettingsPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool InstanceSettingsPage::apply()
|
||||
{
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::applySettings()
|
||||
{
|
||||
// Console
|
||||
bool console = ui->consoleSettingsBox->isChecked();
|
||||
m_settings->set("OverrideConsole", console);
|
||||
if (console)
|
||||
{
|
||||
m_settings->set("ShowConsole", ui->showConsoleCheck->isChecked());
|
||||
m_settings->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("ShowConsole");
|
||||
m_settings->reset("AutoCloseConsole");
|
||||
}
|
||||
|
||||
// Window Size
|
||||
bool window = ui->windowSizeGroupBox->isChecked();
|
||||
m_settings->set("OverrideWindow", window);
|
||||
if (window)
|
||||
{
|
||||
m_settings->set("LaunchMaximized", ui->maximizedCheckBox->isChecked());
|
||||
m_settings->set("MinecraftWinWidth", ui->windowWidthSpinBox->value());
|
||||
m_settings->set("MinecraftWinHeight", ui->windowHeightSpinBox->value());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("LaunchMaximized");
|
||||
m_settings->reset("MinecraftWinWidth");
|
||||
m_settings->reset("MinecraftWinHeight");
|
||||
}
|
||||
|
||||
// Memory
|
||||
bool memory = ui->memoryGroupBox->isChecked();
|
||||
m_settings->set("OverrideMemory", memory);
|
||||
if (memory)
|
||||
{
|
||||
m_settings->set("MinMemAlloc", ui->minMemSpinBox->value());
|
||||
m_settings->set("MaxMemAlloc", ui->maxMemSpinBox->value());
|
||||
m_settings->set("PermGen", ui->permGenSpinBox->value());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("MinMemAlloc");
|
||||
m_settings->reset("MaxMemAlloc");
|
||||
m_settings->reset("PermGen");
|
||||
}
|
||||
|
||||
// Java Install Settings
|
||||
bool javaInstall = ui->javaSettingsGroupBox->isChecked();
|
||||
m_settings->set("OverrideJavaLocation", javaInstall);
|
||||
if (javaInstall)
|
||||
{
|
||||
m_settings->set("JavaPath", ui->javaPathTextBox->text());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("JavaPath");
|
||||
}
|
||||
|
||||
// Java arguments
|
||||
bool javaArgs = ui->javaArgumentsGroupBox->isChecked();
|
||||
m_settings->set("OverrideJavaArgs", javaArgs);
|
||||
if(javaArgs)
|
||||
{
|
||||
m_settings->set("JvmArgs", ui->jvmArgsTextBox->toPlainText().replace("\n", " "));
|
||||
JavaCommon::checkJVMArgs(m_settings->get("JvmArgs").toString(), this->parentWidget());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("JvmArgs");
|
||||
}
|
||||
|
||||
// old generic 'override both' is removed.
|
||||
m_settings->reset("OverrideJava");
|
||||
|
||||
// Custom Commands
|
||||
bool custcmd = ui->customCommandsGroupBox->isChecked();
|
||||
m_settings->set("OverrideCommands", custcmd);
|
||||
if (custcmd)
|
||||
{
|
||||
m_settings->set("PreLaunchCommand", ui->preLaunchCmdTextBox->text());
|
||||
m_settings->set("PostExitCommand", ui->postExitCmdTextBox->text());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("PreLaunchCommand");
|
||||
m_settings->reset("PostExitCommand");
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::loadSettings()
|
||||
{
|
||||
// Console
|
||||
ui->consoleSettingsBox->setChecked(m_settings->get("OverrideConsole").toBool());
|
||||
ui->showConsoleCheck->setChecked(m_settings->get("ShowConsole").toBool());
|
||||
ui->autoCloseConsoleCheck->setChecked(m_settings->get("AutoCloseConsole").toBool());
|
||||
|
||||
// Window Size
|
||||
ui->windowSizeGroupBox->setChecked(m_settings->get("OverrideWindow").toBool());
|
||||
ui->maximizedCheckBox->setChecked(m_settings->get("LaunchMaximized").toBool());
|
||||
ui->windowWidthSpinBox->setValue(m_settings->get("MinecraftWinWidth").toInt());
|
||||
ui->windowHeightSpinBox->setValue(m_settings->get("MinecraftWinHeight").toInt());
|
||||
|
||||
// Memory
|
||||
ui->memoryGroupBox->setChecked(m_settings->get("OverrideMemory").toBool());
|
||||
ui->minMemSpinBox->setValue(m_settings->get("MinMemAlloc").toInt());
|
||||
ui->maxMemSpinBox->setValue(m_settings->get("MaxMemAlloc").toInt());
|
||||
ui->permGenSpinBox->setValue(m_settings->get("PermGen").toInt());
|
||||
|
||||
// Java Settings
|
||||
bool overrideJava = m_settings->get("OverrideJava").toBool();
|
||||
bool overrideLocation = m_settings->get("OverrideJavaLocation").toBool() || overrideJava;
|
||||
bool overrideArgs = m_settings->get("OverrideJavaArgs").toBool() || overrideJava;
|
||||
|
||||
ui->javaSettingsGroupBox->setChecked(overrideLocation);
|
||||
ui->javaPathTextBox->setText(m_settings->get("JavaPath").toString());
|
||||
|
||||
ui->javaArgumentsGroupBox->setChecked(overrideArgs);
|
||||
ui->jvmArgsTextBox->setPlainText(m_settings->get("JvmArgs").toString());
|
||||
|
||||
// Custom Commands
|
||||
ui->customCommandsGroupBox->setChecked(m_settings->get("OverrideCommands").toBool());
|
||||
ui->preLaunchCmdTextBox->setText(m_settings->get("PreLaunchCommand").toString());
|
||||
ui->postExitCmdTextBox->setText(m_settings->get("PostExitCommand").toString());
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::on_javaDetectBtn_clicked()
|
||||
{
|
||||
JavaVersionPtr java;
|
||||
|
||||
VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true);
|
||||
vselect.setResizeOn(2);
|
||||
vselect.exec();
|
||||
|
||||
if (vselect.result() == QDialog::Accepted && vselect.selectedVersion())
|
||||
{
|
||||
java = std::dynamic_pointer_cast<JavaVersion>(vselect.selectedVersion());
|
||||
ui->javaPathTextBox->setText(java->path);
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::on_javaBrowseBtn_clicked()
|
||||
{
|
||||
QString dir = QFileDialog::getOpenFileName(this, tr("Find Java executable"));
|
||||
if (!dir.isNull())
|
||||
{
|
||||
ui->javaPathTextBox->setText(dir);
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::on_javaTestBtn_clicked()
|
||||
{
|
||||
if(checker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
checker.reset(new JavaCommon::TestCheck(
|
||||
this, ui->javaPathTextBox->text(), ui->jvmArgsTextBox->toPlainText().replace("\n", " "),
|
||||
ui->minMemSpinBox->value(), ui->maxMemSpinBox->value(), ui->permGenSpinBox->value()));
|
||||
connect(checker.get(), SIGNAL(finished()), SLOT(checkerFinished()));
|
||||
checker->run();
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::checkerFinished()
|
||||
{
|
||||
checker.reset();
|
||||
}
|
||||
74
application/pages/InstanceSettingsPage.h
Normal file
74
application/pages/InstanceSettingsPage.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "java/JavaChecker.h"
|
||||
#include "BaseInstance.h"
|
||||
#include <QObjectPtr.h>
|
||||
#include "BasePage.h"
|
||||
#include "JavaCommon.h"
|
||||
#include "MultiMC.h"
|
||||
|
||||
class JavaChecker;
|
||||
namespace Ui
|
||||
{
|
||||
class InstanceSettingsPage;
|
||||
}
|
||||
|
||||
class InstanceSettingsPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit InstanceSettingsPage(BaseInstance *inst, QWidget *parent = 0);
|
||||
virtual ~InstanceSettingsPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Settings");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("instance-settings");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "settings";
|
||||
}
|
||||
virtual bool apply();
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Instance-settings";
|
||||
}
|
||||
virtual bool shouldDisplay() const;
|
||||
|
||||
private slots:
|
||||
void on_javaDetectBtn_clicked();
|
||||
void on_javaTestBtn_clicked();
|
||||
void on_javaBrowseBtn_clicked();
|
||||
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
|
||||
void checkerFinished();
|
||||
|
||||
private:
|
||||
Ui::InstanceSettingsPage *ui;
|
||||
BaseInstance *m_instance;
|
||||
SettingsObject *m_settings;
|
||||
QObjectPtr<JavaCommon::TestCheck> checker;
|
||||
};
|
||||
@@ -1,19 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>InstanceSettings</class>
|
||||
<widget class="QDialog" name="InstanceSettings">
|
||||
<class>InstanceSettingsPage</class>
|
||||
<widget class="QWidget" name="InstanceSettingsPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>526</width>
|
||||
<height>637</height>
|
||||
<width>458</width>
|
||||
<height>426</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Instance Settings</string>
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="settingsTabs">
|
||||
<property name="tabShape">
|
||||
@@ -23,134 +35,52 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="minecraftTab">
|
||||
<attribute name="title">
|
||||
<string>Minecraft</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="windowSizeGroupBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Window Size</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="maximizedCheckBox">
|
||||
<property name="text">
|
||||
<string>Start Minecraft maximized?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayoutWindowSize">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelWindowHeight">
|
||||
<property name="text">
|
||||
<string>Window height:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelWindowWidth">
|
||||
<property name="text">
|
||||
<string>Window width:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="windowWidthSpinBox">
|
||||
<property name="minimum">
|
||||
<number>854</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65536</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>854</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="windowHeightSpinBox">
|
||||
<property name="minimum">
|
||||
<number>480</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65536</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>480</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="consoleSettingsBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Console Settings</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="showConsoleCheck">
|
||||
<property name="text">
|
||||
<string>Show console while the game is running?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="autoCloseConsoleCheck">
|
||||
<property name="text">
|
||||
<string>Automatically close console when the game quits?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacerMinecraft">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="javaTab">
|
||||
<attribute name="title">
|
||||
<string>Java</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="javaSettingsGroupBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Java installation</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="3">
|
||||
<widget class="QLineEdit" name="javaPathTextBox"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="javaDetectBtn">
|
||||
<property name="text">
|
||||
<string>Auto-detect...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="javaBrowseBtn">
|
||||
<property name="text">
|
||||
<string>Browse...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="javaTestBtn">
|
||||
<property name="text">
|
||||
<string>Test</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="memoryGroupBox">
|
||||
<property name="enabled">
|
||||
@@ -257,12 +187,12 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="javaSettingsGroupBox">
|
||||
<widget class="QGroupBox" name="javaArgumentsGroupBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Java Settings</string>
|
||||
<string>Java arguments</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
@@ -270,51 +200,157 @@
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="2" column="4">
|
||||
<widget class="QPushButton" name="javaTestBtn">
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="1" column="1">
|
||||
<widget class="QPlainTextEdit" name="jvmArgsTextBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacerMinecraft">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="javaTab">
|
||||
<attribute name="title">
|
||||
<string>Game windows</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="windowSizeGroupBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Game Window</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="maximizedCheckBox">
|
||||
<property name="text">
|
||||
<string>Test</string>
|
||||
<string>Start Minecraft maximized?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelJavaPath">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayoutWindowSize">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelWindowHeight">
|
||||
<property name="text">
|
||||
<string>Window height:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelWindowWidth">
|
||||
<property name="text">
|
||||
<string>Window width:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="windowWidthSpinBox">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65536</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>854</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="windowHeightSpinBox">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65536</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>480</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="consoleSettingsBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Console Settings</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="showConsoleCheck">
|
||||
<property name="text">
|
||||
<string>Java path:</string>
|
||||
<string>Show console while the game is running?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelJVMArgs">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="autoCloseConsoleCheck">
|
||||
<property name="text">
|
||||
<string>JVM arguments:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" colspan="3">
|
||||
<widget class="QLineEdit" name="jvmArgsTextBox"/>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="3">
|
||||
<widget class="QLineEdit" name="javaPathTextBox"/>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QPushButton" name="javaBrowseBtn">
|
||||
<property name="text">
|
||||
<string>Browse...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="javaDetectBtn">
|
||||
<property name="text">
|
||||
<string>Auto-detect...</string>
|
||||
<string>Automatically close console when the game quits?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacerMinecraft_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>88</width>
|
||||
<height>125</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Custom commands</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="customCommandsGroupBox">
|
||||
<property name="enabled">
|
||||
@@ -355,17 +391,8 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelCustomCmdsDescription">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pre-launch command runs before the instance launches and post-exit command runs after it exits. Both will be run in MultiMC's working directory with INST_ID, INST_DIR, and INST_NAME as environment variables.</string>
|
||||
<string><html><head/><body><p>Pre-launch command runs before the instance launches and post-exit command runs after it exits.</p><p>Both will be run in MultiMC's working directory with extra environment variables:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">INST_NAME - Name of the instance</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">INST_ID - ID of the instance</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">INST_DIR - absolute path of the instance</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">INST_MC_DIR - absolute path of minecraft</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">INST_JAVA - java binary used for launch</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">INST_JAVA_ARGS - command-line parameters used for launch</li></ul></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
@@ -378,25 +405,38 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacerMinecraft_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>88</width>
|
||||
<height>186</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>settingsTabs</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
<tabstop>javaSettingsGroupBox</tabstop>
|
||||
<tabstop>javaPathTextBox</tabstop>
|
||||
<tabstop>javaDetectBtn</tabstop>
|
||||
<tabstop>javaBrowseBtn</tabstop>
|
||||
<tabstop>javaTestBtn</tabstop>
|
||||
<tabstop>memoryGroupBox</tabstop>
|
||||
<tabstop>minMemSpinBox</tabstop>
|
||||
<tabstop>maxMemSpinBox</tabstop>
|
||||
<tabstop>permGenSpinBox</tabstop>
|
||||
<tabstop>javaArgumentsGroupBox</tabstop>
|
||||
<tabstop>jvmArgsTextBox</tabstop>
|
||||
<tabstop>windowSizeGroupBox</tabstop>
|
||||
<tabstop>maximizedCheckBox</tabstop>
|
||||
<tabstop>windowWidthSpinBox</tabstop>
|
||||
@@ -404,12 +444,6 @@
|
||||
<tabstop>consoleSettingsBox</tabstop>
|
||||
<tabstop>showConsoleCheck</tabstop>
|
||||
<tabstop>autoCloseConsoleCheck</tabstop>
|
||||
<tabstop>memoryGroupBox</tabstop>
|
||||
<tabstop>minMemSpinBox</tabstop>
|
||||
<tabstop>maxMemSpinBox</tabstop>
|
||||
<tabstop>permGenSpinBox</tabstop>
|
||||
<tabstop>javaSettingsGroupBox</tabstop>
|
||||
<tabstop>jvmArgsTextBox</tabstop>
|
||||
<tabstop>customCommandsGroupBox</tabstop>
|
||||
<tabstop>preLaunchCmdTextBox</tabstop>
|
||||
<tabstop>postExitCmdTextBox</tabstop>
|
||||
163
application/pages/LegacyJarModPage.cpp
Normal file
163
application/pages/LegacyJarModPage.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "LegacyJarModPage.h"
|
||||
#include "ui_LegacyJarModPage.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include <pathutils.h>
|
||||
|
||||
#include "dialogs/VersionSelectDialog.h"
|
||||
#include "dialogs/ProgressDialog.h"
|
||||
#include "dialogs/ModEditDialogCommon.h"
|
||||
#include "minecraft/ModList.h"
|
||||
#include "minecraft/LegacyInstance.h"
|
||||
#include "Env.h"
|
||||
#include "MultiMC.h"
|
||||
#include <GuiUtil.h>
|
||||
|
||||
LegacyJarModPage::LegacyJarModPage(LegacyInstance *inst, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::LegacyJarModPage), m_inst(inst)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
|
||||
m_jarmods = m_inst->jarModList();
|
||||
ui->jarModsTreeView->setModel(m_jarmods.get());
|
||||
ui->jarModsTreeView->setDragDropMode(QAbstractItemView::DragDrop);
|
||||
ui->jarModsTreeView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
ui->jarModsTreeView->installEventFilter(this);
|
||||
m_jarmods->startWatching();
|
||||
auto smodel = ui->jarModsTreeView->selectionModel();
|
||||
connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
|
||||
SLOT(jarCurrent(QModelIndex, QModelIndex)));
|
||||
}
|
||||
|
||||
LegacyJarModPage::~LegacyJarModPage()
|
||||
{
|
||||
m_jarmods->stopWatching();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool LegacyJarModPage::shouldDisplay() const
|
||||
{
|
||||
return !m_inst->isRunning();
|
||||
}
|
||||
|
||||
bool LegacyJarModPage::eventFilter(QObject *obj, QEvent *ev)
|
||||
{
|
||||
if (ev->type() != QEvent::KeyPress || obj != ui->jarModsTreeView)
|
||||
{
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
}
|
||||
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Up:
|
||||
{
|
||||
if (keyEvent->modifiers() & Qt::ControlModifier)
|
||||
{
|
||||
on_moveJarUpBtn_clicked();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Qt::Key_Down:
|
||||
{
|
||||
if (keyEvent->modifiers() & Qt::ControlModifier)
|
||||
{
|
||||
on_moveJarDownBtn_clicked();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Qt::Key_Delete:
|
||||
on_rmJarBtn_clicked();
|
||||
return true;
|
||||
case Qt::Key_Plus:
|
||||
on_addJarBtn_clicked();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
}
|
||||
|
||||
void LegacyJarModPage::on_addJarBtn_clicked()
|
||||
{
|
||||
auto list = GuiUtil::BrowseForMods("jarmod", tr("Select jar mods"), tr("Minecraft.jar mods (*.zip *.jar)"), this->parentWidget());
|
||||
if(!list.empty())
|
||||
{
|
||||
m_jarmods->stopWatching();
|
||||
for (auto filename : list)
|
||||
{
|
||||
m_jarmods->installMod(QFileInfo(filename));
|
||||
}
|
||||
m_jarmods->startWatching();
|
||||
}
|
||||
}
|
||||
|
||||
void LegacyJarModPage::on_moveJarDownBtn_clicked()
|
||||
{
|
||||
int first, last;
|
||||
auto list = ui->jarModsTreeView->selectionModel()->selectedRows();
|
||||
|
||||
if (!lastfirst(list, first, last))
|
||||
return;
|
||||
|
||||
m_jarmods->moveModsDown(first, last);
|
||||
}
|
||||
|
||||
void LegacyJarModPage::on_moveJarUpBtn_clicked()
|
||||
{
|
||||
int first, last;
|
||||
auto list = ui->jarModsTreeView->selectionModel()->selectedRows();
|
||||
|
||||
if (!lastfirst(list, first, last))
|
||||
return;
|
||||
m_jarmods->moveModsUp(first, last);
|
||||
}
|
||||
|
||||
void LegacyJarModPage::on_rmJarBtn_clicked()
|
||||
{
|
||||
int first, last;
|
||||
auto list = ui->jarModsTreeView->selectionModel()->selectedRows();
|
||||
|
||||
if (!lastfirst(list, first, last))
|
||||
return;
|
||||
m_jarmods->stopWatching();
|
||||
m_jarmods->deleteMods(first, last);
|
||||
m_jarmods->startWatching();
|
||||
}
|
||||
|
||||
void LegacyJarModPage::on_viewJarBtn_clicked()
|
||||
{
|
||||
openDirInDefaultProgram(m_inst->jarModsDir(), true);
|
||||
}
|
||||
|
||||
void LegacyJarModPage::jarCurrent(QModelIndex current, QModelIndex previous)
|
||||
{
|
||||
if (!current.isValid())
|
||||
{
|
||||
ui->jarMIFrame->clear();
|
||||
return;
|
||||
}
|
||||
int row = current.row();
|
||||
Mod &m = m_jarmods->operator[](row);
|
||||
ui->jarMIFrame->updateWithMod(m);
|
||||
}
|
||||
76
application/pages/LegacyJarModPage.h
Normal file
76
application/pages/LegacyJarModPage.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "net/NetJob.h"
|
||||
#include "BasePage.h"
|
||||
#include <MultiMC.h>
|
||||
|
||||
class ModList;
|
||||
class LegacyInstance;
|
||||
namespace Ui
|
||||
{
|
||||
class LegacyJarModPage;
|
||||
}
|
||||
|
||||
class LegacyJarModPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LegacyJarModPage(LegacyInstance *inst, QWidget *parent = 0);
|
||||
virtual ~LegacyJarModPage();
|
||||
|
||||
virtual QString displayName() const
|
||||
{
|
||||
return tr("Jar Mods");
|
||||
}
|
||||
virtual QIcon icon() const
|
||||
{
|
||||
return MMC->getThemedIcon("jarmods");
|
||||
}
|
||||
virtual QString id() const
|
||||
{
|
||||
return "jarmods";
|
||||
}
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Legacy-jar-mods";
|
||||
}
|
||||
virtual bool shouldDisplay() const;
|
||||
|
||||
private
|
||||
slots:
|
||||
|
||||
void on_addJarBtn_clicked();
|
||||
void on_rmJarBtn_clicked();
|
||||
void on_moveJarUpBtn_clicked();
|
||||
void on_moveJarDownBtn_clicked();
|
||||
void on_viewJarBtn_clicked();
|
||||
|
||||
void jarCurrent(QModelIndex current, QModelIndex previous);
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject *obj, QEvent *ev) override;
|
||||
|
||||
private:
|
||||
Ui::LegacyJarModPage *ui;
|
||||
std::shared_ptr<ModList> m_jarmods;
|
||||
LegacyInstance *m_inst;
|
||||
NetJobPtr forgeJob;
|
||||
};
|
||||
165
application/pages/LegacyJarModPage.ui
Normal file
165
application/pages/LegacyJarModPage.ui
Normal file
@@ -0,0 +1,165 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LegacyJarModPage</class>
|
||||
<widget class="QWidget" name="LegacyJarModPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>659</width>
|
||||
<height>593</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>LegacyJarModPage</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Tab 1</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="ModListView" name="jarModsTreeView">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="jarModsButtonBox">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Selection</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="rmJarBtn">
|
||||
<property name="text">
|
||||
<string>&Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="moveJarUpBtn">
|
||||
<property name="text">
|
||||
<string>Move &Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="moveJarDownBtn">
|
||||
<property name="text">
|
||||
<string>Move &Down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LineSeparator" name="separator" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Install</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addJarBtn">
|
||||
<property name="text">
|
||||
<string>&Add jar mod</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="viewJarBtn">
|
||||
<property name="text">
|
||||
<string>&View Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MCModInfoFrame" name="jarMIFrame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ModListView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>widgets/ModListView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>MCModInfoFrame</class>
|
||||
<extends>QFrame</extends>
|
||||
<header>widgets/MCModInfoFrame.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LineSeparator</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/LineSeparator.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
25
application/pages/LegacyUpgradePage.cpp
Normal file
25
application/pages/LegacyUpgradePage.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "LegacyUpgradePage.h"
|
||||
#include "ui_LegacyUpgradePage.h"
|
||||
|
||||
#include "minecraft/LegacyInstance.h"
|
||||
|
||||
LegacyUpgradePage::LegacyUpgradePage(LegacyInstance *inst, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::LegacyUpgradePage), m_inst(inst)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
LegacyUpgradePage::~LegacyUpgradePage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void LegacyUpgradePage::on_upgradeButton_clicked()
|
||||
{
|
||||
// now what?
|
||||
}
|
||||
|
||||
bool LegacyUpgradePage::shouldDisplay() const
|
||||
{
|
||||
return !m_inst->isRunning();
|
||||
}
|
||||
60
application/pages/LegacyUpgradePage.h
Normal file
60
application/pages/LegacyUpgradePage.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "minecraft/OneSixInstance.h"
|
||||
#include "pages/BasePage.h"
|
||||
#include <MultiMC.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class LegacyUpgradePage;
|
||||
}
|
||||
|
||||
class LegacyUpgradePage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LegacyUpgradePage(LegacyInstance *inst, QWidget *parent = 0);
|
||||
virtual ~LegacyUpgradePage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Upgrade");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("checkupdate");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "upgrade";
|
||||
}
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Legacy-upgrade";
|
||||
}
|
||||
virtual bool shouldDisplay() const;
|
||||
private
|
||||
slots:
|
||||
void on_upgradeButton_clicked();
|
||||
|
||||
private:
|
||||
Ui::LegacyUpgradePage *ui;
|
||||
LegacyInstance *m_inst;
|
||||
};
|
||||
58
application/pages/LegacyUpgradePage.ui
Normal file
58
application/pages/LegacyUpgradePage.ui
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LegacyUpgradePage</class>
|
||||
<widget class="QWidget" name="LegacyUpgradePage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>546</width>
|
||||
<height>405</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Upgrade</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="textBrowser">
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:600;">New format is available</span> </p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">MultiMC now supports old Minecraft versions in the new (OneSix) instance format. The old format won't be getting any new features and only the most critical bugfixes. As a consequence, you should upgrade this instance. </p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The upgrade will create a new instance with the same contents as the current one, in the new format. The original instance will remain untouched, in case anything goes wrong in the process. </p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Please report any issues on our <a href="https://github.com/MultiMC/MultiMC5/issues"><img src=":/icons/multimc/22x22/bug.png" /></a><a href="https://github.com/MultiMC/MultiMC5/issues"><span style=" text-decoration: underline; color:#68a0df;">github issues page</span></a>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCommandLinkButton" name="upgradeButton">
|
||||
<property name="text">
|
||||
<string>Start the upgrade! (Not Yet Implemented, Coming Soon™)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
227
application/pages/LogPage.cpp
Normal file
227
application/pages/LogPage.cpp
Normal file
@@ -0,0 +1,227 @@
|
||||
#include "LogPage.h"
|
||||
#include "ui_LogPage.h"
|
||||
|
||||
#include "MultiMC.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QScrollBar>
|
||||
#include <QShortcut>
|
||||
|
||||
#include "BaseProcess.h"
|
||||
#include "GuiUtil.h"
|
||||
|
||||
LogPage::LogPage(BaseProcess *proc, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::LogPage), m_process(proc)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
connect(m_process, SIGNAL(log(QString, MessageLevel::Enum)), this,
|
||||
SLOT(write(QString, MessageLevel::Enum)));
|
||||
|
||||
// create the format and set its font
|
||||
defaultFormat = new QTextCharFormat(ui->text->currentCharFormat());
|
||||
QString fontFamily = MMC->settings()->get("ConsoleFont").toString();
|
||||
bool conversionOk = false;
|
||||
int fontSize = MMC->settings()->get("ConsoleFontSize").toInt(&conversionOk);
|
||||
if(!conversionOk)
|
||||
{
|
||||
fontSize = 11;
|
||||
}
|
||||
defaultFormat->setFont(QFont(fontFamily, fontSize));
|
||||
|
||||
auto findShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this);
|
||||
connect(findShortcut, SIGNAL(activated()), SLOT(findActivated()));
|
||||
auto findNextShortcut = new QShortcut(QKeySequence(QKeySequence::FindNext), this);
|
||||
connect(findNextShortcut, SIGNAL(activated()), SLOT(findNextActivated()));
|
||||
connect(ui->searchBar, SIGNAL(returnPressed()), SLOT(on_findButton_clicked()));
|
||||
auto findPreviousShortcut = new QShortcut(QKeySequence(QKeySequence::FindPrevious), this);
|
||||
connect(findPreviousShortcut, SIGNAL(activated()), SLOT(findPreviousActivated()));
|
||||
}
|
||||
|
||||
LogPage::~LogPage()
|
||||
{
|
||||
delete ui;
|
||||
delete defaultFormat;
|
||||
}
|
||||
|
||||
bool LogPage::apply()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LogPage::shouldDisplay() const
|
||||
{
|
||||
return m_process->instance()->isRunning();
|
||||
}
|
||||
|
||||
void LogPage::on_btnPaste_clicked()
|
||||
{
|
||||
GuiUtil::uploadPaste(ui->text->toPlainText(), this);
|
||||
}
|
||||
|
||||
void LogPage::on_btnCopy_clicked()
|
||||
{
|
||||
GuiUtil::setClipboardText(ui->text->toPlainText());
|
||||
}
|
||||
|
||||
void LogPage::on_btnClear_clicked()
|
||||
{
|
||||
ui->text->clear();
|
||||
}
|
||||
|
||||
void LogPage::on_btnBottom_clicked()
|
||||
{
|
||||
ui->text->verticalScrollBar()->setSliderPosition(ui->text->verticalScrollBar()->maximum());
|
||||
}
|
||||
|
||||
void LogPage::on_trackLogCheckbox_clicked(bool checked)
|
||||
{
|
||||
m_write_active = checked;
|
||||
}
|
||||
|
||||
void LogPage::on_findButton_clicked()
|
||||
{
|
||||
auto modifiers = QApplication::keyboardModifiers();
|
||||
if (modifiers & Qt::ShiftModifier)
|
||||
{
|
||||
findPreviousActivated();
|
||||
}
|
||||
else
|
||||
{
|
||||
findNextActivated();
|
||||
}
|
||||
}
|
||||
|
||||
void LogPage::findActivated()
|
||||
{
|
||||
// focus the search bar if it doesn't have focus
|
||||
if (!ui->searchBar->hasFocus())
|
||||
{
|
||||
auto searchForCursor = ui->text->textCursor();
|
||||
auto searchForString = searchForCursor.selectedText();
|
||||
if (searchForString.size())
|
||||
{
|
||||
ui->searchBar->setText(searchForString);
|
||||
}
|
||||
ui->searchBar->setFocus();
|
||||
ui->searchBar->selectAll();
|
||||
}
|
||||
}
|
||||
|
||||
void LogPage::findNextActivated()
|
||||
{
|
||||
auto toSearch = ui->searchBar->text();
|
||||
if (toSearch.size())
|
||||
{
|
||||
ui->text->find(toSearch);
|
||||
}
|
||||
}
|
||||
|
||||
void LogPage::findPreviousActivated()
|
||||
{
|
||||
auto toSearch = ui->searchBar->text();
|
||||
if (toSearch.size())
|
||||
{
|
||||
ui->text->find(toSearch, QTextDocument::FindBackward);
|
||||
}
|
||||
}
|
||||
|
||||
void LogPage::write(QString data, MessageLevel::Enum mode)
|
||||
{
|
||||
if (!m_write_active)
|
||||
{
|
||||
if (mode != MessageLevel::PrePost && mode != MessageLevel::MultiMC)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// save the cursor so it can be restored.
|
||||
auto savedCursor = ui->text->cursor();
|
||||
|
||||
QScrollBar *bar = ui->text->verticalScrollBar();
|
||||
int max_bar = bar->maximum();
|
||||
int val_bar = bar->value();
|
||||
if (isVisible())
|
||||
{
|
||||
if (m_scroll_active)
|
||||
{
|
||||
m_scroll_active = (max_bar - val_bar) <= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_scroll_active = val_bar == max_bar;
|
||||
}
|
||||
}
|
||||
if (data.endsWith('\n'))
|
||||
data = data.left(data.length() - 1);
|
||||
QStringList paragraphs = data.split('\n');
|
||||
QStringList filtered;
|
||||
for (QString ¶graph : paragraphs)
|
||||
{
|
||||
//TODO: implement filtering here.
|
||||
filtered.append(paragraph);
|
||||
}
|
||||
QListIterator<QString> iter(filtered);
|
||||
QTextCharFormat format(*defaultFormat);
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case MessageLevel::MultiMC:
|
||||
{
|
||||
format.setForeground(QColor("blue"));
|
||||
break;
|
||||
}
|
||||
case MessageLevel::Debug:
|
||||
{
|
||||
format.setForeground(QColor("green"));
|
||||
break;
|
||||
}
|
||||
case MessageLevel::Warning:
|
||||
{
|
||||
format.setForeground(QColor("orange"));
|
||||
break;
|
||||
}
|
||||
case MessageLevel::Error:
|
||||
{
|
||||
format.setForeground(QColor("red"));
|
||||
break;
|
||||
}
|
||||
case MessageLevel::Fatal:
|
||||
{
|
||||
format.setForeground(QColor("red"));
|
||||
format.setBackground(QColor("black"));
|
||||
break;
|
||||
}
|
||||
case MessageLevel::PrePost:
|
||||
{
|
||||
format.setForeground(QColor("grey"));
|
||||
break;
|
||||
}
|
||||
case MessageLevel::Info:
|
||||
case MessageLevel::Message:
|
||||
default:
|
||||
{
|
||||
// do nothing, keep original
|
||||
}
|
||||
}
|
||||
|
||||
while (iter.hasNext())
|
||||
{
|
||||
// append a paragraph/line
|
||||
auto workCursor = ui->text->textCursor();
|
||||
workCursor.movePosition(QTextCursor::End);
|
||||
workCursor.insertText(iter.next(), format);
|
||||
workCursor.insertBlock();
|
||||
}
|
||||
|
||||
if (isVisible())
|
||||
{
|
||||
if (m_scroll_active)
|
||||
{
|
||||
bar->setValue(bar->maximum());
|
||||
}
|
||||
m_last_scroll_value = bar->value();
|
||||
}
|
||||
ui->text->setCursor(savedCursor);
|
||||
}
|
||||
86
application/pages/LogPage.h
Normal file
86
application/pages/LogPage.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "BaseInstance.h"
|
||||
#include "BaseProcess.h"
|
||||
#include "BasePage.h"
|
||||
#include <MultiMC.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class LogPage;
|
||||
}
|
||||
class QTextCharFormat;
|
||||
|
||||
class LogPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LogPage(BaseProcess *proc, QWidget *parent = 0);
|
||||
virtual ~LogPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Minecraft Log");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("log");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "console";
|
||||
}
|
||||
virtual bool apply();
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Minecraft-Logs";
|
||||
}
|
||||
virtual bool shouldDisplay() const;
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief write a string
|
||||
* @param data the string
|
||||
* @param mode the WriteMode
|
||||
* lines have to be put through this as a whole!
|
||||
*/
|
||||
void write(QString data, MessageLevel::Enum level = MessageLevel::MultiMC);
|
||||
void on_btnPaste_clicked();
|
||||
void on_btnCopy_clicked();
|
||||
void on_btnClear_clicked();
|
||||
void on_btnBottom_clicked();
|
||||
|
||||
void on_trackLogCheckbox_clicked(bool checked);
|
||||
|
||||
void on_findButton_clicked();
|
||||
void findActivated();
|
||||
void findNextActivated();
|
||||
void findPreviousActivated();
|
||||
|
||||
private:
|
||||
Ui::LogPage *ui;
|
||||
BaseProcess *m_process;
|
||||
int m_last_scroll_value = 0;
|
||||
bool m_scroll_active = true;
|
||||
int m_saved_offset = 0;
|
||||
bool m_write_active = true;
|
||||
|
||||
QTextCharFormat * defaultFormat;
|
||||
};
|
||||
167
application/pages/LogPage.ui
Normal file
167
application/pages/LogPage.ui
Normal file
@@ -0,0 +1,167 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LogPage</class>
|
||||
<widget class="QWidget" name="LogPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>825</width>
|
||||
<height>782</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Log</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Tab 1</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0" colspan="5">
|
||||
<widget class="QPlainTextEdit" name="text">
|
||||
<property name="undoRedoEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="plainText">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
<property name="centerOnScroll">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="5">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="trackLogCheckbox">
|
||||
<property name="text">
|
||||
<string>Keep updating</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnCopy">
|
||||
<property name="toolTip">
|
||||
<string>Copy the whole log into the clipboard</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Copy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnPaste">
|
||||
<property name="toolTip">
|
||||
<string>Upload the log to paste.ee - it will stay online for a month</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Upload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnClear">
|
||||
<property name="toolTip">
|
||||
<string>Clear the log</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Search:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="findButton">
|
||||
<property name="text">
|
||||
<string>Find</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="searchBar"/>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QPushButton" name="btnBottom">
|
||||
<property name="toolTip">
|
||||
<string>Scroll all the way to bottom</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Bottom</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
<tabstop>trackLogCheckbox</tabstop>
|
||||
<tabstop>btnCopy</tabstop>
|
||||
<tabstop>btnPaste</tabstop>
|
||||
<tabstop>btnClear</tabstop>
|
||||
<tabstop>text</tabstop>
|
||||
<tabstop>searchBar</tabstop>
|
||||
<tabstop>findButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
178
application/pages/ModFolderPage.cpp
Normal file
178
application/pages/ModFolderPage.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ModFolderPage.h"
|
||||
#include "ui_ModFolderPage.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QDesktopServices>
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
#include <pathutils.h>
|
||||
|
||||
#include "MultiMC.h"
|
||||
#include "dialogs/CustomMessageBox.h"
|
||||
#include "dialogs/ModEditDialogCommon.h"
|
||||
#include <GuiUtil.h>
|
||||
#include "minecraft/ModList.h"
|
||||
#include "minecraft/Mod.h"
|
||||
#include "minecraft/VersionFilterData.h"
|
||||
|
||||
ModFolderPage::ModFolderPage(BaseInstance *inst, std::shared_ptr<ModList> mods, QString id,
|
||||
QString iconName, QString displayName, QString helpPage,
|
||||
QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::ModFolderPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
m_inst = inst;
|
||||
m_mods = mods;
|
||||
m_id = id;
|
||||
m_displayName = displayName;
|
||||
m_iconName = iconName;
|
||||
m_helpName = helpPage;
|
||||
m_filter = tr("%1 (*.zip *.jar)");
|
||||
ui->modTreeView->setModel(m_mods.get());
|
||||
ui->modTreeView->installEventFilter(this);
|
||||
auto smodel = ui->modTreeView->selectionModel();
|
||||
connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
|
||||
SLOT(modCurrent(QModelIndex, QModelIndex)));
|
||||
}
|
||||
|
||||
void ModFolderPage::opened()
|
||||
{
|
||||
m_mods->startWatching();
|
||||
}
|
||||
|
||||
void ModFolderPage::closed()
|
||||
{
|
||||
m_mods->stopWatching();
|
||||
}
|
||||
|
||||
CoreModFolderPage::CoreModFolderPage(BaseInstance *inst, std::shared_ptr<ModList> mods,
|
||||
QString id, QString iconName, QString displayName,
|
||||
QString helpPage, QWidget *parent)
|
||||
: ModFolderPage(inst, mods, id, iconName, displayName, helpPage, parent)
|
||||
{
|
||||
}
|
||||
|
||||
ModFolderPage::~ModFolderPage()
|
||||
{
|
||||
m_mods->stopWatching();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool ModFolderPage::shouldDisplay() const
|
||||
{
|
||||
if (m_inst)
|
||||
return !m_inst->isRunning();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoreModFolderPage::shouldDisplay() const
|
||||
{
|
||||
if (ModFolderPage::shouldDisplay())
|
||||
{
|
||||
auto inst = dynamic_cast<OneSixInstance *>(m_inst);
|
||||
if (!inst)
|
||||
return true;
|
||||
auto version = inst->getMinecraftProfile();
|
||||
if (!version)
|
||||
return true;
|
||||
if (version->m_releaseTime < g_VersionFilterData.legacyCutoffDate)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ModFolderPage::modListFilter(QKeyEvent *keyEvent)
|
||||
{
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
on_rmModBtn_clicked();
|
||||
return true;
|
||||
case Qt::Key_Plus:
|
||||
on_addModBtn_clicked();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QWidget::eventFilter(ui->modTreeView, keyEvent);
|
||||
}
|
||||
|
||||
bool ModFolderPage::eventFilter(QObject *obj, QEvent *ev)
|
||||
{
|
||||
if (ev->type() != QEvent::KeyPress)
|
||||
{
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
}
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
|
||||
if (obj == ui->modTreeView)
|
||||
return modListFilter(keyEvent);
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
}
|
||||
|
||||
void ModFolderPage::on_addModBtn_clicked()
|
||||
{
|
||||
auto list = GuiUtil::BrowseForMods(
|
||||
m_helpName,
|
||||
tr("Select %1",
|
||||
"Select whatever type of files the page contains. Example: 'Loader Mods'")
|
||||
.arg(m_displayName),
|
||||
m_filter.arg(m_displayName), this->parentWidget());
|
||||
if (!list.empty())
|
||||
{
|
||||
m_mods->stopWatching();
|
||||
for (auto filename : list)
|
||||
{
|
||||
m_mods->installMod(QFileInfo(filename));
|
||||
}
|
||||
m_mods->startWatching();
|
||||
}
|
||||
|
||||
}
|
||||
void ModFolderPage::on_rmModBtn_clicked()
|
||||
{
|
||||
int first, last;
|
||||
auto list = ui->modTreeView->selectionModel()->selectedRows();
|
||||
|
||||
if (!lastfirst(list, first, last))
|
||||
return;
|
||||
m_mods->stopWatching();
|
||||
m_mods->deleteMods(first, last);
|
||||
m_mods->startWatching();
|
||||
}
|
||||
|
||||
void ModFolderPage::on_viewModBtn_clicked()
|
||||
{
|
||||
openDirInDefaultProgram(m_mods->dir().absolutePath(), true);
|
||||
}
|
||||
|
||||
void ModFolderPage::modCurrent(const QModelIndex ¤t, const QModelIndex &previous)
|
||||
{
|
||||
if (!current.isValid())
|
||||
{
|
||||
ui->frame->clear();
|
||||
return;
|
||||
}
|
||||
int row = current.row();
|
||||
Mod &m = m_mods->operator[](row);
|
||||
ui->frame->updateWithMod(m);
|
||||
}
|
||||
102
application/pages/ModFolderPage.h
Normal file
102
application/pages/ModFolderPage.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/* Copyright 2013-2015 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "minecraft/OneSixInstance.h"
|
||||
#include "BasePage.h"
|
||||
#include <MultiMC.h>
|
||||
|
||||
class ModList;
|
||||
namespace Ui
|
||||
{
|
||||
class ModFolderPage;
|
||||
}
|
||||
|
||||
class ModFolderPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ModFolderPage(BaseInstance *inst, std::shared_ptr<ModList> mods, QString id,
|
||||
QString iconName, QString displayName, QString helpPage = "",
|
||||
QWidget *parent = 0);
|
||||
virtual ~ModFolderPage();
|
||||
|
||||
void setFilter(const QString & filter)
|
||||
{
|
||||
m_filter = filter;
|
||||
}
|
||||
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return m_displayName;
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon(m_iconName);
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return m_helpName;
|
||||
}
|
||||
virtual bool shouldDisplay() const;
|
||||
|
||||
virtual void opened();
|
||||
virtual void closed();
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *ev);
|
||||
bool modListFilter(QKeyEvent *ev);
|
||||
|
||||
protected:
|
||||
BaseInstance *m_inst;
|
||||
|
||||
private:
|
||||
Ui::ModFolderPage *ui;
|
||||
std::shared_ptr<ModList> m_mods;
|
||||
QString m_iconName;
|
||||
QString m_id;
|
||||
QString m_displayName;
|
||||
QString m_helpName;
|
||||
QString m_filter;
|
||||
|
||||
public
|
||||
slots:
|
||||
void modCurrent(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_addModBtn_clicked();
|
||||
void on_rmModBtn_clicked();
|
||||
void on_viewModBtn_clicked();
|
||||
};
|
||||
|
||||
class CoreModFolderPage : public ModFolderPage
|
||||
{
|
||||
public:
|
||||
explicit CoreModFolderPage(BaseInstance *inst, std::shared_ptr<ModList> mods, QString id,
|
||||
QString iconName, QString displayName, QString helpPage = "",
|
||||
QWidget *parent = 0);
|
||||
virtual ~CoreModFolderPage()
|
||||
{
|
||||
}
|
||||
virtual bool shouldDisplay() const;
|
||||
};
|
||||
124
application/pages/ModFolderPage.ui
Normal file
124
application/pages/ModFolderPage.ui
Normal file
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ModFolderPage</class>
|
||||
<widget class="QWidget" name="ModFolderPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>723</width>
|
||||
<height>532</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Mods</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Tab 1</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="ModListView" name="modTreeView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DropOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="addModBtn">
|
||||
<property name="text">
|
||||
<string>&Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="rmModBtn">
|
||||
<property name="text">
|
||||
<string>&Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="viewModBtn">
|
||||
<property name="text">
|
||||
<string>&View Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="MCModInfoFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ModListView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>widgets/ModListView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>MCModInfoFrame</class>
|
||||
<extends>QFrame</extends>
|
||||
<header>widgets/MCModInfoFrame.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user