Compare commits
418 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 71a3c60d95 | |||
| fefc76e5da | |||
| 07f6646f7f | |||
| c8b3d92836 | |||
| 1d1f616063 | |||
| cb5fe12ee1 | |||
| 166f5d1612 | |||
| e4fed17f59 | |||
| 5a6d002bf0 | |||
| 395cc0c32f | |||
| b840dd9af8 | |||
| c4c256f56a | |||
| c41451af75 | |||
| 4ea171fa5e | |||
| d6006e9a3f | |||
| 65d42a428f | |||
| 04e52ffed0 | |||
| a0e4c2e1fc | |||
| 12c1766997 | |||
| 377cd301b3 | |||
| 50866199a4 | |||
| dba7bcd489 | |||
| a1eeb9908d | |||
| 91f559a71f | |||
| c17e1bd7a8 | |||
| 4a3d57e469 | |||
| 8aeb425669 | |||
| 65b389da70 | |||
| 348ca07e0d | |||
| 0a6f685ad0 | |||
| 3aed797466 | |||
| 185e405bc1 | |||
| 519ddfae04 | |||
| 1914a1d21c | |||
| f34176996e | |||
| ac48e059bc | |||
| 95f45112e9 | |||
| a5ebba7e36 | |||
| a6cfc73cb2 | |||
| 90c3dd300f | |||
| f072f48806 | |||
| a323bc5af8 | |||
| 2069430baa | |||
| fc708b396b | |||
| e41c8b6780 | |||
| 646622ccd4 | |||
| c7c4ef9d43 | |||
| cdabc9064b | |||
| 8592f8a2b4 | |||
| 42a7c5d017 | |||
| 5388e6db84 | |||
| 38dbe57797 | |||
| ddb186e61d | |||
| 7b2917b4e1 | |||
| 5a8cd1b118 | |||
| d2d7a5060f | |||
| 16ff0161b3 | |||
| 420b1f89d3 | |||
| ee099b2697 | |||
| 945effcc75 | |||
| 5554de3933 | |||
| 8171ad65cd | |||
| d25648cb6c | |||
| 210c2c9a56 | |||
| 6806a893bd | |||
| 019bc9f6b2 | |||
| c68255f70f | |||
| 247cd92216 | |||
| 3289abe1cc | |||
| 4b95b0df97 | |||
| 3d2e80daed | |||
| d825dff259 | |||
| 9110cfdefb | |||
| f94cb0bdb2 | |||
| 19454e71d8 | |||
| 116989be8e | |||
| 2c791b38e6 | |||
| 52cc25ccbf | |||
| 993dbe49fc | |||
| 65e20f424a | |||
| 02169406be | |||
| bc38d4c81b | |||
| 3394f24728 | |||
| cfb9bcbe42 | |||
| 065867e2c2 | |||
| 08a5cf0b5b | |||
| 8094743f63 | |||
| 4bf53eb935 | |||
| b6b73d9a5a | |||
| c1bad4357a | |||
| ec28d3c439 | |||
| d84a93c987 | |||
| aee3b57c44 | |||
| 49bfd0c461 | |||
| 00213377b1 | |||
| db7abfecdd | |||
| 7f445a59fa | |||
| 3ead4a3494 | |||
| ea4b7226a6 | |||
| bb22d6d8f7 | |||
| ecacb002be | |||
| 922d5187c4 | |||
| 5068279f23 | |||
| 136e8e829f | |||
| 6418a42884 | |||
| e33ffdc555 | |||
| b4fc2e52a2 | |||
| 7331bb9d8d | |||
| f4fe71c1c9 | |||
| 342170fcd3 | |||
| 7361eac10f | |||
| c40e7593f5 | |||
| ea4e4b05e4 | |||
| 7626ca3343 | |||
| 3a6e2922a2 | |||
| 5153d5387a | |||
| b5d21cc1b1 | |||
| 41b1f8d616 | |||
| 12ef74456c | |||
| 5396593b55 | |||
| 7d86a6ff02 | |||
| 61f293e5c9 | |||
| 7f78b17e20 | |||
| 44556dc21a | |||
| a9d8e24e47 | |||
| 74f30c0223 | |||
| 20699e90fa | |||
| 2f1ef3910b | |||
| 60831eabd9 | |||
| 93bc59b62d | |||
| 339dc4f806 | |||
| b462618ed7 | |||
| e8269fe3bc | |||
| d001687ca6 | |||
| cd6dcef5aa | |||
| 0a74d8490a | |||
| af69b48390 | |||
| 440eb840ea | |||
| bfe8816f7c | |||
| acf22336ec | |||
| 9ec26a805a | |||
| d5131805ce | |||
| ad6e20cfde | |||
| e8d2de1f99 | |||
| a170aa16b6 | |||
| 049769a0c9 | |||
| 81a5ecdb18 | |||
| 9edfd88a8a | |||
| 9a07ed53eb | |||
| 06c410ee88 | |||
| ab2677f0a1 | |||
| 5a2b15bf75 | |||
| a1138028a8 | |||
| faaea00069 | |||
| 6c78c2ae38 | |||
| 4aac1ae4b1 | |||
| 59236b7d0f | |||
| e169fdad4f | |||
| 5bef54618a | |||
| a3e68dce56 | |||
| f20f4587e6 | |||
| edd498f6e0 | |||
| 85eeae7aad | |||
| 904584e4ba | |||
| fd7c273fab | |||
| 0949e38263 | |||
| 0ecb6c6647 | |||
| e12ee020e7 | |||
| c8707628f6 | |||
| 271f2e2d78 | |||
| 5a042bdaa1 | |||
| eee302b9b9 | |||
| 12d569e483 | |||
| fc086f93b2 | |||
| f2c26443f8 | |||
| b9f543b29f | |||
| 02547439b1 | |||
| 343d92a092 | |||
| 2c1e119c4a | |||
| 913971417e | |||
| 49c4c329f6 | |||
| 21671d05a3 | |||
| da25a59866 | |||
| 41928dfdda | |||
| 934b2d8842 | |||
| f54ea749a4 | |||
| c6de9657be | |||
| 44c763f9c6 | |||
| cfed6936f3 | |||
| 9f44a44f2f | |||
| 75f23ad494 | |||
| 7a06037c5f | |||
| ed25191ee6 | |||
| d08bd3e062 | |||
| 1b4331397b | |||
| 0aff3ba2ff | |||
| ec50a9b5b9 | |||
| fa647cc0b9 | |||
| bb7d4ec3d3 | |||
| 0c1bb46f0a | |||
| 648bef235e | |||
| f2b76284ed | |||
| b021e09fc0 | |||
| 751cc687bb | |||
| 2f62bae9e3 | |||
| 72a49c2bbc | |||
| faa067f175 | |||
| 3671fd0a97 | |||
| 8acf739b3f | |||
| 8f638e81e9 | |||
| da62e92784 | |||
| d57b12193b | |||
| b805ee653f | |||
| d2c4dbde9e | |||
| 2c4615f3a6 | |||
| a488b86e97 | |||
| 510f71d871 | |||
| 9f81221528 | |||
| eae107d0e9 | |||
| da22def511 | |||
| f23760b1e1 | |||
| 1e983b19df | |||
| ad5a5ef43f | |||
| e02785be83 | |||
| 27a6ef64fd | |||
| 9434603450 | |||
| 703d7aaab6 | |||
| 9beb239634 | |||
| 2cdc7142b0 | |||
| 34abe4a905 | |||
| f6d45b747e | |||
| 1b074b8984 | |||
| 50d2dc3b51 | |||
| d23f9f75ff | |||
| 4356361faf | |||
| 51aa5a5364 | |||
| 25538db150 | |||
| 9bae3992e6 | |||
| 91d8657959 | |||
| d3c166d4d5 | |||
| 0536004d91 | |||
| 57f80c74b6 | |||
| caa11748c6 | |||
| 7866eb03bb | |||
| 4b03e6e776 | |||
| 8f5052a514 | |||
| 0b27c721c9 | |||
| 2a7eff57a8 | |||
| bf380b8584 | |||
| 864841eb9e | |||
| 39a8dba9a6 | |||
| 626f746971 | |||
| 7a06864100 | |||
| 0297448fbc | |||
| aa2844bcf9 | |||
| b57c5a9b54 | |||
| 674122038a | |||
| 126aaeb6d3 | |||
| c7d8b7421c | |||
| 7444963bbb | |||
| 2cb6106523 | |||
| 76a0814142 | |||
| 84bb772003 | |||
| 269d233a94 | |||
| c2f6f2ba7a | |||
| 2e8d6fe9a0 | |||
| eba3bb9d21 | |||
| cfa7b92563 | |||
| 89edbe8aa2 | |||
| b6156e735c | |||
| ab704acab8 | |||
| 722195cf70 | |||
| addc0bf037 | |||
| 086db71e94 | |||
| 7ccbdd4d8d | |||
| 5e5933256b | |||
| da7e9553de | |||
| 6fca1c82fd | |||
| de4746ff69 | |||
| 0eeecde67c | |||
| 479bd50b96 | |||
| d3d0f2f451 | |||
| 34bed1ab41 | |||
| d9df63583f | |||
| 3401676768 | |||
| 02c2b28cd0 | |||
| 66f2ad716b | |||
| 74120c5e3a | |||
| f93d939426 | |||
| 34ce1dd7c7 | |||
| b8751630e2 | |||
| d9205f82b3 | |||
| b99fc70191 | |||
| 260b841dc3 | |||
| 0b7a03bd65 | |||
| 860d73637e | |||
| 8c30ed6d09 | |||
| cc47a6a9c2 | |||
| 403cf6be69 | |||
| 9e726a9250 | |||
| df51eb9bde | |||
| 898aa5fb66 | |||
| ebb64d5bf4 | |||
| 7d257ce7bd | |||
| 707ed72a3c | |||
| 08d5bd36d8 | |||
| 6e81473574 | |||
| c17a59b58e | |||
| 0d2d0844a5 | |||
| 01a57d4c8d | |||
| 1da72c7792 | |||
| 54dc22285b | |||
| 03b3c5800b | |||
| 07934f0e87 | |||
| 72b22fd433 | |||
| 1ed1dd3c89 | |||
| fa3ffff8de | |||
| aab57b7975 | |||
| 497ccfaedc | |||
| 922b0d9933 | |||
| bea6fca9a1 | |||
| fc84822266 | |||
| 29a06ad393 | |||
| e1a196cfd7 | |||
| 0af182baa2 | |||
| d95605cd24 | |||
| b096ec68cd | |||
| 724c19a307 | |||
| cfdec68d5a | |||
| 729545a946 | |||
| cd80471c90 | |||
| dec5680934 | |||
| 6a2084a204 | |||
| dcb91ca4a4 | |||
| 7412f314e4 | |||
| 3c5fb53634 | |||
| 609c11bab3 | |||
| 697a2c0018 | |||
| 3b5690c9e1 | |||
| 2ff39f6fdc | |||
| ae758a236f | |||
| 75e0d16caa | |||
| c413cafdac | |||
| 4c8c5ad1b6 | |||
| 98fb36cb0a | |||
| a02c4686c3 | |||
| 1acd807176 | |||
| f4610e77e2 | |||
| c19ad21ae8 | |||
| 04d9c27120 | |||
| 4cc8ab8a86 | |||
| 2e268abe42 | |||
| 51c787bfc1 | |||
| 1c65b3ee53 | |||
| 19bbdedf00 | |||
| d363b2c7d2 | |||
| 8805233f5e | |||
| 9c5248d101 | |||
| 502f3cef87 | |||
| 29cd40bded | |||
| 5ba49f188b | |||
| 6e2040c955 | |||
| ae93402312 | |||
| 80d74d77d5 | |||
| 5568fcfec1 | |||
| cdce1edf74 | |||
| d1e35a37be | |||
| ad55faaa35 | |||
| 86278f5db2 | |||
| 607ff3489c | |||
| f0c2190ceb | |||
| 956b2bd332 | |||
| ea78f9a2ef | |||
| 4cd6c3e6f1 | |||
| 8cdd86fa25 | |||
| 7083c5bfc8 | |||
| 6125590a7b | |||
| aaaca1cd6d | |||
| 17704271f4 | |||
| e5e9bee1cc | |||
| 0da84c4de8 | |||
| 17b7f0389a | |||
| 27eeb20001 | |||
| 9f39f7c041 | |||
| b7d04d848d | |||
| 39497183a6 | |||
| 8285776603 | |||
| a223006c50 | |||
| 9e7713c150 | |||
| 7d0d2af3fa | |||
| f973274b99 | |||
| de69a5266f | |||
| 2a2a578932 | |||
| b17f031e35 | |||
| ce921e0f26 | |||
| 51ca93981d | |||
| ba2c917842 | |||
| 9ad77ba6d3 | |||
| d5c1f3929c | |||
| 12e58917c0 | |||
| bb32a4a8d7 | |||
| edb1d5d242 | |||
| 7eff91ff20 | |||
| b45930a0ed | |||
| 4143675b2d | |||
| 4a5f9f5a6d | |||
| aa3adf6c3f | |||
| f6e6913f8f | |||
| e681723a4a | |||
| 578e6c5a57 | |||
| 5bc9f15c6d | |||
| a8c09cd5e4 | |||
| e3e6a11ab8 | |||
| 0a40106cf1 | |||
| d1e40dd244 | |||
| 0f40c8c634 | |||
| fd40d55a4f | |||
| bf1c1788ca |
@@ -8,7 +8,17 @@ cd /yuzu
|
||||
ccache -s
|
||||
|
||||
mkdir build || true && cd build
|
||||
cmake .. -DDISPLAY_VERSION=$1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_INSTALL_PREFIX="/usr"
|
||||
cmake .. \
|
||||
-DBoost_USE_STATIC_LIBS=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ \
|
||||
-DCMAKE_C_COMPILER=/usr/lib/ccache/gcc \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DDISPLAY_VERSION=$1 \
|
||||
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
|
||||
-DENABLE_QT_TRANSLATION=ON \
|
||||
-DUSE_DISCORD_PRESENCE=ON \
|
||||
-DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"}
|
||||
|
||||
make -j$(nproc)
|
||||
|
||||
@@ -20,10 +30,10 @@ make install DESTDIR=AppDir
|
||||
rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester
|
||||
|
||||
# Download tools needed to build an AppImage
|
||||
wget -nc https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
||||
wget -nc https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
|
||||
wget -nc https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/AppRun-patched-x86_64
|
||||
wget -nc https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/exec-x86_64.so
|
||||
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-x86_64.AppImage
|
||||
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-plugin-qt-x86_64.AppImage
|
||||
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/AppRun-patched-x86_64
|
||||
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/exec-x86_64.so
|
||||
# Set executable bit
|
||||
chmod 755 \
|
||||
AppRun-patched-x86_64 \
|
||||
|
||||
@@ -21,7 +21,7 @@ cp build/bin/yuzu "$DIR_NAME"
|
||||
# Build an AppImage
|
||||
cd build
|
||||
|
||||
wget -nc https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/appimagetool-x86_64.AppImage
|
||||
chmod 755 appimagetool-x86_64.AppImage
|
||||
|
||||
if [ "${RELEASE_NAME}" = "mainline" ]; then
|
||||
|
||||
@@ -47,3 +47,6 @@ python3 .ci/scripts/windows/scan_dll.py package/imageformats/*.dll "package/"
|
||||
EXTERNALS_PATH="$(pwd)/build/externals"
|
||||
FFMPEG_DLL_PATH="$(find ${EXTERNALS_PATH} -maxdepth 1 -type d | grep ffmpeg)/bin"
|
||||
find ${FFMPEG_DLL_PATH} -type f -regex ".*\.dll" -exec cp -v {} package/ ';'
|
||||
|
||||
# copy libraries from yuzu.exe path
|
||||
find "$(pwd)/build/bin/" -type f -regex ".*\.dll" -exec cp -v {} package/ ';'
|
||||
|
||||
@@ -8,7 +8,7 @@ steps:
|
||||
displayName: 'Install vulkan-sdk'
|
||||
- script: python -m pip install --upgrade pip conan
|
||||
displayName: 'Install conan'
|
||||
- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 16 2019" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} .. && cmake --install . --config Release && cd ..
|
||||
- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 16 2019" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release .. && cd ..
|
||||
displayName: 'Configure CMake'
|
||||
- task: MSBuild@1
|
||||
displayName: 'Build'
|
||||
|
||||
@@ -40,3 +40,6 @@
|
||||
[submodule "ffmpeg"]
|
||||
path = externals/ffmpeg
|
||||
url = https://git.ffmpeg.org/ffmpeg.git
|
||||
[submodule "SDL"]
|
||||
path = externals/SDL
|
||||
url = https://github.com/libsdl-org/SDL.git
|
||||
|
||||
@@ -12,14 +12,18 @@ project(yuzu)
|
||||
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
|
||||
option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF)
|
||||
# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion
|
||||
option(YUZU_ALLOW_SYSTEM_SDL2 "Try using system SDL2 before fallling back to one from externals" OFF)
|
||||
|
||||
option(ENABLE_QT "Enable the Qt frontend" ON)
|
||||
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" ON "ENABLE_QT;MSVC" OFF)
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF)
|
||||
|
||||
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
|
||||
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled yuzu" ON "WIN32" OFF)
|
||||
option(YUZU_USE_BUNDLED_BOOST "Download bundled Boost" OFF)
|
||||
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" ON "WIN32" OFF)
|
||||
|
||||
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
|
||||
|
||||
@@ -170,7 +174,7 @@ macro(yuzu_find_packages)
|
||||
"lz4 1.8 lz4/1.9.2"
|
||||
"nlohmann_json 3.8 nlohmann_json/3.8.0"
|
||||
"ZLIB 1.2 zlib/1.2.11"
|
||||
"zstd 1.4 zstd/1.4.8"
|
||||
"zstd 1.5 zstd/1.5.0"
|
||||
# can't use opus until AVX check is fixed: https://github.com/yuzu-emu/yuzu/pull/4068
|
||||
#"opus 1.3 opus/1.3.1"
|
||||
)
|
||||
@@ -199,7 +203,9 @@ macro(yuzu_find_packages)
|
||||
unset(FN_FORCE_REQUIRED)
|
||||
endmacro()
|
||||
|
||||
find_package(Boost 1.73.0 COMPONENTS context headers QUIET)
|
||||
if (NOT YUZU_USE_BUNDLED_BOOST)
|
||||
find_package(Boost 1.73.0 CONFIG COMPONENTS context headers QUIET)
|
||||
endif()
|
||||
if (Boost_FOUND)
|
||||
set(Boost_LIBRARIES Boost::boost)
|
||||
# Conditionally add Boost::context only if the active version of the Conan or system Boost package provides it
|
||||
@@ -210,6 +216,20 @@ if (Boost_FOUND)
|
||||
if (TARGET Boost::context)
|
||||
list(APPEND Boost_LIBRARIES Boost::context)
|
||||
endif()
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR YUZU_USE_BUNDLED_BOOST)
|
||||
message(STATUS "Boost 1.73.0 or newer not found, falling back to externals")
|
||||
set(YUZU_USE_BUNDLED_BOOST ON CACHE BOOL "Download bundled Boost" FORCE)
|
||||
|
||||
# Use yuzu Boost binaries
|
||||
set(Boost_EXT_NAME "boost_1_75_0")
|
||||
set(Boost_PATH "${CMAKE_BINARY_DIR}/externals/${Boost_EXT_NAME}")
|
||||
download_bundled_external("boost/" ${Boost_EXT_NAME} "")
|
||||
set(Boost_USE_DEBUG_RUNTIME FALSE)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
find_package(Boost 1.75.0 CONFIG REQUIRED COMPONENTS context headers PATHS ${Boost_PATH} NO_DEFAULT_PATH)
|
||||
# Manually set the include dirs since the find_package sets it incorrectly
|
||||
set(Boost_INCLUDE_DIRS ${Boost_PATH}/include CACHE PATH "Path to Boost headers" FORCE)
|
||||
include_directories(SYSTEM "${Boost_INCLUDE_DIRS}")
|
||||
else()
|
||||
message(STATUS "Boost 1.73.0 or newer not found, falling back to Conan")
|
||||
list(APPEND CONAN_REQUIRED_LIBS "boost/1.73.0")
|
||||
@@ -220,6 +240,7 @@ yuzu_find_packages()
|
||||
|
||||
# Qt5 requires that we find components, so it doesn't fit our pretty little find package function
|
||||
if(ENABLE_QT)
|
||||
set(QT_VERSION 5.12)
|
||||
# We want to load the generated conan qt config so that we get the QT_ROOT var so that we can use the official
|
||||
# Qt5Config inside the root folder instead of the conan generated one.
|
||||
if(EXISTS ${CMAKE_BINARY_DIR}/qtConfig.cmake)
|
||||
@@ -227,22 +248,40 @@ if(ENABLE_QT)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CONAN_QT_ROOT_RELEASE}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${CONAN_QT_ROOT_RELEASE}")
|
||||
endif()
|
||||
|
||||
# Check for system Qt on Linux, fallback to bundled Qt
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
if (NOT YUZU_USE_BUNDLED_QT)
|
||||
find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets QUIET)
|
||||
if (NOT Qt5_FOUND)
|
||||
set(YUZU_USE_BUNDLED_QT ON CACHE BOOL "Download bundled Qt" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
if (YUZU_USE_BUNDLED_QT)
|
||||
# Binary package currently does not support Qt webengine, so make sure it's disabled
|
||||
set(YUZU_USE_QT_WEB_ENGINE OFF CACHE BOOL "Use Qt Webengine" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Workaround for an issue where conan tries to build Qt from scratch instead of download prebuilt binaries
|
||||
set(QT_PREFIX_HINT)
|
||||
|
||||
if(YUZU_USE_BUNDLED_QT)
|
||||
if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64)
|
||||
set(QT_VER qt-5.12.8-msvc2017_64)
|
||||
set(QT_BUILD qt-5.12.8-msvc2017_64)
|
||||
elseif ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux") AND NOT MINGW AND ARCHITECTURE_x86_64)
|
||||
set(QT_BUILD qt5_5_15_2)
|
||||
else()
|
||||
message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable YUZU_USE_BUNDLED_QT and provide your own.")
|
||||
endif()
|
||||
|
||||
if (DEFINED QT_VER)
|
||||
download_bundled_external("qt/" ${QT_VER} QT_PREFIX)
|
||||
if (DEFINED QT_BUILD)
|
||||
download_bundled_external("qt/" ${QT_BUILD} QT_PREFIX)
|
||||
endif()
|
||||
|
||||
set(QT_PREFIX_HINT HINTS "${QT_PREFIX}")
|
||||
endif()
|
||||
find_package(Qt5 5.9 COMPONENTS Widgets ${QT_PREFIX_HINT})
|
||||
find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets ${QT_PREFIX_HINT} NO_CMAKE_SYSTEM_PATH)
|
||||
if (YUZU_USE_QT_WEB_ENGINE)
|
||||
find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets)
|
||||
endif()
|
||||
@@ -251,12 +290,13 @@ if(ENABLE_QT)
|
||||
find_package(Qt5 REQUIRED COMPONENTS LinguistTools ${QT_PREFIX_HINT})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the yuzu_find_package
|
||||
if (ENABLE_SDL2)
|
||||
if (YUZU_USE_BUNDLED_SDL2)
|
||||
# Detect toolchain and platform
|
||||
if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64)
|
||||
set(SDL2_VER "SDL2-2.0.14")
|
||||
set(SDL2_VER "SDL2-2.0.15-prerelease")
|
||||
else()
|
||||
message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable YUZU_USE_BUNDLED_SDL2 and provide your own.")
|
||||
endif()
|
||||
@@ -274,20 +314,26 @@ if (ENABLE_SDL2)
|
||||
target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}")
|
||||
target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}")
|
||||
else()
|
||||
find_package(SDL2 REQUIRED)
|
||||
if (YUZU_ALLOW_SYSTEM_SDL2)
|
||||
find_package(SDL2 2.0.15 QUIET)
|
||||
|
||||
# Some installations don't set SDL2_LIBRARIES
|
||||
if("${SDL2_LIBRARIES}" STREQUAL "")
|
||||
message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2")
|
||||
set(SDL2_LIBRARIES "SDL2::SDL2")
|
||||
if (SDL2_FOUND)
|
||||
# Some installations don't set SDL2_LIBRARIES
|
||||
if("${SDL2_LIBRARIES}" STREQUAL "")
|
||||
message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2")
|
||||
set(SDL2_LIBRARIES "SDL2::SDL2")
|
||||
endif()
|
||||
|
||||
include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
|
||||
add_library(SDL2 INTERFACE)
|
||||
target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}")
|
||||
else()
|
||||
message(STATUS "SDL2 2.0.15 or newer not found, falling back to externals.")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Using SDL2 from externals.")
|
||||
endif()
|
||||
|
||||
include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
|
||||
add_library(SDL2 INTERFACE)
|
||||
target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}")
|
||||
endif()
|
||||
else()
|
||||
set(SDL2_FOUND NO)
|
||||
endif()
|
||||
|
||||
# Install any missing dependencies with conan install
|
||||
@@ -353,7 +399,7 @@ if (CONAN_REQUIRED_LIBS)
|
||||
if(ENABLE_QT)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CONAN_QT_ROOT_RELEASE}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${CONAN_QT_ROOT_RELEASE}")
|
||||
find_package(Qt5 5.9 REQUIRED COMPONENTS Widgets)
|
||||
find_package(Qt5 5.12 REQUIRED COMPONENTS Widgets)
|
||||
if (YUZU_USE_QT_WEB_ENGINE)
|
||||
find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets)
|
||||
endif()
|
||||
@@ -380,7 +426,7 @@ if(NOT APPLE)
|
||||
endif()
|
||||
if (NOT LIBUSB_FOUND)
|
||||
add_subdirectory(externals/libusb)
|
||||
set(LIBUSB_INCLUDE_DIR "")
|
||||
set(LIBUSB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/externals/libusb/libusb/libusb")
|
||||
set(LIBUSB_LIBRARIES usb)
|
||||
endif()
|
||||
|
||||
@@ -392,7 +438,7 @@ set(FFmpeg_COMPONENTS
|
||||
|
||||
if (NOT YUZU_USE_BUNDLED_FFMPEG)
|
||||
# Use system installed FFmpeg
|
||||
find_package(FFmpeg REQUIRED COMPONENTS ${FFmpeg_COMPONENTS})
|
||||
find_package(FFmpeg QUIET COMPONENTS ${FFmpeg_COMPONENTS})
|
||||
|
||||
if (FFmpeg_FOUND)
|
||||
# Overwrite aggregate defines from FFmpeg module to avoid over-linking libraries.
|
||||
@@ -431,6 +477,7 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
set(FFmpeg_FOUND YES)
|
||||
endif()
|
||||
|
||||
unset(FFmpeg_LIBRARIES CACHE)
|
||||
foreach(COMPONENT ${FFmpeg_COMPONENTS})
|
||||
set(FFmpeg_${COMPONENT}_PREFIX "${FFmpeg_BUILD_DIR}/lib${COMPONENT}")
|
||||
set(FFmpeg_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a")
|
||||
@@ -443,7 +490,7 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
endforeach()
|
||||
|
||||
set(FFmpeg_INCLUDE_DIR
|
||||
${FFmpeg_PREFIX}
|
||||
"${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR}"
|
||||
CACHE PATH "Path to FFmpeg headers" FORCE)
|
||||
|
||||
# `configure` parameters builds only exactly what yuzu needs from FFmpeg
|
||||
@@ -490,13 +537,11 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
|
||||
# ALL makes this custom target build every time
|
||||
# but it won't actually build if the DEPENDS parameter is up to date
|
||||
add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_LIBRARIES})
|
||||
add_custom_target(ffmpeg-configure ALL DEPENDS ${FFmpeg_MAKEFILE})
|
||||
add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_LIBRARIES} ffmpeg-configure)
|
||||
|
||||
if (FFmpeg_FOUND)
|
||||
message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
|
||||
|
||||
add_dependencies(ffmpeg-build ffmpeg-configure)
|
||||
else()
|
||||
message(FATAL_ERROR "FFmpeg not found")
|
||||
endif()
|
||||
|
||||
@@ -1,52 +1,111 @@
|
||||
function(copy_yuzu_Qt5_deps target_dir)
|
||||
include(WindowsCopyFiles)
|
||||
set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/")
|
||||
set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin")
|
||||
if (MSVC)
|
||||
set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/")
|
||||
set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin")
|
||||
else()
|
||||
set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/")
|
||||
set(Qt5_DLL_DIR "${Qt5_DIR}/../../../lib/")
|
||||
endif()
|
||||
set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/")
|
||||
set(Qt5_PLATFORMTHEMES_DIR "${Qt5_DIR}/../../../plugins/platformthemes/")
|
||||
set(Qt5_PLATFORMINPUTCONTEXTS_DIR "${Qt5_DIR}/../../../plugins/platforminputcontexts/")
|
||||
set(Qt5_XCBGLINTEGRATIONS_DIR "${Qt5_DIR}/../../../plugins/xcbglintegrations/")
|
||||
set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/")
|
||||
set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/")
|
||||
set(Qt5_RESOURCES_DIR "${Qt5_DIR}/../../../resources/")
|
||||
set(PLATFORMS ${DLL_DEST}plugins/platforms/)
|
||||
set(STYLES ${DLL_DEST}plugins/styles/)
|
||||
set(IMAGEFORMATS ${DLL_DEST}plugins/imageformats/)
|
||||
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
|
||||
icudt*.dll
|
||||
icuin*.dll
|
||||
icuuc*.dll
|
||||
Qt5Core$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Gui$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Widgets$<$<CONFIG:Debug>:d>.*
|
||||
)
|
||||
|
||||
if (YUZU_USE_QT_WEB_ENGINE)
|
||||
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
|
||||
Qt5Network$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Positioning$<$<CONFIG:Debug>:d>.*
|
||||
Qt5PrintSupport$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Qml$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Quick$<$<CONFIG:Debug>:d>.*
|
||||
Qt5QuickWidgets$<$<CONFIG:Debug>:d>.*
|
||||
Qt5WebChannel$<$<CONFIG:Debug>:d>.*
|
||||
Qt5WebEngine$<$<CONFIG:Debug>:d>.*
|
||||
Qt5WebEngineCore$<$<CONFIG:Debug>:d>.*
|
||||
Qt5WebEngineWidgets$<$<CONFIG:Debug>:d>.*
|
||||
QtWebEngineProcess$<$<CONFIG:Debug>:d>.*
|
||||
if (MSVC)
|
||||
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
|
||||
icudt*.dll
|
||||
icuin*.dll
|
||||
icuuc*.dll
|
||||
Qt5Core$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Gui$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Widgets$<$<CONFIG:Debug>:d>.*
|
||||
)
|
||||
|
||||
windows_copy_files(${target_dir} ${Qt5_RESOURCES_DIR} ${DLL_DEST}
|
||||
qtwebengine_resources.pak
|
||||
qtwebengine_devtools_resources.pak
|
||||
qtwebengine_resources_100p.pak
|
||||
qtwebengine_resources_200p.pak
|
||||
icudtl.dat
|
||||
)
|
||||
endif ()
|
||||
windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
|
||||
windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*)
|
||||
windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS}
|
||||
qjpeg$<$<CONFIG:Debug>:d>.*
|
||||
qgif$<$<CONFIG:Debug>:d>.*
|
||||
)
|
||||
if (YUZU_USE_QT_WEB_ENGINE)
|
||||
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
|
||||
Qt5Network$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Positioning$<$<CONFIG:Debug>:d>.*
|
||||
Qt5PrintSupport$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Qml$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Quick$<$<CONFIG:Debug>:d>.*
|
||||
Qt5QuickWidgets$<$<CONFIG:Debug>:d>.*
|
||||
Qt5WebChannel$<$<CONFIG:Debug>:d>.*
|
||||
Qt5WebEngine$<$<CONFIG:Debug>:d>.*
|
||||
Qt5WebEngineCore$<$<CONFIG:Debug>:d>.*
|
||||
Qt5WebEngineWidgets$<$<CONFIG:Debug>:d>.*
|
||||
QtWebEngineProcess$<$<CONFIG:Debug>:d>.*
|
||||
)
|
||||
|
||||
windows_copy_files(${target_dir} ${Qt5_RESOURCES_DIR} ${DLL_DEST}
|
||||
qtwebengine_resources.pak
|
||||
qtwebengine_devtools_resources.pak
|
||||
qtwebengine_resources_100p.pak
|
||||
qtwebengine_resources_200p.pak
|
||||
icudtl.dat
|
||||
)
|
||||
endif ()
|
||||
windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
|
||||
windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*)
|
||||
windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS}
|
||||
qjpeg$<$<CONFIG:Debug>:d>.*
|
||||
qgif$<$<CONFIG:Debug>:d>.*
|
||||
)
|
||||
else()
|
||||
set(Qt5_DLLS
|
||||
"${Qt5_DLL_DIR}libQt5Core.so.5"
|
||||
"${Qt5_DLL_DIR}libQt5DBus.so.5"
|
||||
"${Qt5_DLL_DIR}libQt5Gui.so.5"
|
||||
"${Qt5_DLL_DIR}libQt5Widgets.so.5"
|
||||
"${Qt5_DLL_DIR}libQt5XcbQpa.so.5"
|
||||
"${Qt5_DLL_DIR}libicudata.so.60"
|
||||
"${Qt5_DLL_DIR}libicui18n.so.60"
|
||||
"${Qt5_DLL_DIR}libicuuc.so.60"
|
||||
)
|
||||
set(Qt5_IMAGEFORMAT_DLLS
|
||||
"${Qt5_IMAGEFORMATS_DIR}libqjpeg.so"
|
||||
"${Qt5_IMAGEFORMATS_DIR}libqgif.so"
|
||||
"${Qt5_IMAGEFORMATS_DIR}libqico.so"
|
||||
)
|
||||
set(Qt5_PLATFORMTHEME_DLLS
|
||||
"${Qt5_PLATFORMTHEMES_DIR}libqgtk3.so"
|
||||
"${Qt5_PLATFORMTHEMES_DIR}libqxdgdesktopportal.so"
|
||||
)
|
||||
set(Qt5_PLATFORM_DLLS
|
||||
"${Qt5_PLATFORMS_DIR}libqxcb.so"
|
||||
)
|
||||
set(Qt5_PLATFORMINPUTCONTEXT_DLLS
|
||||
"${Qt5_PLATFORMINPUTCONTEXTS_DIR}libcomposeplatforminputcontextplugin.so"
|
||||
"${Qt5_PLATFORMINPUTCONTEXTS_DIR}libibusplatforminputcontextplugin.so"
|
||||
)
|
||||
set(Qt5_XCBGLINTEGRATION_DLLS
|
||||
"${Qt5_XCBGLINTEGRATIONS_DIR}libqxcb-glx-integration.so"
|
||||
)
|
||||
foreach(LIB ${Qt5_DLLS})
|
||||
file(COPY ${LIB} DESTINATION "${DLL_DEST}/lib" FOLLOW_SYMLINK_CHAIN)
|
||||
endforeach()
|
||||
foreach(LIB ${Qt5_IMAGEFORMAT_DLLS})
|
||||
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/imageformats/" FOLLOW_SYMLINK_CHAIN)
|
||||
endforeach()
|
||||
foreach(LIB ${Qt5_PLATFORMTHEME_DLLS})
|
||||
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/platformthemes/" FOLLOW_SYMLINK_CHAIN)
|
||||
endforeach()
|
||||
foreach(LIB ${Qt5_PLATFORM_DLLS})
|
||||
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/platforms/" FOLLOW_SYMLINK_CHAIN)
|
||||
endforeach()
|
||||
foreach(LIB ${Qt5_PLATFORMINPUTCONTEXT_DLLS})
|
||||
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/platforminputcontexts/" FOLLOW_SYMLINK_CHAIN)
|
||||
endforeach()
|
||||
foreach(LIB ${Qt5_XCBGLINTEGRATION_DLLS})
|
||||
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/xcbglintegrations/" FOLLOW_SYMLINK_CHAIN)
|
||||
endforeach()
|
||||
|
||||
endif()
|
||||
# Create an empty qt.conf file. Qt will detect that this file exists, and use the folder that its in as the root folder.
|
||||
# This way it'll look for plugins in the root/plugins/ folder
|
||||
add_custom_command(TARGET yuzu POST_BUILD
|
||||
|
||||
@@ -4,15 +4,29 @@
|
||||
# remote_path: path to the file to download, relative to the remote repository root
|
||||
# prefix_var: name of a variable which will be set with the path to the extracted contents
|
||||
function(download_bundled_external remote_path lib_name prefix_var)
|
||||
|
||||
set(package_repo "no_platform")
|
||||
set(package_extension "no_platform")
|
||||
if (WIN32)
|
||||
set(package_repo "ext-windows-bin/raw/master/")
|
||||
set(package_extension ".7z")
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
set(package_repo "ext-linux-bin/raw/main/")
|
||||
set(package_extension ".tar.xz")
|
||||
else()
|
||||
message(FATAL_ERROR "No package available for this platform")
|
||||
endif()
|
||||
set(package_url "https://github.com/yuzu-emu/${package_repo}")
|
||||
|
||||
set(prefix "${CMAKE_BINARY_DIR}/externals/${lib_name}")
|
||||
if (NOT EXISTS "${prefix}")
|
||||
message(STATUS "Downloading binaries for ${lib_name}...")
|
||||
file(DOWNLOAD
|
||||
https://github.com/yuzu-emu/ext-windows-bin/raw/master/${remote_path}${lib_name}.7z
|
||||
"${CMAKE_BINARY_DIR}/externals/${lib_name}.7z" SHOW_PROGRESS)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${CMAKE_BINARY_DIR}/externals/${lib_name}.7z"
|
||||
${package_url}${remote_path}${lib_name}${package_extension}
|
||||
"${CMAKE_BINARY_DIR}/externals/${lib_name}${package_extension}" SHOW_PROGRESS)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${CMAKE_BINARY_DIR}/externals/${lib_name}${package_extension}"
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
|
||||
endif()
|
||||
message(STATUS "Using bundled binaries at ${prefix}")
|
||||
set(${prefix_var} "${prefix}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
endfunction()
|
||||
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 712 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 683 B |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 796 B |
|
After Width: | Height: | Size: 745 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 936 B |
|
After Width: | Height: | Size: 894 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,64 @@
|
||||
<RCC>
|
||||
<qresource prefix="overlay">
|
||||
<file>arrow_left.png</file>
|
||||
<file>arrow_left_dark.png</file>
|
||||
<file>arrow_right.png</file>
|
||||
<file>arrow_right_dark.png</file>
|
||||
<file>button_minus.png</file>
|
||||
<file>button_minus_dark.png</file>
|
||||
<file>button_plus.png</file>
|
||||
<file>button_plus_dark.png</file>
|
||||
<file>button_A.png</file>
|
||||
<file>button_A_dark.png</file>
|
||||
<file>button_B.png</file>
|
||||
<file>button_B_dark.png</file>
|
||||
<file>button_X.png</file>
|
||||
<file>button_X_dark.png</file>
|
||||
<file>button_Y.png</file>
|
||||
<file>button_Y_dark.png</file>
|
||||
<file>button_L.png</file>
|
||||
<file>button_L_dark.png</file>
|
||||
<file>button_R.png</file>
|
||||
<file>button_R_dark.png</file>
|
||||
<file>button_press_stick.png</file>
|
||||
<file>button_press_stick_dark.png</file>
|
||||
<file>osk_button_B.png</file>
|
||||
<file>osk_button_B_disabled.png</file>
|
||||
<file>osk_button_B_dark.png</file>
|
||||
<file>osk_button_B_dark_disabled.png</file>
|
||||
<file>osk_button_Y.png</file>
|
||||
<file>osk_button_Y_disabled.png</file>
|
||||
<file>osk_button_Y_dark.png</file>
|
||||
<file>osk_button_Y_dark_disabled.png</file>
|
||||
<file>osk_button_backspace.png</file>
|
||||
<file>osk_button_backspace_dark.png</file>
|
||||
<file>osk_button_plus.png</file>
|
||||
<file>osk_button_plus_disabled.png</file>
|
||||
<file>osk_button_plus_dark.png</file>
|
||||
<file>osk_button_plus_dark_disabled.png</file>
|
||||
<file>osk_button_shift.png</file>
|
||||
<file>osk_button_shift_dark.png</file>
|
||||
<file>osk_button_shift_on.png</file>
|
||||
<file>osk_button_shift_on_dark.png</file>
|
||||
<file>osk_button_shift_lock_on.png</file>
|
||||
<file>osk_button_shift_lock_off.png</file>
|
||||
<file>controller_dual_joycon.png</file>
|
||||
<file>controller_dual_joycon_dark.png</file>
|
||||
<file>controller_pro.png</file>
|
||||
<file>controller_pro_dark.png</file>
|
||||
<file>controller_handheld.png</file>
|
||||
<file>controller_handheld_dark.png</file>
|
||||
<file>controller_single_joycon_left.png</file>
|
||||
<file>controller_single_joycon_left_dark.png</file>
|
||||
<file>controller_single_joycon_right.png</file>
|
||||
<file>controller_single_joycon_right_dark.png</file>
|
||||
<file>controller_single_joycon_left_a.png</file>
|
||||
<file>controller_single_joycon_left_a_dark.png</file>
|
||||
<file>controller_single_joycon_left_b.png</file>
|
||||
<file>controller_single_joycon_left_b_dark.png</file>
|
||||
<file>controller_single_joycon_left_x.png</file>
|
||||
<file>controller_single_joycon_left_x_dark.png</file>
|
||||
<file>controller_single_joycon_left_y.png</file>
|
||||
<file>controller_single_joycon_left_y_dark.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -12,6 +12,7 @@ qt_themes/default/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
||||
qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/48x48/star.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io
|
||||
qt_themes/qdarkstyle/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
@@ -20,6 +21,7 @@ qt_themes/qdarkstyle/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
||||
qt_themes/qdarkstyle/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/48x48/star.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/colorful/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/colorful/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io
|
||||
qt_themes/colorful/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
@@ -28,5 +30,6 @@ qt_themes/colorful/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/colorful/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/colorful/icons/48x48/plus.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/colorful/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/colorful/icons/48x48/star.png | CC BY-ND 3.0 | https://icons8.com
|
||||
|
||||
<!-- TODO: Add the license of the yuzu icon -->
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -7,6 +7,7 @@
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="colorful">
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||
<file alias="256x256/yuzu.png">icons/256x256/yuzu.png</file>
|
||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||
</qresource>
|
||||
|
||||
|
After Width: | Height: | Size: 686 B |
@@ -281,3 +281,370 @@ QWidget#controllerPlayer7,
|
||||
QWidget#controllerPlayer8 {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog,
|
||||
QStackedWidget#topOSK {
|
||||
background: rgba(51, 51, 51, .9);
|
||||
}
|
||||
|
||||
|
||||
QDialog#OverlayDialog,
|
||||
QStackedWidget#stackedDialog {
|
||||
background: rgba(51, 51, 51, .7);
|
||||
}
|
||||
|
||||
QWidget#boxOSK,
|
||||
QWidget#lineOSK,
|
||||
QWidget#richDialog,
|
||||
QWidget#lineDialog {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QStackedWidget#bottomOSK,
|
||||
QWidget#contentDialog,
|
||||
QWidget#contentRichDialog {
|
||||
background: rgba(240, 240, 240, 1);
|
||||
}
|
||||
|
||||
QWidget#contentDialog,
|
||||
QWidget#contentRichDialog {
|
||||
margin: 5px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
QWidget#buttonsDialog,
|
||||
QWidget#buttonsRichDialog {
|
||||
margin: 5px;
|
||||
border-top: 2px solid rgba(44, 44, 44, 1);
|
||||
}
|
||||
|
||||
QWidget#legendOSKnum {
|
||||
border-top: 1px solid rgba(44, 44, 44, 1);
|
||||
}
|
||||
|
||||
QStackedWidget#stackedDialog QTextBrowser QScrollBar::vertical {
|
||||
background: #cdcdcd;
|
||||
width: 15px;
|
||||
margin: 15px 3px 15px 3px;
|
||||
border: 1px transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
QStackedWidget#stackedDialog QTextBrowser QScrollBar::horizoncal {
|
||||
background: #cdcdcd;
|
||||
height: 15px;
|
||||
margin: 3px 15px 3px 15px;
|
||||
border: 1px transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
QStackedWidget#stackedDialog QTextBrowser QScrollBar::handle {
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
min-height: 5px;
|
||||
min-width: 5px;
|
||||
}
|
||||
|
||||
QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line,
|
||||
QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line,
|
||||
QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-page,
|
||||
QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-page {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QWidget#inputOSK {
|
||||
border-bottom: 3px solid rgba(255, 255, 255, .9);
|
||||
}
|
||||
|
||||
QWidget#inputOSK QLineEdit {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
QWidget#inputBoxOSK {
|
||||
border: 2px solid rgba(255, 255, 255, .9);
|
||||
}
|
||||
|
||||
QWidget#inputBoxOSK QTextEdit {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
QWidget#richDialog QTextBrowser {
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 35px 65px;
|
||||
}
|
||||
|
||||
|
||||
QWidget#lineOSK QLabel#label_header {
|
||||
color: #f0f0f0;
|
||||
}
|
||||
|
||||
QWidget#lineOSK QLabel#label_sub,
|
||||
QWidget#lineOSK QLabel#label_characters,
|
||||
QWidget#boxOSK QLabel#label_characters_box {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
QWidget#contentDialog QLabel#label_title,
|
||||
QWidget#contentRichDialog QLabel#label_title_rich {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
QWidget#contentDialog QLabel#label_dialog {
|
||||
padding: 20px 65px;
|
||||
}
|
||||
|
||||
QWidget#contentDialog QLabel#label_title,
|
||||
QWidget#contentRichDialog QLabel#label_title_rich {
|
||||
padding: 0px 65px;
|
||||
}
|
||||
|
||||
QDialog#OverlayDialog QPushButton {
|
||||
color: rgba(49, 79, 239, 1);
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0px;
|
||||
min-width: 0px;
|
||||
}
|
||||
|
||||
QDialog#OverlayDialog QPushButton:focus,
|
||||
QDialog#OverlayDialog QPushButton:hover {
|
||||
color: rgba(49, 79, 239, 1);
|
||||
background: rgba(255, 255, 255, 1);
|
||||
border: 5px solid rgba(148, 250, 202, 1);
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
QDialog#OverlayDialog QPushButton:pressed {
|
||||
color: rgba(240, 240, 240, 1);
|
||||
background: rgba(150, 150, 150, 1);
|
||||
border: 5px solid rgba(148, 250, 202, 1);
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton {
|
||||
background: rgba(232, 232, 232, 1);
|
||||
border: 2px solid rgba(240, 240, 240, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
|
||||
background: rgba(218, 218, 218, 1);
|
||||
border: 2px solid rgba(240, 240, 240, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
|
||||
color: rgba(240, 240, 240, 1);
|
||||
background: rgba(44, 44, 44, 1);
|
||||
border: 2px solid rgba(240, 240, 240, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
|
||||
color: rgba(240, 240, 240, 1);
|
||||
background: rgba(49, 79, 239, 1);
|
||||
border: 2px solid rgba(240, 240, 240, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus,
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover {
|
||||
color: rgba(0, 0, 0, 1);
|
||||
background: rgba(255, 255, 255, 1);
|
||||
border: 5px solid rgba(148, 250, 202, 1);
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed {
|
||||
color: rgba(240, 240, 240, 1);
|
||||
background: rgba(150, 150, 150, 1);
|
||||
border: 5px solid rgba(148, 250, 202, 1);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
|
||||
image: url(:/overlay/osk_button_B.png);
|
||||
image-position: right;
|
||||
qproperty-icon: url(:/overlay/osk_button_backspace.png);
|
||||
qproperty-iconSize: 36px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
|
||||
image: url(:/overlay/osk_button_Y.png);
|
||||
image-position: right;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
|
||||
image: url(:/overlay/osk_button_plus.png);
|
||||
image-position: right;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift {
|
||||
image: url(:/overlay/osk_button_shift_lock_off.png);
|
||||
image-position: left;
|
||||
qproperty-icon: url(:/overlay/osk_button_shift.png);
|
||||
qproperty-iconSize: 36px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift {
|
||||
image: url(:/overlay/osk_button_shift_lock_off.png);
|
||||
image-position: left;
|
||||
qproperty-icon: url(:/overlay/osk_button_shift_on.png);
|
||||
qproperty-iconSize: 36px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis {
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel {
|
||||
background: transparent;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_L,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num {
|
||||
image: url(:/overlay/button_L.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num {
|
||||
image: url(:/overlay/arrow_left.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_R,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num {
|
||||
image: url(:/overlay/button_R.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num {
|
||||
image: url(:/overlay/arrow_right.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift {
|
||||
image: url(:/overlay/button_press_stick.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_X,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num {
|
||||
image: url(:/overlay/button_X.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_A,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num {
|
||||
image: url(:/overlay/button_A.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
|
||||
color: rgba(164, 164, 164, 1);
|
||||
background-color: rgba(218, 218, 218, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled {
|
||||
color: rgba(164, 164, 164, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled {
|
||||
image: url(:/overlay/osk_button_plus_disabled.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
|
||||
image: url(:/overlay/osk_button_B_disabled.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled {
|
||||
image: url(:/overlay/osk_button_Y_disabled.png);
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 725 B |
@@ -8,6 +8,7 @@
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="qss_icons">
|
||||
|
||||
@@ -1560,7 +1560,390 @@ QWidget#controllerPlayer8 {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* touchscreen mapping widget */
|
||||
TouchScreenPreview {
|
||||
qproperty-dotHighlightColor: #3daee9;
|
||||
QDialog#QtSoftwareKeyboardDialog,
|
||||
QStackedWidget#topOSK {
|
||||
background: rgba(41, 41, 41, .9);
|
||||
}
|
||||
|
||||
|
||||
QDialog#OverlayDialog,
|
||||
QStackedWidget#stackedDialog {
|
||||
background: rgba(41, 41, 41, .7);
|
||||
}
|
||||
|
||||
QWidget#boxOSK,
|
||||
QWidget#lineOSK,
|
||||
QWidget#richDialog,
|
||||
QWidget#lineDialog {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QStackedWidget#bottomOSK,
|
||||
QWidget#contentDialog,
|
||||
QWidget#contentRichDialog {
|
||||
background: rgba(71, 69, 71, 1);
|
||||
}
|
||||
|
||||
QWidget#contentDialog,
|
||||
QWidget#contentRichDialog {
|
||||
margin: 5px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
QWidget#buttonsDialog,
|
||||
QWidget#buttonsRichDialog {
|
||||
margin: 5px;
|
||||
border-top: 2px solid rgba(255, 255, 255, .9);
|
||||
}
|
||||
|
||||
QWidget#legendOSKnum {
|
||||
border-top: 1px solid rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
QStackedWidget#stackedDialog QTextBrowser QWidget {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QStackedWidget#stackedDialog QTextBrowser QScrollBar {
|
||||
background: #2a2929;
|
||||
}
|
||||
|
||||
QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line,
|
||||
QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line {
|
||||
border-image: none;
|
||||
}
|
||||
|
||||
QWidget#inputOSK {
|
||||
border-bottom: 3px solid rgba(255, 255, 255, .9);
|
||||
}
|
||||
|
||||
QWidget#inputOSK QLineEdit {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #ccc;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
QWidget#inputBoxOSK {
|
||||
border: 2px solid rgba(255, 255, 255, .9);
|
||||
}
|
||||
|
||||
QWidget#inputBoxOSK QTextEdit {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
QWidget#richDialog QTextBrowser {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #fff;
|
||||
padding: 35px 65px;
|
||||
}
|
||||
|
||||
QWidget#lineOSK QLabel#label_header {
|
||||
color: #f0f0f0;
|
||||
}
|
||||
|
||||
QWidget#lineOSK QLabel#label_sub,
|
||||
QWidget#lineOSK QLabel#label_characters,
|
||||
QWidget#contentDialog QLabel#label_title,
|
||||
QWidget#contentRichDialog QLabel#label_title_rich,
|
||||
QWidget#boxOSK QLabel#label_characters_box {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
QWidget#buttonsDialog,
|
||||
QWidget#buttonsRichDialog,
|
||||
QWidget#mainOSK,
|
||||
QWidget#headerOSK,
|
||||
QWidget#normalOSK,
|
||||
QWidget#shiftOSK,
|
||||
QWidget#numOSK,
|
||||
QWidget#subOSK,
|
||||
QWidget#inputOSK,
|
||||
QWidget#inputBoxOSK,
|
||||
QWidget#charactersOSK,
|
||||
QWidget#charactersBoxOSK,
|
||||
QWidget#legendOSK,
|
||||
QWidget#legendOSK QWidget,
|
||||
QWidget#legendOSKshift,
|
||||
QWidget#legendOSKshift QWidget,
|
||||
QWidget#legendOSKnum,
|
||||
QWidget#legendOSKnum QWidget {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QWidget#contentDialog QLabel,
|
||||
QWidget#legendOSK QLabel,
|
||||
QWidget#legendOSKshift QLabel,
|
||||
QWidget#legendOSKnum QLabel {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
QWidget#contentDialog QLabel#label_dialog {
|
||||
padding: 20px 65px;
|
||||
}
|
||||
|
||||
QWidget#contentDialog QLabel#label_title,
|
||||
QWidget#contentRichDialog QLabel#label_title_rich {
|
||||
padding: 0px 65px;
|
||||
}
|
||||
|
||||
QDialog#OverlayDialog QPushButton {
|
||||
color: rgba(1, 253, 201, 1);
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0px;
|
||||
min-width: 0px;
|
||||
}
|
||||
|
||||
QDialog#OverlayDialog QPushButton:focus,
|
||||
QDialog#OverlayDialog QPushButton:hover {
|
||||
color: rgba(1, 253, 201, 1);
|
||||
background: rgba(58, 61, 66, 1);
|
||||
border: 5px solid rgba(56, 189, 225, 1);
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
QDialog#OverlayDialog QPushButton:pressed {
|
||||
color: rgba(240, 240, 240, 1);
|
||||
background: rgba(150, 150, 150, 1);
|
||||
border: 5px solid rgba(56, 189, 225, 1);
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
background: rgba(80, 79, 80, 1);
|
||||
border: 2px solid rgba(71, 69, 71, 1);
|
||||
padding: 0px;
|
||||
min-width: 0px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
|
||||
background: rgba(95, 94, 95, 1);
|
||||
border: 2px solid rgba(71, 69, 71, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
|
||||
color: rgba(240, 240, 240, 1);
|
||||
background: rgba(255, 255, 255, 1);
|
||||
border: 2px solid rgba(71, 69, 71, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
|
||||
color: rgba(0, 0, 0, 1);
|
||||
background: rgba(1, 253, 201, 1);
|
||||
border: 2px solid rgba(71, 69, 71, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus,
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
background: rgba(58, 61, 66, 1);
|
||||
border: 5px solid rgba(56, 189, 225, 1);
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed {
|
||||
color: rgba(240, 240, 240, 1);
|
||||
background: rgba(150, 150, 150, 1);
|
||||
border: 5px solid rgba(56, 189, 225, 1);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
|
||||
image: url(:/overlay/osk_button_B_dark.png);
|
||||
image-position: right;
|
||||
qproperty-icon: url(:/overlay/osk_button_backspace_dark.png);
|
||||
qproperty-iconSize: 36px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
|
||||
image: url(:/overlay/osk_button_Y_dark.png);
|
||||
image-position: right;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
|
||||
color: rgba(44, 44, 44, 1);
|
||||
image: url(:/overlay/osk_button_plus_dark.png);
|
||||
image-position: right;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift {
|
||||
image: url(:/overlay/osk_button_shift_lock_off.png);
|
||||
image-position: left;
|
||||
qproperty-icon: url(:/overlay/osk_button_shift_dark.png);
|
||||
qproperty-iconSize: 36px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift {
|
||||
image: url(:/overlay/osk_button_shift_lock_off.png);
|
||||
image-position: left;
|
||||
qproperty-icon: url(:/overlay/osk_button_shift_on_dark.png);
|
||||
qproperty-iconSize: 36px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis {
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel {
|
||||
background: transparent;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_L,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num {
|
||||
image: url(:/overlay/button_L_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num {
|
||||
image: url(:/overlay/arrow_left_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_R,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num {
|
||||
image: url(:/overlay/button_R_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num {
|
||||
image: url(:/overlay/arrow_right_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift {
|
||||
image: url(:/overlay/button_press_stick_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_X,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num {
|
||||
image: url(:/overlay/button_X_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_A,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num {
|
||||
image: url(:/overlay/button_A_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
|
||||
color: rgba(144, 144, 144, 1);
|
||||
background-color: rgba(95, 94, 95, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled {
|
||||
color: rgba(144, 144, 144, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled {
|
||||
image: url(:/overlay/osk_button_plus_dark_disabled.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
|
||||
image: url(:/overlay/osk_button_B_dark_disabled.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled {
|
||||
image: url(:/overlay/osk_button_Y_dark_disabled.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QFrame,
|
||||
QDialog#QtSoftwareKeyboardDialog QFrame[frameShape="0"],
|
||||
QDialog#OverlayDialog QFrame,
|
||||
QDialog#OverlayDialog QFrame[frameShape="0"] {
|
||||
border-radius: 0px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 725 B |
@@ -8,6 +8,7 @@
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="qss_icons">
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
|
||||
Created by the qtsass compiler v0.1.1
|
||||
Created by the qtsass compiler v0.1.1
|
||||
|
||||
The definitions are in the "qdarkstyle.qss._styles.scss" module
|
||||
The definitions are in the "qdarkstyle.qss._styles.scss" module
|
||||
|
||||
WARNING! All changes made in this file will be lost!
|
||||
WARNING! All changes made in this file will be lost!
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
/* QDarkStyleSheet -----------------------------------------------------------
|
||||
@@ -15,34 +15,34 @@ It is based on three selecting colors, three greyish (background) colors
|
||||
plus three whitish (foreground) colors. Each set of widgets of the same
|
||||
type have a header like this:
|
||||
|
||||
------------------
|
||||
GroupName --------
|
||||
------------------
|
||||
------------------
|
||||
GroupName --------
|
||||
------------------
|
||||
|
||||
And each widget is separated with a header like this:
|
||||
|
||||
QWidgetName ------
|
||||
QWidgetName ------
|
||||
|
||||
This makes more easy to find and change some css field. The basic
|
||||
configuration is described bellow.
|
||||
|
||||
BACKGROUND -----------
|
||||
BACKGROUND -----------
|
||||
|
||||
Light (unpressed)
|
||||
Normal (border, disabled, pressed, checked, toolbars, menus)
|
||||
Dark (background)
|
||||
Light (unpressed)
|
||||
Normal (border, disabled, pressed, checked, toolbars, menus)
|
||||
Dark (background)
|
||||
|
||||
FOREGROUND -----------
|
||||
FOREGROUND -----------
|
||||
|
||||
Light (texts/labels)
|
||||
Normal (not used yet)
|
||||
Dark (disabled texts)
|
||||
Light (texts/labels)
|
||||
Normal (not used yet)
|
||||
Dark (disabled texts)
|
||||
|
||||
SELECTION ------------
|
||||
SELECTION ------------
|
||||
|
||||
Light (selection/hover/active)
|
||||
Normal (selected)
|
||||
Dark (selected disabled)
|
||||
Light (selection/hover/active)
|
||||
Normal (selected)
|
||||
Dark (selected disabled)
|
||||
|
||||
If a stranger configuration is required because of a bugfix or anything
|
||||
else, keep the comment on the line above so nobody changes it, including the
|
||||
@@ -2483,3 +2483,394 @@ QWidget#controllerPlayer7,
|
||||
QWidget#controllerPlayer8 {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog,
|
||||
QStackedWidget#topOSK {
|
||||
background: rgba(15, 25, 34, .9);
|
||||
}
|
||||
|
||||
QDialog#OverlayDialog,
|
||||
QStackedWidget#stackedDialog {
|
||||
background: rgba(15, 25, 34, .7);
|
||||
}
|
||||
|
||||
QWidget#boxOSK,
|
||||
QWidget#lineOSK,
|
||||
QWidget#richDialog,
|
||||
QWidget#lineDialog {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QStackedWidget#bottomOSK,
|
||||
QWidget#contentDialog,
|
||||
QWidget#contentRichDialog {
|
||||
background: rgba(31, 41, 51, 1);
|
||||
}
|
||||
|
||||
QWidget#contentDialog,
|
||||
QWidget#contentRichDialog {
|
||||
margin: 5px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
QWidget#buttonsDialog,
|
||||
QWidget#buttonsRichDialog {
|
||||
margin: 5px;
|
||||
border-top: 2px solid rgba(255, 255, 255, .9);
|
||||
}
|
||||
|
||||
QWidget#legendOSKnum {
|
||||
border-top: 1px solid rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
QStackedWidget#stackedDialog QTextBrowser QWidget {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QStackedWidget#stackedDialog QTextBrowser QScrollBar {
|
||||
background: #19232d;
|
||||
border: none;
|
||||
}
|
||||
|
||||
QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line,
|
||||
QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line {
|
||||
border-image: none;
|
||||
}
|
||||
|
||||
QWidget#mainOSK QStackedWidget,
|
||||
QDialog#OverlayDialog QStackedWidget {
|
||||
border: none;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
QWidget#inputOSK {
|
||||
border-bottom: 3px solid rgba(255, 255, 255, .9);
|
||||
}
|
||||
|
||||
QWidget#inputOSK QLineEdit {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #ccc;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
QWidget#inputBoxOSK {
|
||||
border: 2px solid rgba(255, 255, 255, .9);
|
||||
}
|
||||
|
||||
QWidget#inputBoxOSK QTextEdit {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
QWidget#richDialog QTextBrowser {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #fff;
|
||||
padding: 35px 65px;
|
||||
}
|
||||
|
||||
QWidget#lineOSK QLabel#label_header {
|
||||
color: #f0f0f0;
|
||||
}
|
||||
|
||||
QWidget#lineOSK QLabel#label_sub,
|
||||
QWidget#lineOSK QLabel#label_characters,
|
||||
QWidget#contentDialog QLabel#label_title,
|
||||
QWidget#contentRichDialog QLabel#label_title_rich,
|
||||
QWidget#boxOSK QLabel#label_characters_box {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
QWidget#buttonsDialog,
|
||||
QWidget#buttonsRichDialog,
|
||||
QWidget#mainOSK,
|
||||
QWidget#headerOSK,
|
||||
QWidget#normalOSK,
|
||||
QWidget#shiftOSK,
|
||||
QWidget#numOSK,
|
||||
QWidget#subOSK,
|
||||
QWidget#inputOSK,
|
||||
QWidget#inputBoxOSK,
|
||||
QWidget#charactersOSK,
|
||||
QWidget#charactersBoxOSK,
|
||||
QWidget#legendOSK,
|
||||
QWidget#legendOSK QWidget,
|
||||
QWidget#legendOSKshift,
|
||||
QWidget#legendOSKshift QWidget,
|
||||
QWidget#legendOSKnum,
|
||||
QWidget#legendOSKnum QWidget {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QWidget#contentDialog QLabel,
|
||||
QWidget#legendOSK QLabel,
|
||||
QWidget#legendOSKshift QLabel,
|
||||
QWidget#legendOSKnum QLabel {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
QWidget#contentDialog QLabel#label_dialog {
|
||||
padding: 20px 65px;
|
||||
}
|
||||
|
||||
QWidget#contentDialog QLabel#label_title,
|
||||
QWidget#contentRichDialog QLabel#label_title_rich {
|
||||
padding: 0px 65px;
|
||||
}
|
||||
|
||||
QDialog#OverlayDialog QPushButton {
|
||||
color: rgba(1, 253, 201, 1);
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0px;
|
||||
min-width: 0px;
|
||||
}
|
||||
|
||||
QDialog#OverlayDialog QPushButton:focus,
|
||||
QDialog#OverlayDialog QPushButton:hover {
|
||||
color: rgba(1, 253, 201, 1);
|
||||
background: rgba(18, 33, 46, 1);
|
||||
border: 5px solid rgba(56, 189, 225, 1);
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
QDialog#OverlayDialog QPushButton:pressed {
|
||||
color: rgba(240, 240, 240, 1);
|
||||
background: rgba(110, 122, 130, 1);
|
||||
border: 5px solid rgba(56, 189, 225, 1);
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QLabel {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
background: rgba(40, 51, 60, 1);
|
||||
border: 2px solid rgba(31, 41, 51, 1);
|
||||
border-radius: 0px;
|
||||
padding: 0px;
|
||||
min-width: 0px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
|
||||
background: rgba(55, 66, 75, 1);
|
||||
border: 2px solid rgba(31, 41, 51, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
|
||||
color: rgba(240, 240, 240, 1);
|
||||
background: rgba(255, 255, 255, 1);
|
||||
border: 2px solid rgba(31, 41, 51, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
|
||||
color: rgba(0, 0, 0, 1);
|
||||
background: rgba(1, 253, 201, 1);
|
||||
border: 2px solid rgba(31, 41, 51, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus,
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
background: rgba(18, 33, 46, 1);
|
||||
border: 5px solid rgba(56, 189, 225, 1);
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed {
|
||||
color: rgba(240, 240, 240, 1);
|
||||
background: rgba(110, 122, 130, 1);
|
||||
border: 5px solid rgba(56, 189, 225, 1);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
|
||||
image: url(:/overlay/osk_button_B_dark.png);
|
||||
image-position: right;
|
||||
qproperty-icon: url(:/overlay/osk_button_backspace_dark.png);
|
||||
qproperty-iconSize: 36px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
|
||||
image: url(:/overlay/osk_button_Y_dark.png);
|
||||
image-position: right;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
|
||||
color: rgba(44, 44, 44, 1);
|
||||
image: url(:/overlay/osk_button_plus_dark.png);
|
||||
image-position: right;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift {
|
||||
image: url(:/overlay/osk_button_shift_lock_off.png);
|
||||
image-position: left;
|
||||
qproperty-icon: url(:/overlay/osk_button_shift_dark.png);
|
||||
qproperty-iconSize: 36px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift {
|
||||
image: url(:/overlay/osk_button_shift_lock_off.png);
|
||||
image-position: left;
|
||||
qproperty-icon: url(:/overlay/osk_button_shift_on_dark.png);
|
||||
qproperty-iconSize: 36px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis {
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel {
|
||||
background: transparent;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_L,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num {
|
||||
image: url(:/overlay/button_L_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num {
|
||||
image: url(:/overlay/arrow_left_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_R,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num {
|
||||
image: url(:/overlay/button_R_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num {
|
||||
image: url(:/overlay/arrow_right_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift {
|
||||
image: url(:/overlay/button_press_stick_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_X,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num {
|
||||
image: url(:/overlay/button_X_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_A,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift,
|
||||
QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num {
|
||||
image: url(:/overlay/button_A_dark.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
|
||||
color: rgba(144, 144, 144, 1);
|
||||
background-color: rgba(55, 66, 75, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled {
|
||||
color: rgba(144, 144, 144, 1);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled {
|
||||
image: url(:/overlay/osk_button_plus_dark_disabled.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
|
||||
image: url(:/overlay/osk_button_B_dark_disabled.png);
|
||||
}
|
||||
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
|
||||
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled {
|
||||
image: url(:/overlay/osk_button_Y_dark_disabled.png);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,28 @@ target_include_directories(microprofile INTERFACE ./microprofile)
|
||||
add_library(unicorn-headers INTERFACE)
|
||||
target_include_directories(unicorn-headers INTERFACE ./unicorn/include)
|
||||
|
||||
# SDL2
|
||||
if (NOT SDL2_FOUND AND ENABLE_SDL2)
|
||||
if (NOT WIN32)
|
||||
# Yuzu itself needs: Events Joystick Haptic Sensor Timers
|
||||
# Yuzu-cmd also needs: Video (depends on Loadso/Dlopen)
|
||||
set(SDL_UNUSED_SUBSYSTEMS
|
||||
Atomic Audio Render Power Threads
|
||||
File CPUinfo Filesystem Locale)
|
||||
foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS})
|
||||
string(TOUPPER ${_SUB} _OPT)
|
||||
option(SDL_${_OPT} "" OFF)
|
||||
endforeach()
|
||||
|
||||
option(HIDAPI "" ON)
|
||||
endif()
|
||||
set(SDL_STATIC ON)
|
||||
set(SDL_SHARED OFF)
|
||||
|
||||
add_subdirectory(SDL EXCLUDE_FROM_ALL)
|
||||
add_library(SDL2 ALIAS SDL2-static)
|
||||
endif()
|
||||
|
||||
# SoundTouch
|
||||
add_subdirectory(soundtouch)
|
||||
|
||||
|
||||
@@ -1,155 +1,239 @@
|
||||
# Ensure libusb compiles with UTF-8 encoding on MSVC
|
||||
if(MSVC)
|
||||
add_compile_options(/utf-8)
|
||||
endif()
|
||||
if (MINGW)
|
||||
# The MinGW toolchain for some reason doesn't work with this CMakeLists file after updating to
|
||||
# 1.0.24, so we do it the old-fashioned way for now. We may want to move native Linux toolchains
|
||||
# to here, too (TODO lat9nq?).
|
||||
|
||||
add_library(usb STATIC EXCLUDE_FROM_ALL
|
||||
libusb/libusb/core.c
|
||||
libusb/libusb/core.c
|
||||
libusb/libusb/descriptor.c
|
||||
libusb/libusb/hotplug.c
|
||||
libusb/libusb/io.c
|
||||
libusb/libusb/strerror.c
|
||||
libusb/libusb/sync.c
|
||||
)
|
||||
set_target_properties(usb PROPERTIES VERSION 1.0.23)
|
||||
if(WIN32)
|
||||
target_include_directories(usb
|
||||
BEFORE
|
||||
PUBLIC
|
||||
libusb/libusb
|
||||
set(LIBUSB_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/libusb")
|
||||
set(LIBUSB_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libusb")
|
||||
# Workarounds for MSYS/MinGW
|
||||
if (MSYS)
|
||||
# CMake on Windows passes `C:/`, but we need `/C/` or `/c/` to use `configure`
|
||||
string(REPLACE ":/" "/" LIBUSB_SRC_DIR "${LIBUSB_SRC_DIR}")
|
||||
set(LIBUSB_SRC_DIR "/${LIBUSB_SRC_DIR}")
|
||||
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
|
||||
if (NOT MINGW)
|
||||
target_include_directories(usb BEFORE PRIVATE libusb/msvc)
|
||||
# And now that we are using /C/ for srcdir but everything else is using C:/, we need to
|
||||
# compile everything in the source directory, else `configure` won't think the build
|
||||
# environment is sane.
|
||||
set(LIBUSB_PREFIX "${LIBUSB_SRC_DIR}")
|
||||
endif()
|
||||
|
||||
# Works around other libraries providing their own definition of USB GUIDs (e.g. SDL2)
|
||||
target_compile_definitions(usb PRIVATE "-DGUID_DEVINTERFACE_USB_DEVICE=(GUID){ 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}}")
|
||||
else()
|
||||
target_include_directories(usb
|
||||
# turns out other projects also have "config.h", so make sure the
|
||||
# LibUSB one comes first
|
||||
BEFORE
|
||||
set(LIBUSB_CONFIGURE "${LIBUSB_SRC_DIR}/configure")
|
||||
set(LIBUSB_MAKEFILE "${LIBUSB_PREFIX}/Makefile")
|
||||
set(LIBUSB_LIBRARY "${LIBUSB_PREFIX}/libusb/.libs/libusb-1.0.dll.a")
|
||||
set(LIBUSB_SHARED_LIBRARY "${LIBUSB_PREFIX}/libusb/.libs/libusb-1.0.dll")
|
||||
set(LIBUSB_SHARED_LIBRARY_DEST "${CMAKE_BINARY_DIR}/bin/libusb-1.0.dll")
|
||||
|
||||
PUBLIC
|
||||
libusb/libusb
|
||||
# Causes "externals/libusb/libusb/libusb/os/windows_winusb.c:1427:2: error: conversion to non-scalar type requested", so cannot statically link it for now.
|
||||
# set(LIBUSB_CFLAGS "-DGUID_DEVINTERFACE_USB_DEVICE=\\(GUID\\){0xA5DCBF10,0x6530,0x11D2,{0x90,0x1F,0x00,0xC0,0x4F,0xB9,0x51,0xED}}")
|
||||
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
endif()
|
||||
make_directory("${LIBUSB_PREFIX}")
|
||||
|
||||
if(WIN32 OR CYGWIN)
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/threads_windows.c
|
||||
libusb/libusb/os/windows_winusb.c
|
||||
libusb/libusb/os/windows_usbdk.c
|
||||
libusb/libusb/os/windows_nt_common.c
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
"${LIBUSB_LIBRARY}"
|
||||
COMMAND
|
||||
make
|
||||
WORKING_DIRECTORY
|
||||
"${LIBUSB_PREFIX}"
|
||||
)
|
||||
set(OS_WINDOWS TRUE)
|
||||
elseif(APPLE)
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/darwin_usb.c
|
||||
|
||||
# We may use this path for other GNU toolchains, so put all of the MinGW-specific stuff here
|
||||
if (MINGW)
|
||||
set(LIBUSB_CONFIGURE_ARGS --host=x86_64-w64-mingw32 --build=x86_64-windows)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
"${LIBUSB_MAKEFILE}"
|
||||
COMMAND
|
||||
# /bin/env
|
||||
# CFLAGS="${LIBUSB_CFLAGS}"
|
||||
/bin/sh "${LIBUSB_CONFIGURE}"
|
||||
${LIBUSB_CONFIGURE_ARGS}
|
||||
--srcdir="${LIBUSB_SRC_DIR}"
|
||||
WORKING_DIRECTORY
|
||||
"${LIBUSB_PREFIX}"
|
||||
)
|
||||
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
|
||||
find_library(IOKIT_LIBRARY IOKit)
|
||||
find_library(OBJC_LIBRARY objc)
|
||||
target_link_libraries(usb PRIVATE
|
||||
${COREFOUNDATION_LIBRARY}
|
||||
${IOKIT_LIBRARY}
|
||||
${OBJC_LIBRARY}
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
"${LIBUSB_CONFIGURE}"
|
||||
COMMAND
|
||||
/bin/sh "${LIBUSB_SRC_DIR}/bootstrap.sh"
|
||||
WORKING_DIRECTORY
|
||||
"${LIBUSB_SRC_DIR}"
|
||||
)
|
||||
set(OS_DARWIN TRUE)
|
||||
elseif(ANDROID)
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/linux_usbfs.c
|
||||
libusb/libusb/os/linux_netlink.c
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
"${LIBUSB_SHARED_LIBRARY_DEST}"
|
||||
COMMAND
|
||||
/bin/cp "${LIBUSB_SHARED_LIBRARY}" "${LIBUSB_SHARED_LIBRARY_DEST}"
|
||||
)
|
||||
find_library(LOG_LIBRARY log)
|
||||
target_link_libraries(usb PRIVATE ${LOG_LIBRARY})
|
||||
set(OS_LINUX TRUE)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/linux_usbfs.c
|
||||
|
||||
add_custom_target(usb-bootstrap ALL DEPENDS "${LIBUSB_CONFIGURE}")
|
||||
add_custom_target(usb-configure ALL DEPENDS "${LIBUSB_MAKEFILE}" usb-bootstrap)
|
||||
add_custom_target(usb-build ALL DEPENDS "${LIBUSB_LIBRARY}" usb-configure)
|
||||
# Workaround since static linking didn't work out -- We need to copy the DLL to the bin directory
|
||||
add_custom_target(usb-copy ALL DEPENDS "${LIBUSB_SHARED_LIBRARY_DEST}" usb-build)
|
||||
|
||||
# Make `usb` alias to LIBUSB_LIBRARY
|
||||
add_library(usb INTERFACE)
|
||||
target_link_libraries(usb INTERFACE "${LIBUSB_LIBRARY}")
|
||||
else() # MINGW
|
||||
# Ensure libusb compiles with UTF-8 encoding on MSVC
|
||||
if(MSVC)
|
||||
add_compile_options(/utf-8)
|
||||
endif()
|
||||
|
||||
add_library(usb STATIC EXCLUDE_FROM_ALL
|
||||
libusb/libusb/core.c
|
||||
libusb/libusb/core.c
|
||||
libusb/libusb/descriptor.c
|
||||
libusb/libusb/hotplug.c
|
||||
libusb/libusb/io.c
|
||||
libusb/libusb/strerror.c
|
||||
libusb/libusb/sync.c
|
||||
)
|
||||
find_package(Libudev)
|
||||
if(LIBUDEV_FOUND)
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/linux_udev.c
|
||||
set_target_properties(usb PROPERTIES VERSION 1.0.24)
|
||||
if(WIN32)
|
||||
target_include_directories(usb
|
||||
BEFORE
|
||||
PUBLIC
|
||||
libusb/libusb
|
||||
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
target_link_libraries(usb PRIVATE "${LIBUDEV_LIBRARIES}")
|
||||
target_include_directories(usb PRIVATE "${LIBUDEV_INCLUDE_DIR}")
|
||||
set(HAVE_LIBUDEV TRUE)
|
||||
set(USE_UDEV TRUE)
|
||||
|
||||
if (NOT MINGW)
|
||||
target_include_directories(usb BEFORE PRIVATE libusb/msvc)
|
||||
endif()
|
||||
|
||||
# Works around other libraries providing their own definition of USB GUIDs (e.g. SDL2)
|
||||
target_compile_definitions(usb PRIVATE "-DGUID_DEVINTERFACE_USB_DEVICE=(GUID){ 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}}")
|
||||
else()
|
||||
target_include_directories(usb
|
||||
# turns out other projects also have "config.h", so make sure the
|
||||
# LibUSB one comes first
|
||||
BEFORE
|
||||
|
||||
PUBLIC
|
||||
libusb/libusb
|
||||
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32 OR CYGWIN)
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/threads_windows.c
|
||||
libusb/libusb/os/windows_winusb.c
|
||||
libusb/libusb/os/windows_usbdk.c
|
||||
libusb/libusb/os/windows_common.c
|
||||
)
|
||||
set(OS_WINDOWS TRUE)
|
||||
elseif(APPLE)
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/darwin_usb.c
|
||||
)
|
||||
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
|
||||
find_library(IOKIT_LIBRARY IOKit)
|
||||
find_library(OBJC_LIBRARY objc)
|
||||
target_link_libraries(usb PRIVATE
|
||||
${COREFOUNDATION_LIBRARY}
|
||||
${IOKIT_LIBRARY}
|
||||
${OBJC_LIBRARY}
|
||||
)
|
||||
set(OS_DARWIN TRUE)
|
||||
elseif(ANDROID)
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/linux_usbfs.c
|
||||
libusb/libusb/os/linux_netlink.c
|
||||
)
|
||||
find_library(LOG_LIBRARY log)
|
||||
target_link_libraries(usb PRIVATE ${LOG_LIBRARY})
|
||||
set(OS_LINUX TRUE)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/linux_usbfs.c
|
||||
)
|
||||
find_package(Libudev)
|
||||
if(LIBUDEV_FOUND)
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/linux_udev.c
|
||||
)
|
||||
target_link_libraries(usb PRIVATE "${LIBUDEV_LIBRARIES}")
|
||||
target_include_directories(usb PRIVATE "${LIBUDEV_INCLUDE_DIR}")
|
||||
set(HAVE_LIBUDEV TRUE)
|
||||
set(USE_UDEV TRUE)
|
||||
else()
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/linux_netlink.c
|
||||
)
|
||||
endif()
|
||||
set(OS_LINUX TRUE)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/netbsd_usb.c
|
||||
)
|
||||
set(OS_NETBSD TRUE)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/openbsd_usb.c
|
||||
)
|
||||
set(OS_OPENBSD TRUE)
|
||||
endif()
|
||||
set(OS_LINUX TRUE)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/netbsd_usb.c
|
||||
)
|
||||
set(OS_NETBSD TRUE)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/openbsd_usb.c
|
||||
)
|
||||
set(OS_OPENBSD TRUE)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/poll_posix.c
|
||||
libusb/libusb/os/threads_posix.c
|
||||
)
|
||||
find_package(Threads REQUIRED)
|
||||
if(THREADS_HAVE_PTHREAD_ARG)
|
||||
target_compile_options(usb PUBLIC "-pthread")
|
||||
if(UNIX)
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/events_posix.c
|
||||
libusb/libusb/os/threads_posix.c
|
||||
)
|
||||
find_package(Threads REQUIRED)
|
||||
if(THREADS_HAVE_PTHREAD_ARG)
|
||||
target_compile_options(usb PUBLIC "-pthread")
|
||||
endif()
|
||||
if(CMAKE_THREAD_LIBS_INIT)
|
||||
target_link_libraries(usb PRIVATE "${CMAKE_THREAD_LIBS_INIT}")
|
||||
endif()
|
||||
set(THREADS_POSIX TRUE)
|
||||
elseif(WIN32)
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/events_windows.c
|
||||
libusb/libusb/os/threads_windows.c
|
||||
)
|
||||
endif()
|
||||
if(CMAKE_THREAD_LIBS_INIT)
|
||||
target_link_libraries(usb PRIVATE "${CMAKE_THREAD_LIBS_INIT}")
|
||||
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckTypeSize)
|
||||
check_include_files(asm/types.h HAVE_ASM_TYPES_H)
|
||||
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
|
||||
check_include_files(linux/filter.h HAVE_LINUX_FILTER_H)
|
||||
check_include_files(linux/netlink.h HAVE_LINUX_NETLINK_H)
|
||||
check_include_files(poll.h HAVE_POLL_H)
|
||||
check_include_files(signal.h HAVE_SIGNAL_H)
|
||||
check_include_files(strings.h HAVE_STRINGS_H)
|
||||
check_type_size("struct timespec" STRUCT_TIMESPEC)
|
||||
check_function_exists(syslog HAVE_SYSLOG_FUNC)
|
||||
check_include_files(syslog.h HAVE_SYSLOG_H)
|
||||
check_include_files(sys/socket.h HAVE_SYS_SOCKET_H)
|
||||
check_include_files(sys/time.h HAVE_SYS_TIME_H)
|
||||
check_include_files(sys/types.h HAVE_SYS_TYPES_H)
|
||||
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES poll.h)
|
||||
check_type_size("nfds_t" nfds_t)
|
||||
unset(CMAKE_EXTRA_INCLUDE_FILES)
|
||||
if(HAVE_NFDS_T)
|
||||
set(POLL_NFDS_TYPE "nfds_t")
|
||||
else()
|
||||
set(POLL_NFDS_TYPE "unsigned int")
|
||||
endif()
|
||||
set(THREADS_POSIX TRUE)
|
||||
elseif(WIN32)
|
||||
target_sources(usb PRIVATE
|
||||
libusb/libusb/os/poll_windows.c
|
||||
libusb/libusb/os/threads_windows.c
|
||||
)
|
||||
endif()
|
||||
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckTypeSize)
|
||||
check_include_files(asm/types.h HAVE_ASM_TYPES_H)
|
||||
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
|
||||
check_include_files(linux/filter.h HAVE_LINUX_FILTER_H)
|
||||
check_include_files(linux/netlink.h HAVE_LINUX_NETLINK_H)
|
||||
check_include_files(poll.h HAVE_POLL_H)
|
||||
check_include_files(signal.h HAVE_SIGNAL_H)
|
||||
check_include_files(strings.h HAVE_STRINGS_H)
|
||||
check_type_size("struct timespec" STRUCT_TIMESPEC)
|
||||
check_function_exists(syslog HAVE_SYSLOG_FUNC)
|
||||
check_include_files(syslog.h HAVE_SYSLOG_H)
|
||||
check_include_files(sys/socket.h HAVE_SYS_SOCKET_H)
|
||||
check_include_files(sys/time.h HAVE_SYS_TIME_H)
|
||||
check_include_files(sys/types.h HAVE_SYS_TYPES_H)
|
||||
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES poll.h)
|
||||
check_type_size("nfds_t" nfds_t)
|
||||
unset(CMAKE_EXTRA_INCLUDE_FILES)
|
||||
if(HAVE_NFDS_T)
|
||||
set(POLL_NFDS_TYPE "nfds_t")
|
||||
else()
|
||||
set(POLL_NFDS_TYPE "unsigned int")
|
||||
endif()
|
||||
|
||||
check_include_files(sys/timerfd.h USBI_TIMERFD_AVAILABLE)
|
||||
check_include_files(sys/timerfd.h USBI_TIMERFD_AVAILABLE)
|
||||
|
||||
|
||||
configure_file(config.h.in config.h)
|
||||
configure_file(config.h.in config.h)
|
||||
endif() # MINGW
|
||||
|
||||
@@ -358,6 +358,7 @@ chip.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
||||
folder.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
||||
plus.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
||||
sd_card.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
||||
star.png | CC BY-ND 3.0 | https://icons8.com
|
||||
|
||||
Note:
|
||||
Some icons are different in different themes, and they are separately listed
|
||||
|
||||
@@ -54,6 +54,7 @@ if (MSVC)
|
||||
/we4547 # 'operator' : operator before comma has no effect; expected operator with side-effect
|
||||
/we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'?
|
||||
/we4555 # Expression has no effect; expected expression with side-effect
|
||||
/we4715 # 'function': not all control paths return a value
|
||||
/we4834 # Discarding return value of function with 'nodiscard' attribute
|
||||
/we5038 # data member 'member1' will be initialized after data member 'member2'
|
||||
)
|
||||
|
||||
@@ -197,7 +197,7 @@ ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_param
|
||||
|
||||
ReleaseAndQueueBuffers();
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
|
||||
|
||||
@@ -407,7 +407,7 @@ ResultCode InfoUpdater::UpdateMixes(MixContext& mix_context, std::size_t mix_buf
|
||||
|
||||
// TODO(ogniK): Sort when splitter is suppoorted
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
bool InfoUpdater::UpdateSinks(SinkContext& sink_context) {
|
||||
|
||||
@@ -109,7 +109,6 @@ add_library(common STATIC
|
||||
cityhash.cpp
|
||||
cityhash.h
|
||||
common_funcs.h
|
||||
common_paths.h
|
||||
common_sizes.h
|
||||
common_types.h
|
||||
concepts.h
|
||||
@@ -118,8 +117,16 @@ add_library(common STATIC
|
||||
dynamic_library.h
|
||||
fiber.cpp
|
||||
fiber.h
|
||||
file_util.cpp
|
||||
file_util.h
|
||||
fs/file.cpp
|
||||
fs/file.h
|
||||
fs/fs.cpp
|
||||
fs/fs.h
|
||||
fs/fs_paths.h
|
||||
fs/fs_types.h
|
||||
fs/fs_util.cpp
|
||||
fs/fs_util.h
|
||||
fs/path_util.cpp
|
||||
fs/path_util.h
|
||||
hash.h
|
||||
hex_util.cpp
|
||||
hex_util.h
|
||||
@@ -147,6 +154,7 @@ add_library(common STATIC
|
||||
param_package.cpp
|
||||
param_package.h
|
||||
parent_of_member.h
|
||||
point.h
|
||||
quaternion.h
|
||||
ring_buffer.h
|
||||
scm_rev.cpp
|
||||
|
||||
@@ -97,30 +97,13 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
|
||||
return static_cast<T>(key) == 0; \
|
||||
}
|
||||
|
||||
/// Evaluates a boolean expression, and returns a result unless that expression is true.
|
||||
#define R_UNLESS(expr, res) \
|
||||
{ \
|
||||
if (!(expr)) { \
|
||||
if (res.IsError()) { \
|
||||
LOG_ERROR(Kernel, "Failed with result: {}", res.raw); \
|
||||
} \
|
||||
return res; \
|
||||
} \
|
||||
}
|
||||
#define YUZU_NON_COPYABLE(cls) \
|
||||
cls(const cls&) = delete; \
|
||||
cls& operator=(const cls&) = delete
|
||||
|
||||
#define R_SUCCEEDED(res) (res.IsSuccess())
|
||||
|
||||
/// Evaluates an expression that returns a result, and returns the result if it would fail.
|
||||
#define R_TRY(res_expr) \
|
||||
{ \
|
||||
const auto _tmp_r_try_rc = (res_expr); \
|
||||
if (_tmp_r_try_rc.IsError()) { \
|
||||
return _tmp_r_try_rc; \
|
||||
} \
|
||||
}
|
||||
|
||||
/// Evaluates a boolean expression, and succeeds if that expression is true.
|
||||
#define R_SUCCEED_IF(expr) R_UNLESS(!(expr), RESULT_SUCCESS)
|
||||
#define YUZU_NON_MOVEABLE(cls) \
|
||||
cls(cls&&) = delete; \
|
||||
cls& operator=(cls&&) = delete
|
||||
|
||||
namespace Common {
|
||||
|
||||
@@ -128,4 +111,19 @@ namespace Common {
|
||||
return u32(a) | u32(b) << 8 | u32(c) << 16 | u32(d) << 24;
|
||||
}
|
||||
|
||||
// std::size() does not support zero-size C arrays. We're fixing that.
|
||||
template <class C>
|
||||
constexpr auto Size(const C& c) -> decltype(c.size()) {
|
||||
return std::size(c);
|
||||
}
|
||||
|
||||
template <class C>
|
||||
constexpr std::size_t Size(const C& c) {
|
||||
if constexpr (sizeof(C) == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return std::size(c);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
// Directory separators, do we need this?
|
||||
#define DIR_SEP "/"
|
||||
#define DIR_SEP_CHR '/'
|
||||
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 260
|
||||
#endif
|
||||
|
||||
// The user data dir
|
||||
#define ROOT_DIR "."
|
||||
#define USERDATA_DIR "user"
|
||||
#ifdef USER_DIR
|
||||
#define EMU_DATA_DIR USER_DIR
|
||||
#else
|
||||
#define EMU_DATA_DIR "yuzu"
|
||||
#endif
|
||||
|
||||
// Dirs in both User and Sys
|
||||
#define EUR_DIR "EUR"
|
||||
#define USA_DIR "USA"
|
||||
#define JAP_DIR "JAP"
|
||||
|
||||
// Subdirs in the User dir returned by GetUserPath(UserPath::UserDir)
|
||||
#define CONFIG_DIR "config"
|
||||
#define CACHE_DIR "cache"
|
||||
#define SDMC_DIR "sdmc"
|
||||
#define NAND_DIR "nand"
|
||||
#define SYSDATA_DIR "sysdata"
|
||||
#define KEYS_DIR "keys"
|
||||
#define LOAD_DIR "load"
|
||||
#define DUMP_DIR "dump"
|
||||
#define SCREENSHOTS_DIR "screenshots"
|
||||
#define SHADER_DIR "shader"
|
||||
#define LOG_DIR "log"
|
||||
|
||||
// Filenames
|
||||
// Files in the directory returned by GetUserPath(UserPath::ConfigDir)
|
||||
#define EMU_CONFIG "emu.ini"
|
||||
#define DEBUGGER_CONFIG "debugger.ini"
|
||||
#define LOGGER_CONFIG "logger.ini"
|
||||
// Files in the directory returned by GetUserPath(UserPath::LogDir)
|
||||
#define LOG_FILE "yuzu_log.txt"
|
||||
|
||||
// Sys files
|
||||
#define SHARED_FONT "shared_font.bin"
|
||||
#define AES_KEYS "aes_keys.txt"
|
||||
@@ -1,298 +0,0 @@
|
||||
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "common/string_util.h"
|
||||
#endif
|
||||
|
||||
namespace Common::FS {
|
||||
|
||||
// User paths for GetUserPath
|
||||
enum class UserPath {
|
||||
CacheDir,
|
||||
ConfigDir,
|
||||
KeysDir,
|
||||
LogDir,
|
||||
NANDDir,
|
||||
RootDir,
|
||||
SDMCDir,
|
||||
LoadDir,
|
||||
DumpDir,
|
||||
ScreenshotsDir,
|
||||
ShaderDir,
|
||||
SysDataDir,
|
||||
UserDir,
|
||||
};
|
||||
|
||||
// FileSystem tree node/
|
||||
struct FSTEntry {
|
||||
bool isDirectory;
|
||||
u64 size; // file length or number of entries from children
|
||||
std::string physicalName; // name on disk
|
||||
std::string virtualName; // name in FST names table
|
||||
std::vector<FSTEntry> children;
|
||||
};
|
||||
|
||||
// Returns true if file filename exists
|
||||
[[nodiscard]] bool Exists(const std::string& filename);
|
||||
|
||||
// Returns true if filename is a directory
|
||||
[[nodiscard]] bool IsDirectory(const std::string& filename);
|
||||
|
||||
// Returns the size of filename (64bit)
|
||||
[[nodiscard]] u64 GetSize(const std::string& filename);
|
||||
|
||||
// Overloaded GetSize, accepts file descriptor
|
||||
[[nodiscard]] u64 GetSize(int fd);
|
||||
|
||||
// Overloaded GetSize, accepts FILE*
|
||||
[[nodiscard]] u64 GetSize(FILE* f);
|
||||
|
||||
// Returns true if successful, or path already exists.
|
||||
bool CreateDir(const std::string& filename);
|
||||
|
||||
// Creates the full path of fullPath returns true on success
|
||||
bool CreateFullPath(const std::string& fullPath);
|
||||
|
||||
// Deletes a given filename, return true on success
|
||||
// Doesn't supports deleting a directory
|
||||
bool Delete(const std::string& filename);
|
||||
|
||||
// Deletes a directory filename, returns true on success
|
||||
bool DeleteDir(const std::string& filename);
|
||||
|
||||
// renames file srcFilename to destFilename, returns true on success
|
||||
bool Rename(const std::string& srcFilename, const std::string& destFilename);
|
||||
|
||||
// copies file srcFilename to destFilename, returns true on success
|
||||
bool Copy(const std::string& srcFilename, const std::string& destFilename);
|
||||
|
||||
// creates an empty file filename, returns true on success
|
||||
bool CreateEmptyFile(const std::string& filename);
|
||||
|
||||
/**
|
||||
* @param num_entries_out to be assigned by the callable with the number of iterated directory
|
||||
* entries, never null
|
||||
* @param directory the path to the enclosing directory
|
||||
* @param virtual_name the entry name, without any preceding directory info
|
||||
* @return whether handling the entry succeeded
|
||||
*/
|
||||
using DirectoryEntryCallable = std::function<bool(
|
||||
u64* num_entries_out, const std::string& directory, const std::string& virtual_name)>;
|
||||
|
||||
/**
|
||||
* Scans a directory, calling the callback for each file/directory contained within.
|
||||
* If the callback returns failure, scanning halts and this function returns failure as well
|
||||
* @param num_entries_out assigned by the function with the number of iterated directory entries,
|
||||
* can be null
|
||||
* @param directory the directory to scan
|
||||
* @param callback The callback which will be called for each entry
|
||||
* @return whether scanning the directory succeeded
|
||||
*/
|
||||
bool ForeachDirectoryEntry(u64* num_entries_out, const std::string& directory,
|
||||
DirectoryEntryCallable callback);
|
||||
|
||||
/**
|
||||
* Scans the directory tree, storing the results.
|
||||
* @param directory the parent directory to start scanning from
|
||||
* @param parent_entry FSTEntry where the filesystem tree results will be stored.
|
||||
* @param recursion Number of children directories to read before giving up.
|
||||
* @return the total number of files/directories found
|
||||
*/
|
||||
u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry,
|
||||
unsigned int recursion = 0);
|
||||
|
||||
// deletes the given directory and anything under it. Returns true on success.
|
||||
bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256);
|
||||
|
||||
// Returns the current directory
|
||||
[[nodiscard]] std::optional<std::string> GetCurrentDir();
|
||||
|
||||
// Create directory and copy contents (does not overwrite existing files)
|
||||
void CopyDir(const std::string& source_path, const std::string& dest_path);
|
||||
|
||||
// Set the current directory to given directory
|
||||
bool SetCurrentDir(const std::string& directory);
|
||||
|
||||
// Returns a pointer to a string with a yuzu data dir in the user's home
|
||||
// directory. To be used in "multi-user" mode (that is, installed).
|
||||
const std::string& GetUserPath(UserPath path, const std::string& new_path = "");
|
||||
|
||||
[[nodiscard]] std::string GetHactoolConfigurationPath();
|
||||
|
||||
[[nodiscard]] std::string GetNANDRegistrationDir(bool system = false);
|
||||
|
||||
// Returns the path to where the sys file are
|
||||
[[nodiscard]] std::string GetSysDirectory();
|
||||
|
||||
#ifdef __APPLE__
|
||||
[[nodiscard]] std::string GetBundleDirectory();
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
[[nodiscard]] const std::string& GetExeDirectory();
|
||||
[[nodiscard]] std::string AppDataRoamingDirectory();
|
||||
#endif
|
||||
|
||||
std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str);
|
||||
|
||||
std::size_t ReadFileToString(bool text_file, const std::string& filename, std::string& str);
|
||||
|
||||
/**
|
||||
* Splits the filename into 8.3 format
|
||||
* Loosely implemented following https://en.wikipedia.org/wiki/8.3_filename
|
||||
* @param filename The normal filename to use
|
||||
* @param short_name A 9-char array in which the short name will be written
|
||||
* @param extension A 4-char array in which the extension will be written
|
||||
*/
|
||||
void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name,
|
||||
std::array<char, 4>& extension);
|
||||
|
||||
// Splits the path on '/' or '\' and put the components into a vector
|
||||
// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" }
|
||||
[[nodiscard]] std::vector<std::string> SplitPathComponents(std::string_view filename);
|
||||
|
||||
// Gets all of the text up to the last '/' or '\' in the path.
|
||||
[[nodiscard]] std::string_view GetParentPath(std::string_view path);
|
||||
|
||||
// Gets all of the text after the first '/' or '\' in the path.
|
||||
[[nodiscard]] std::string_view GetPathWithoutTop(std::string_view path);
|
||||
|
||||
// Gets the filename of the path
|
||||
[[nodiscard]] std::string_view GetFilename(std::string_view path);
|
||||
|
||||
// Gets the extension of the filename
|
||||
[[nodiscard]] std::string_view GetExtensionFromFilename(std::string_view name);
|
||||
|
||||
// Removes the final '/' or '\' if one exists
|
||||
[[nodiscard]] std::string_view RemoveTrailingSlash(std::string_view path);
|
||||
|
||||
// Creates a new vector containing indices [first, last) from the original.
|
||||
template <typename T>
|
||||
[[nodiscard]] std::vector<T> SliceVector(const std::vector<T>& vector, std::size_t first,
|
||||
std::size_t last) {
|
||||
if (first >= last) {
|
||||
return {};
|
||||
}
|
||||
last = std::min<std::size_t>(last, vector.size());
|
||||
return std::vector<T>(vector.begin() + first, vector.begin() + first + last);
|
||||
}
|
||||
|
||||
enum class DirectorySeparator {
|
||||
ForwardSlash,
|
||||
BackwardSlash,
|
||||
PlatformDefault,
|
||||
};
|
||||
|
||||
// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\'
|
||||
// depending if directory_separator is BackwardSlash or PlatformDefault and running on windows
|
||||
[[nodiscard]] std::string SanitizePath(
|
||||
std::string_view path,
|
||||
DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash);
|
||||
|
||||
// To deal with Windows being dumb at Unicode
|
||||
template <typename T>
|
||||
void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode) {
|
||||
#ifdef _MSC_VER
|
||||
fstream.open(Common::UTF8ToUTF16W(filename), openmode);
|
||||
#else
|
||||
fstream.open(filename, openmode);
|
||||
#endif
|
||||
}
|
||||
|
||||
// simple wrapper for cstdlib file functions to
|
||||
// hopefully will make error checking easier
|
||||
// and make forgetting an fclose() harder
|
||||
class IOFile : public NonCopyable {
|
||||
public:
|
||||
IOFile();
|
||||
// flags is used for windows specific file open mode flags, which
|
||||
// allows yuzu to open the logs in shared write mode, so that the file
|
||||
// isn't considered "locked" while yuzu is open and people can open the log file and view it
|
||||
IOFile(const std::string& filename, const char openmode[], int flags = 0);
|
||||
|
||||
~IOFile();
|
||||
|
||||
IOFile(IOFile&& other) noexcept;
|
||||
IOFile& operator=(IOFile&& other) noexcept;
|
||||
|
||||
void Swap(IOFile& other) noexcept;
|
||||
|
||||
bool Open(const std::string& filename, const char openmode[], int flags = 0);
|
||||
bool Close();
|
||||
|
||||
template <typename T>
|
||||
std::size_t ReadArray(T* data, std::size_t length) const {
|
||||
static_assert(std::is_trivially_copyable_v<T>,
|
||||
"Given array does not consist of trivially copyable objects");
|
||||
|
||||
return ReadImpl(data, length, sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t WriteArray(const T* data, std::size_t length) {
|
||||
static_assert(std::is_trivially_copyable_v<T>,
|
||||
"Given array does not consist of trivially copyable objects");
|
||||
|
||||
return WriteImpl(data, length, sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t ReadBytes(T* data, std::size_t length) const {
|
||||
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
|
||||
return ReadArray(reinterpret_cast<char*>(data), length);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t WriteBytes(const T* data, std::size_t length) {
|
||||
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
|
||||
return WriteArray(reinterpret_cast<const char*>(data), length);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t WriteObject(const T& object) {
|
||||
static_assert(!std::is_pointer_v<T>, "WriteObject arguments must not be a pointer");
|
||||
return WriteArray(&object, 1);
|
||||
}
|
||||
|
||||
std::size_t WriteString(std::string_view str) {
|
||||
return WriteArray(str.data(), str.length());
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsOpen() const {
|
||||
return nullptr != m_file;
|
||||
}
|
||||
|
||||
bool Seek(s64 off, int origin) const;
|
||||
[[nodiscard]] u64 Tell() const;
|
||||
[[nodiscard]] u64 GetSize() const;
|
||||
bool Resize(u64 size);
|
||||
bool Flush();
|
||||
|
||||
// clear error state
|
||||
void Clear() {
|
||||
std::clearerr(m_file);
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t ReadImpl(void* data, std::size_t length, std::size_t data_size) const;
|
||||
std::size_t WriteImpl(const void* data, std::size_t length, std::size_t data_size);
|
||||
|
||||
std::FILE* m_file = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Common::FS
|
||||
@@ -0,0 +1,392 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/fs/file.h"
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/logging/log.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <share.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define fileno _fileno
|
||||
#define fseeko _fseeki64
|
||||
#define ftello _ftelli64
|
||||
#endif
|
||||
|
||||
namespace Common::FS {
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/**
|
||||
* Converts the file access mode and file type enums to a file access mode wide string.
|
||||
*
|
||||
* @param mode File access mode
|
||||
* @param type File type
|
||||
*
|
||||
* @returns A pointer to a wide string representing the file access mode.
|
||||
*/
|
||||
[[nodiscard]] constexpr const wchar_t* AccessModeToWStr(FileAccessMode mode, FileType type) {
|
||||
switch (type) {
|
||||
case FileType::BinaryFile:
|
||||
switch (mode) {
|
||||
case FileAccessMode::Read:
|
||||
return L"rb";
|
||||
case FileAccessMode::Write:
|
||||
return L"wb";
|
||||
case FileAccessMode::Append:
|
||||
return L"ab";
|
||||
case FileAccessMode::ReadWrite:
|
||||
return L"r+b";
|
||||
case FileAccessMode::ReadAppend:
|
||||
return L"a+b";
|
||||
}
|
||||
break;
|
||||
case FileType::TextFile:
|
||||
switch (mode) {
|
||||
case FileAccessMode::Read:
|
||||
return L"r";
|
||||
case FileAccessMode::Write:
|
||||
return L"w";
|
||||
case FileAccessMode::Append:
|
||||
return L"a";
|
||||
case FileAccessMode::ReadWrite:
|
||||
return L"r+";
|
||||
case FileAccessMode::ReadAppend:
|
||||
return L"a+";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return L"";
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the file-share access flag enum to a Windows defined file-share access flag.
|
||||
*
|
||||
* @param flag File-share access flag
|
||||
*
|
||||
* @returns Windows defined file-share access flag.
|
||||
*/
|
||||
[[nodiscard]] constexpr int ToWindowsFileShareFlag(FileShareFlag flag) {
|
||||
switch (flag) {
|
||||
case FileShareFlag::ShareNone:
|
||||
default:
|
||||
return _SH_DENYRW;
|
||||
case FileShareFlag::ShareReadOnly:
|
||||
return _SH_DENYWR;
|
||||
case FileShareFlag::ShareWriteOnly:
|
||||
return _SH_DENYRD;
|
||||
case FileShareFlag::ShareReadWrite:
|
||||
return _SH_DENYNO;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* Converts the file access mode and file type enums to a file access mode string.
|
||||
*
|
||||
* @param mode File access mode
|
||||
* @param type File type
|
||||
*
|
||||
* @returns A pointer to a string representing the file access mode.
|
||||
*/
|
||||
[[nodiscard]] constexpr const char* AccessModeToStr(FileAccessMode mode, FileType type) {
|
||||
switch (type) {
|
||||
case FileType::BinaryFile:
|
||||
switch (mode) {
|
||||
case FileAccessMode::Read:
|
||||
return "rb";
|
||||
case FileAccessMode::Write:
|
||||
return "wb";
|
||||
case FileAccessMode::Append:
|
||||
return "ab";
|
||||
case FileAccessMode::ReadWrite:
|
||||
return "r+b";
|
||||
case FileAccessMode::ReadAppend:
|
||||
return "a+b";
|
||||
}
|
||||
break;
|
||||
case FileType::TextFile:
|
||||
switch (mode) {
|
||||
case FileAccessMode::Read:
|
||||
return "r";
|
||||
case FileAccessMode::Write:
|
||||
return "w";
|
||||
case FileAccessMode::Append:
|
||||
return "a";
|
||||
case FileAccessMode::ReadWrite:
|
||||
return "r+";
|
||||
case FileAccessMode::ReadAppend:
|
||||
return "a+";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Converts the seek origin enum to a seek origin integer.
|
||||
*
|
||||
* @param origin Seek origin
|
||||
*
|
||||
* @returns Seek origin integer.
|
||||
*/
|
||||
[[nodiscard]] constexpr int ToSeekOrigin(SeekOrigin origin) {
|
||||
switch (origin) {
|
||||
case SeekOrigin::SetOrigin:
|
||||
default:
|
||||
return SEEK_SET;
|
||||
case SeekOrigin::CurrentPosition:
|
||||
return SEEK_CUR;
|
||||
case SeekOrigin::End:
|
||||
return SEEK_END;
|
||||
}
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
std::string ReadStringFromFile(const std::filesystem::path& path, FileType type) {
|
||||
if (!IsFile(path)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
IOFile io_file{path, FileAccessMode::Read, type};
|
||||
|
||||
return io_file.ReadString(io_file.GetSize());
|
||||
}
|
||||
|
||||
size_t WriteStringToFile(const std::filesystem::path& path, FileType type,
|
||||
std::string_view string) {
|
||||
if (!IsFile(path)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
IOFile io_file{path, FileAccessMode::Write, type};
|
||||
|
||||
return io_file.WriteString(string);
|
||||
}
|
||||
|
||||
size_t AppendStringToFile(const std::filesystem::path& path, FileType type,
|
||||
std::string_view string) {
|
||||
if (!Exists(path)) {
|
||||
return WriteStringToFile(path, type, string);
|
||||
}
|
||||
|
||||
if (!IsFile(path)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
IOFile io_file{path, FileAccessMode::Append, type};
|
||||
|
||||
return io_file.WriteString(string);
|
||||
}
|
||||
|
||||
IOFile::IOFile() = default;
|
||||
|
||||
IOFile::IOFile(const std::string& path, FileAccessMode mode, FileType type, FileShareFlag flag) {
|
||||
Open(path, mode, type, flag);
|
||||
}
|
||||
|
||||
IOFile::IOFile(std::string_view path, FileAccessMode mode, FileType type, FileShareFlag flag) {
|
||||
Open(path, mode, type, flag);
|
||||
}
|
||||
|
||||
IOFile::IOFile(const fs::path& path, FileAccessMode mode, FileType type, FileShareFlag flag) {
|
||||
Open(path, mode, type, flag);
|
||||
}
|
||||
|
||||
IOFile::~IOFile() {
|
||||
Close();
|
||||
}
|
||||
|
||||
IOFile::IOFile(IOFile&& other) noexcept {
|
||||
std::swap(file_path, other.file_path);
|
||||
std::swap(file_access_mode, other.file_access_mode);
|
||||
std::swap(file_type, other.file_type);
|
||||
std::swap(file, other.file);
|
||||
}
|
||||
|
||||
IOFile& IOFile::operator=(IOFile&& other) noexcept {
|
||||
std::swap(file_path, other.file_path);
|
||||
std::swap(file_access_mode, other.file_access_mode);
|
||||
std::swap(file_type, other.file_type);
|
||||
std::swap(file, other.file);
|
||||
return *this;
|
||||
}
|
||||
|
||||
fs::path IOFile::GetPath() const {
|
||||
return file_path;
|
||||
}
|
||||
|
||||
FileAccessMode IOFile::GetAccessMode() const {
|
||||
return file_access_mode;
|
||||
}
|
||||
|
||||
FileType IOFile::GetType() const {
|
||||
return file_type;
|
||||
}
|
||||
|
||||
void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, FileShareFlag flag) {
|
||||
Close();
|
||||
|
||||
file_path = path;
|
||||
file_access_mode = mode;
|
||||
file_type = type;
|
||||
|
||||
errno = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (flag != FileShareFlag::ShareNone) {
|
||||
file = _wfsopen(path.c_str(), AccessModeToWStr(mode, type), ToWindowsFileShareFlag(flag));
|
||||
} else {
|
||||
_wfopen_s(&file, path.c_str(), AccessModeToWStr(mode, type));
|
||||
}
|
||||
#else
|
||||
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
|
||||
#endif
|
||||
|
||||
if (!IsOpen()) {
|
||||
const auto ec = std::error_code{errno, std::generic_category()};
|
||||
LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}, ec_message={}",
|
||||
PathToUTF8String(file_path), ec.message());
|
||||
}
|
||||
}
|
||||
|
||||
void IOFile::Close() {
|
||||
if (!IsOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
||||
const auto close_result = std::fclose(file) == 0;
|
||||
|
||||
if (!close_result) {
|
||||
const auto ec = std::error_code{errno, std::generic_category()};
|
||||
LOG_ERROR(Common_Filesystem, "Failed to close the file at path={}, ec_message={}",
|
||||
PathToUTF8String(file_path), ec.message());
|
||||
}
|
||||
|
||||
file = nullptr;
|
||||
}
|
||||
|
||||
bool IOFile::IsOpen() const {
|
||||
return file != nullptr;
|
||||
}
|
||||
|
||||
std::string IOFile::ReadString(size_t length) const {
|
||||
std::vector<char> string_buffer(length);
|
||||
|
||||
const auto chars_read = ReadSpan<char>(string_buffer);
|
||||
const auto string_size = chars_read != length ? chars_read : length;
|
||||
|
||||
return std::string{string_buffer.data(), string_size};
|
||||
}
|
||||
|
||||
size_t IOFile::WriteString(std::span<const char> string) const {
|
||||
return WriteSpan(string);
|
||||
}
|
||||
|
||||
bool IOFile::Flush() const {
|
||||
if (!IsOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
||||
const auto flush_result = std::fflush(file) == 0;
|
||||
|
||||
if (!flush_result) {
|
||||
const auto ec = std::error_code{errno, std::generic_category()};
|
||||
LOG_ERROR(Common_Filesystem, "Failed to flush the file at path={}, ec_message={}",
|
||||
PathToUTF8String(file_path), ec.message());
|
||||
}
|
||||
|
||||
return flush_result;
|
||||
}
|
||||
|
||||
bool IOFile::SetSize(u64 size) const {
|
||||
if (!IsOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
const auto set_size_result = _chsize_s(fileno(file), static_cast<s64>(size)) == 0;
|
||||
#else
|
||||
const auto set_size_result = ftruncate(fileno(file), static_cast<s64>(size)) == 0;
|
||||
#endif
|
||||
|
||||
if (!set_size_result) {
|
||||
const auto ec = std::error_code{errno, std::generic_category()};
|
||||
LOG_ERROR(Common_Filesystem, "Failed to resize the file at path={}, size={}, ec_message={}",
|
||||
PathToUTF8String(file_path), size, ec.message());
|
||||
}
|
||||
|
||||
return set_size_result;
|
||||
}
|
||||
|
||||
u64 IOFile::GetSize() const {
|
||||
if (!IsOpen()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
const auto file_size = fs::file_size(file_path, ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to retrieve the file size of path={}, ec_message={}",
|
||||
PathToUTF8String(file_path), ec.message());
|
||||
return 0;
|
||||
}
|
||||
|
||||
return file_size;
|
||||
}
|
||||
|
||||
bool IOFile::Seek(s64 offset, SeekOrigin origin) const {
|
||||
if (!IsOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
||||
const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0;
|
||||
|
||||
if (!seek_result) {
|
||||
const auto ec = std::error_code{errno, std::generic_category()};
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"Failed to seek the file at path={}, offset={}, origin={}, ec_message={}",
|
||||
PathToUTF8String(file_path), offset, origin, ec.message());
|
||||
}
|
||||
|
||||
return seek_result;
|
||||
}
|
||||
|
||||
s64 IOFile::Tell() const {
|
||||
if (!IsOpen()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
||||
return ftello(file);
|
||||
}
|
||||
|
||||
} // namespace Common::FS
|
||||
@@ -0,0 +1,453 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <span>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "common/concepts.h"
|
||||
#include "common/fs/fs_types.h"
|
||||
#include "common/fs/fs_util.h"
|
||||
|
||||
namespace Common::FS {
|
||||
|
||||
enum class SeekOrigin {
|
||||
SetOrigin, // Seeks from the start of the file.
|
||||
CurrentPosition, // Seeks from the current file pointer position.
|
||||
End, // Seeks from the end of the file.
|
||||
};
|
||||
|
||||
/**
|
||||
* Opens a file stream at path with the specified open mode.
|
||||
*
|
||||
* @param file_stream Reference to file stream
|
||||
* @param path Filesystem path
|
||||
* @param open_mode File stream open mode
|
||||
*/
|
||||
template <typename FileStream>
|
||||
void OpenFileStream(FileStream& file_stream, const std::filesystem::path& path,
|
||||
std::ios_base::openmode open_mode) {
|
||||
file_stream.open(path, open_mode);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
template <typename FileStream, typename Path>
|
||||
void OpenFileStream(FileStream& file_stream, const Path& path, std::ios_base::openmode open_mode) {
|
||||
if constexpr (IsChar<typename Path::value_type>) {
|
||||
file_stream.open(ToU8String(path), open_mode);
|
||||
} else {
|
||||
file_stream.open(std::filesystem::path{path}, open_mode);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Reads an entire file at path and returns a string of the contents read from the file.
|
||||
* If the filesystem object at path is not a file, this function returns an empty string.
|
||||
*
|
||||
* @param path Filesystem path
|
||||
* @param type File type
|
||||
*
|
||||
* @returns A string of the contents read from the file.
|
||||
*/
|
||||
[[nodiscard]] std::string ReadStringFromFile(const std::filesystem::path& path, FileType type);
|
||||
|
||||
#ifdef _WIN32
|
||||
template <typename Path>
|
||||
[[nodiscard]] std::string ReadStringFromFile(const Path& path, FileType type) {
|
||||
if constexpr (IsChar<typename Path::value_type>) {
|
||||
return ReadStringFromFile(ToU8String(path), type);
|
||||
} else {
|
||||
return ReadStringFromFile(std::filesystem::path{path}, type);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Writes a string to a file at path and returns the number of characters successfully written.
|
||||
* If an file already exists at path, its contents will be erased.
|
||||
* If the filesystem object at path is not a file, this function returns 0.
|
||||
*
|
||||
* @param path Filesystem path
|
||||
* @param type File type
|
||||
*
|
||||
* @returns Number of characters successfully written.
|
||||
*/
|
||||
[[nodiscard]] size_t WriteStringToFile(const std::filesystem::path& path, FileType type,
|
||||
std::string_view string);
|
||||
|
||||
#ifdef _WIN32
|
||||
template <typename Path>
|
||||
[[nodiscard]] size_t WriteStringToFile(const Path& path, FileType type, std::string_view string) {
|
||||
if constexpr (IsChar<typename Path::value_type>) {
|
||||
return WriteStringToFile(ToU8String(path), type, string);
|
||||
} else {
|
||||
return WriteStringToFile(std::filesystem::path{path}, type, string);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Appends a string to a file at path and returns the number of characters successfully written.
|
||||
* If a file does not exist at path, WriteStringToFile is called instead.
|
||||
* If the filesystem object at path is not a file, this function returns 0.
|
||||
*
|
||||
* @param path Filesystem path
|
||||
* @param type File type
|
||||
*
|
||||
* @returns Number of characters successfully written.
|
||||
*/
|
||||
[[nodiscard]] size_t AppendStringToFile(const std::filesystem::path& path, FileType type,
|
||||
std::string_view string);
|
||||
|
||||
#ifdef _WIN32
|
||||
template <typename Path>
|
||||
[[nodiscard]] size_t AppendStringToFile(const Path& path, FileType type, std::string_view string) {
|
||||
if constexpr (IsChar<typename Path::value_type>) {
|
||||
return AppendStringToFile(ToU8String(path), type, string);
|
||||
} else {
|
||||
return AppendStringToFile(std::filesystem::path{path}, type, string);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
class IOFile final {
|
||||
public:
|
||||
IOFile();
|
||||
|
||||
explicit IOFile(const std::string& path, FileAccessMode mode,
|
||||
FileType type = FileType::BinaryFile,
|
||||
FileShareFlag flag = FileShareFlag::ShareReadOnly);
|
||||
|
||||
explicit IOFile(std::string_view path, FileAccessMode mode,
|
||||
FileType type = FileType::BinaryFile,
|
||||
FileShareFlag flag = FileShareFlag::ShareReadOnly);
|
||||
|
||||
/**
|
||||
* An IOFile is a lightweight wrapper on C Library file operations.
|
||||
* Automatically closes an open file on the destruction of an IOFile object.
|
||||
*
|
||||
* @param path Filesystem path
|
||||
* @param mode File access mode
|
||||
* @param type File type, default is BinaryFile. Use TextFile to open the file as a text file
|
||||
* @param flag (Windows only) File-share access flag, default is ShareReadOnly
|
||||
*/
|
||||
explicit IOFile(const std::filesystem::path& path, FileAccessMode mode,
|
||||
FileType type = FileType::BinaryFile,
|
||||
FileShareFlag flag = FileShareFlag::ShareReadOnly);
|
||||
|
||||
~IOFile();
|
||||
|
||||
IOFile(const IOFile&) = delete;
|
||||
IOFile& operator=(const IOFile&) = delete;
|
||||
|
||||
IOFile(IOFile&& other) noexcept;
|
||||
IOFile& operator=(IOFile&& other) noexcept;
|
||||
|
||||
/**
|
||||
* Gets the path of the file.
|
||||
*
|
||||
* @returns The path of the file.
|
||||
*/
|
||||
[[nodiscard]] std::filesystem::path GetPath() const;
|
||||
|
||||
/**
|
||||
* Gets the access mode of the file.
|
||||
*
|
||||
* @returns The access mode of the file.
|
||||
*/
|
||||
[[nodiscard]] FileAccessMode GetAccessMode() const;
|
||||
|
||||
/**
|
||||
* Gets the type of the file.
|
||||
*
|
||||
* @returns The type of the file.
|
||||
*/
|
||||
[[nodiscard]] FileType GetType() const;
|
||||
|
||||
/**
|
||||
* Opens a file at path with the specified file access mode.
|
||||
* This function behaves differently depending on the FileAccessMode.
|
||||
* These behaviors are documented in each enum value of FileAccessMode.
|
||||
*
|
||||
* @param path Filesystem path
|
||||
* @param mode File access mode
|
||||
* @param type File type, default is BinaryFile. Use TextFile to open the file as a text file
|
||||
* @param flag (Windows only) File-share access flag, default is ShareReadOnly
|
||||
*/
|
||||
void Open(const std::filesystem::path& path, FileAccessMode mode,
|
||||
FileType type = FileType::BinaryFile,
|
||||
FileShareFlag flag = FileShareFlag::ShareReadOnly);
|
||||
|
||||
#ifdef _WIN32
|
||||
template <typename Path>
|
||||
[[nodiscard]] void Open(const Path& path, FileAccessMode mode,
|
||||
FileType type = FileType::BinaryFile,
|
||||
FileShareFlag flag = FileShareFlag::ShareReadOnly) {
|
||||
using ValueType = typename Path::value_type;
|
||||
if constexpr (IsChar<ValueType>) {
|
||||
Open(ToU8String(path), mode, type, flag);
|
||||
} else {
|
||||
Open(std::filesystem::path{path}, mode, type, flag);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Closes the file if it is opened.
|
||||
void Close();
|
||||
|
||||
/**
|
||||
* Checks whether the file is open.
|
||||
* Use this to check whether the calls to Open() or Close() succeeded.
|
||||
*
|
||||
* @returns True if the file is open, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] bool IsOpen() const;
|
||||
|
||||
/**
|
||||
* Helper function which deduces the value type of a contiguous STL container used in ReadSpan.
|
||||
* If T is not a contiguous STL container as defined by the concept IsSTLContainer, this calls
|
||||
* ReadObject and T must be a trivially copyable object.
|
||||
*
|
||||
* See ReadSpan for more details if T is a contiguous container.
|
||||
* See ReadObject for more details if T is a trivially copyable object.
|
||||
*
|
||||
* @tparam T Contiguous container or trivially copyable object
|
||||
*
|
||||
* @param data Container of T::value_type data or reference to object
|
||||
*
|
||||
* @returns Count of T::value_type data or objects successfully read.
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] size_t Read(T& data) const {
|
||||
if constexpr (IsSTLContainer<T>) {
|
||||
using ContiguousType = typename T::value_type;
|
||||
static_assert(std::is_trivially_copyable_v<ContiguousType>,
|
||||
"Data type must be trivially copyable.");
|
||||
return ReadSpan<ContiguousType>(data);
|
||||
} else {
|
||||
return ReadObject(data) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function which deduces the value type of a contiguous STL container used in WriteSpan.
|
||||
* If T is not a contiguous STL container as defined by the concept IsSTLContainer, this calls
|
||||
* WriteObject and T must be a trivially copyable object.
|
||||
*
|
||||
* See WriteSpan for more details if T is a contiguous container.
|
||||
* See WriteObject for more details if T is a trivially copyable object.
|
||||
*
|
||||
* @tparam T Contiguous container or trivially copyable object
|
||||
*
|
||||
* @param data Container of T::value_type data or const reference to object
|
||||
*
|
||||
* @returns Count of T::value_type data or objects successfully written.
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] size_t Write(const T& data) const {
|
||||
if constexpr (IsSTLContainer<T>) {
|
||||
using ContiguousType = typename T::value_type;
|
||||
static_assert(std::is_trivially_copyable_v<ContiguousType>,
|
||||
"Data type must be trivially copyable.");
|
||||
return WriteSpan<ContiguousType>(data);
|
||||
} else {
|
||||
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
|
||||
return WriteObject(data) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a span of T data from a file sequentially.
|
||||
* This function reads from the current position of the file pointer and
|
||||
* advances it by the (count of T * sizeof(T)) bytes successfully read.
|
||||
*
|
||||
* Failures occur when:
|
||||
* - The file is not open
|
||||
* - The opened file lacks read permissions
|
||||
* - Attempting to read beyond the end-of-file
|
||||
*
|
||||
* @tparam T Data type
|
||||
*
|
||||
* @param data Span of T data
|
||||
*
|
||||
* @returns Count of T data successfully read.
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] size_t ReadSpan(std::span<T> data) const {
|
||||
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
|
||||
|
||||
if (!IsOpen()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return std::fread(data.data(), sizeof(T), data.size(), file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a span of T data to a file sequentially.
|
||||
* This function writes from the current position of the file pointer and
|
||||
* advances it by the (count of T * sizeof(T)) bytes successfully written.
|
||||
*
|
||||
* Failures occur when:
|
||||
* - The file is not open
|
||||
* - The opened file lacks write permissions
|
||||
*
|
||||
* @tparam T Data type
|
||||
*
|
||||
* @param data Span of T data
|
||||
*
|
||||
* @returns Count of T data successfully written.
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] size_t WriteSpan(std::span<const T> data) const {
|
||||
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
|
||||
|
||||
if (!IsOpen()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return std::fwrite(data.data(), sizeof(T), data.size(), file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a T object from a file sequentially.
|
||||
* This function reads from the current position of the file pointer and
|
||||
* advances it by the sizeof(T) bytes successfully read.
|
||||
*
|
||||
* Failures occur when:
|
||||
* - The file is not open
|
||||
* - The opened file lacks read permissions
|
||||
* - Attempting to read beyond the end-of-file
|
||||
*
|
||||
* @tparam T Data type
|
||||
*
|
||||
* @param object Reference to object
|
||||
*
|
||||
* @returns True if the object is successfully read from the file, false otherwise.
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] bool ReadObject(T& object) const {
|
||||
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
|
||||
static_assert(!std::is_pointer_v<T>, "T must not be a pointer to an object.");
|
||||
|
||||
if (!IsOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::fread(&object, sizeof(T), 1, file) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a T object to a file sequentially.
|
||||
* This function writes from the current position of the file pointer and
|
||||
* advances it by the sizeof(T) bytes successfully written.
|
||||
*
|
||||
* Failures occur when:
|
||||
* - The file is not open
|
||||
* - The opened file lacks write permissions
|
||||
*
|
||||
* @tparam T Data type
|
||||
*
|
||||
* @param object Const reference to object
|
||||
*
|
||||
* @returns True if the object is successfully written to the file, false otherwise.
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] bool WriteObject(const T& object) const {
|
||||
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
|
||||
static_assert(!std::is_pointer_v<T>, "T must not be a pointer to an object.");
|
||||
|
||||
if (!IsOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::fwrite(&object, sizeof(T), 1, file) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialized function to read a string of a given length from a file sequentially.
|
||||
* This function writes from the current position of the file pointer and
|
||||
* advances it by the number of characters successfully read.
|
||||
* The size of the returned string may not match length if not all bytes are successfully read.
|
||||
*
|
||||
* @param length Length of the string
|
||||
*
|
||||
* @returns A string read from the file.
|
||||
*/
|
||||
[[nodiscard]] std::string ReadString(size_t length) const;
|
||||
|
||||
/**
|
||||
* Specialized function to write a string to a file sequentially.
|
||||
* This function writes from the current position of the file pointer and
|
||||
* advances it by the number of characters successfully written.
|
||||
*
|
||||
* @param string Span of const char backed std::string or std::string_view
|
||||
*
|
||||
* @returns Number of characters successfully written.
|
||||
*/
|
||||
[[nodiscard]] size_t WriteString(std::span<const char> string) const;
|
||||
|
||||
/**
|
||||
* Flushes any unwritten buffered data into the file.
|
||||
*
|
||||
* @returns True if the flush was successful, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] bool Flush() const;
|
||||
|
||||
/**
|
||||
* Resizes the file to a given size.
|
||||
* If the file is resized to a smaller size, the remainder of the file is discarded.
|
||||
* If the file is resized to a larger size, the new area appears as if zero-filled.
|
||||
*
|
||||
* Failures occur when:
|
||||
* - The file is not open
|
||||
*
|
||||
* @param size File size in bytes
|
||||
*
|
||||
* @returns True if the file resize succeeded, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] bool SetSize(u64 size) const;
|
||||
|
||||
/**
|
||||
* Gets the size of the file.
|
||||
*
|
||||
* Failures occur when:
|
||||
* - The file is not open
|
||||
*
|
||||
* @returns The file size in bytes of the file. Returns 0 on failure.
|
||||
*/
|
||||
[[nodiscard]] u64 GetSize() const;
|
||||
|
||||
/**
|
||||
* Moves the current position of the file pointer with the specified offset and seek origin.
|
||||
*
|
||||
* @param offset Offset from seek origin
|
||||
* @param origin Seek origin
|
||||
*
|
||||
* @returns True if the file pointer has moved to the specified offset, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] bool Seek(s64 offset, SeekOrigin origin = SeekOrigin::SetOrigin) const;
|
||||
|
||||
/**
|
||||
* Gets the current position of the file pointer.
|
||||
*
|
||||
* @returns The current position of the file pointer.
|
||||
*/
|
||||
[[nodiscard]] s64 Tell() const;
|
||||
|
||||
private:
|
||||
std::filesystem::path file_path;
|
||||
FileAccessMode file_access_mode{};
|
||||
FileType file_type{};
|
||||
|
||||
std::FILE* file = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Common::FS
|
||||
@@ -0,0 +1,610 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/fs/file.h"
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/logging/log.h"
|
||||
|
||||
namespace Common::FS {
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
// File Operations
|
||||
|
||||
bool NewFile(const fs::path& path, u64 size) {
|
||||
if (!ValidatePath(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Exists(path.parent_path())) {
|
||||
LOG_ERROR(Common_Filesystem, "Parent directory of path={} does not exist",
|
||||
PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Exists(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at path={} exists", PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
IOFile io_file{path, FileAccessMode::Write};
|
||||
|
||||
if (!io_file.IsOpen()) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to create a file at path={}", PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!io_file.SetSize(size)) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to resize the file at path={} to size={}",
|
||||
PathToUTF8String(path), size);
|
||||
return false;
|
||||
}
|
||||
|
||||
io_file.Close();
|
||||
|
||||
LOG_DEBUG(Common_Filesystem, "Successfully created a file at path={} with size={}",
|
||||
PathToUTF8String(path), size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RemoveFile(const fs::path& path) {
|
||||
if (!ValidatePath(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Exists(path)) {
|
||||
LOG_DEBUG(Common_Filesystem, "Filesystem object at path={} does not exist",
|
||||
PathToUTF8String(path));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsFile(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at path={} is not a file",
|
||||
PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
fs::remove(path, ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to remove the file at path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG(Common_Filesystem, "Successfully removed the file at path={}",
|
||||
PathToUTF8String(path));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenameFile(const fs::path& old_path, const fs::path& new_path) {
|
||||
if (!ValidatePath(old_path) || !ValidatePath(new_path)) {
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"One or both input path(s) is not valid, old_path={}, new_path={}",
|
||||
PathToUTF8String(old_path), PathToUTF8String(new_path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Exists(old_path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at old_path={} does not exist",
|
||||
PathToUTF8String(old_path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsFile(old_path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at old_path={} is not a file",
|
||||
PathToUTF8String(old_path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Exists(new_path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at new_path={} exists",
|
||||
PathToUTF8String(new_path));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
fs::rename(old_path, new_path, ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"Failed to rename the file from old_path={} to new_path={}, ec_message={}",
|
||||
PathToUTF8String(old_path), PathToUTF8String(new_path), ec.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG(Common_Filesystem, "Successfully renamed the file from old_path={} to new_path={}",
|
||||
PathToUTF8String(old_path), PathToUTF8String(new_path));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<IOFile> FileOpen(const fs::path& path, FileAccessMode mode, FileType type,
|
||||
FileShareFlag flag) {
|
||||
if (!ValidatePath(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!IsFile(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at path={} is not a file",
|
||||
PathToUTF8String(path));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto io_file = std::make_shared<IOFile>(path, mode, type, flag);
|
||||
|
||||
if (!io_file->IsOpen()) {
|
||||
io_file.reset();
|
||||
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"Failed to open the file at path={} with mode={}, type={}, flag={}",
|
||||
PathToUTF8String(path), mode, type, flag);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LOG_DEBUG(Common_Filesystem,
|
||||
"Successfully opened the file at path={} with mode={}, type={}, flag={}",
|
||||
PathToUTF8String(path), mode, type, flag);
|
||||
|
||||
return io_file;
|
||||
}
|
||||
|
||||
// Directory Operations
|
||||
|
||||
bool CreateDir(const fs::path& path) {
|
||||
if (!ValidatePath(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Exists(path.parent_path())) {
|
||||
LOG_ERROR(Common_Filesystem, "Parent directory of path={} does not exist",
|
||||
PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsDir(path)) {
|
||||
LOG_DEBUG(Common_Filesystem, "Filesystem object at path={} exists and is a directory",
|
||||
PathToUTF8String(path));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
fs::create_directory(path, ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to create the directory at path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG(Common_Filesystem, "Successfully created the directory at path={}",
|
||||
PathToUTF8String(path));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CreateDirs(const fs::path& path) {
|
||||
if (!ValidatePath(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsDir(path)) {
|
||||
LOG_DEBUG(Common_Filesystem, "Filesystem object at path={} exists and is a directory",
|
||||
PathToUTF8String(path));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
fs::create_directories(path, ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to create the directories at path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG(Common_Filesystem, "Successfully created the directories at path={}",
|
||||
PathToUTF8String(path));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CreateParentDir(const fs::path& path) {
|
||||
return CreateDir(path.parent_path());
|
||||
}
|
||||
|
||||
bool CreateParentDirs(const fs::path& path) {
|
||||
return CreateDirs(path.parent_path());
|
||||
}
|
||||
|
||||
bool RemoveDir(const fs::path& path) {
|
||||
if (!ValidatePath(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Exists(path)) {
|
||||
LOG_DEBUG(Common_Filesystem, "Filesystem object at path={} does not exist",
|
||||
PathToUTF8String(path));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsDir(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at path={} is not a directory",
|
||||
PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
fs::remove(path, ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to remove the directory at path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG(Common_Filesystem, "Successfully removed the directory at path={}",
|
||||
PathToUTF8String(path));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RemoveDirRecursively(const fs::path& path) {
|
||||
if (!ValidatePath(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Exists(path)) {
|
||||
LOG_DEBUG(Common_Filesystem, "Filesystem object at path={} does not exist",
|
||||
PathToUTF8String(path));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsDir(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at path={} is not a directory",
|
||||
PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
fs::remove_all(path, ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"Failed to remove the directory and its contents at path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG(Common_Filesystem, "Successfully removed the directory and its contents at path={}",
|
||||
PathToUTF8String(path));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RemoveDirContentsRecursively(const fs::path& path) {
|
||||
if (!ValidatePath(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Exists(path)) {
|
||||
LOG_DEBUG(Common_Filesystem, "Filesystem object at path={} does not exist",
|
||||
PathToUTF8String(path));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsDir(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at path={} is not a directory",
|
||||
PathToUTF8String(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
for (const auto& entry : fs::recursive_directory_iterator(path, ec)) {
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"Failed to completely enumerate the directory at path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
break;
|
||||
}
|
||||
|
||||
fs::remove(entry.path(), ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"Failed to remove the filesystem object at path={}, ec_message={}",
|
||||
PathToUTF8String(entry.path()), ec.message());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"Failed to remove all the contents of the directory at path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG(Common_Filesystem,
|
||||
"Successfully removed all the contents of the directory at path={}",
|
||||
PathToUTF8String(path));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenameDir(const fs::path& old_path, const fs::path& new_path) {
|
||||
if (!ValidatePath(old_path) || !ValidatePath(new_path)) {
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"One or both input path(s) is not valid, old_path={}, new_path={}",
|
||||
PathToUTF8String(old_path), PathToUTF8String(new_path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Exists(old_path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at old_path={} does not exist",
|
||||
PathToUTF8String(old_path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsDir(old_path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at old_path={} is not a directory",
|
||||
PathToUTF8String(old_path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Exists(new_path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at new_path={} exists",
|
||||
PathToUTF8String(new_path));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
fs::rename(old_path, new_path, ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"Failed to rename the file from old_path={} to new_path={}, ec_message={}",
|
||||
PathToUTF8String(old_path), PathToUTF8String(new_path), ec.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG(Common_Filesystem, "Successfully renamed the file from old_path={} to new_path={}",
|
||||
PathToUTF8String(old_path), PathToUTF8String(new_path));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IterateDirEntries(const std::filesystem::path& path, const DirEntryCallable& callback,
|
||||
DirEntryFilter filter) {
|
||||
if (!ValidatePath(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Exists(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at path={} does not exist",
|
||||
PathToUTF8String(path));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsDir(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at path={} is not a directory",
|
||||
PathToUTF8String(path));
|
||||
return;
|
||||
}
|
||||
|
||||
bool callback_error = false;
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
for (const auto& entry : fs::directory_iterator(path, ec)) {
|
||||
if (ec) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (True(filter & DirEntryFilter::File) &&
|
||||
entry.status().type() == fs::file_type::regular) {
|
||||
if (!callback(entry.path())) {
|
||||
callback_error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (True(filter & DirEntryFilter::Directory) &&
|
||||
entry.status().type() == fs::file_type::directory) {
|
||||
if (!callback(entry.path())) {
|
||||
callback_error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (callback_error || ec) {
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"Failed to visit all the directory entries of path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DEBUG(Common_Filesystem, "Successfully visited all the directory entries of path={}",
|
||||
PathToUTF8String(path));
|
||||
}
|
||||
|
||||
void IterateDirEntriesRecursively(const std::filesystem::path& path,
|
||||
const DirEntryCallable& callback, DirEntryFilter filter) {
|
||||
if (!ValidatePath(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Exists(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at path={} does not exist",
|
||||
PathToUTF8String(path));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsDir(path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at path={} is not a directory",
|
||||
PathToUTF8String(path));
|
||||
return;
|
||||
}
|
||||
|
||||
bool callback_error = false;
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
for (const auto& entry : fs::recursive_directory_iterator(path, ec)) {
|
||||
if (ec) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (True(filter & DirEntryFilter::File) &&
|
||||
entry.status().type() == fs::file_type::regular) {
|
||||
if (!callback(entry.path())) {
|
||||
callback_error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (True(filter & DirEntryFilter::Directory) &&
|
||||
entry.status().type() == fs::file_type::directory) {
|
||||
if (!callback(entry.path())) {
|
||||
callback_error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (callback_error || ec) {
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"Failed to visit all the directory entries of path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DEBUG(Common_Filesystem, "Successfully visited all the directory entries of path={}",
|
||||
PathToUTF8String(path));
|
||||
}
|
||||
|
||||
// Generic Filesystem Operations
|
||||
|
||||
bool Exists(const fs::path& path) {
|
||||
return fs::exists(path);
|
||||
}
|
||||
|
||||
bool IsFile(const fs::path& path) {
|
||||
return fs::is_regular_file(path);
|
||||
}
|
||||
|
||||
bool IsDir(const fs::path& path) {
|
||||
return fs::is_directory(path);
|
||||
}
|
||||
|
||||
fs::path GetCurrentDir() {
|
||||
std::error_code ec;
|
||||
|
||||
const auto current_path = fs::current_path(ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to get the current path, ec_message={}", ec.message());
|
||||
return {};
|
||||
}
|
||||
|
||||
return current_path;
|
||||
}
|
||||
|
||||
bool SetCurrentDir(const fs::path& path) {
|
||||
std::error_code ec;
|
||||
|
||||
fs::current_path(path, ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to set the current path to path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fs::file_type GetEntryType(const fs::path& path) {
|
||||
std::error_code ec;
|
||||
|
||||
const auto file_status = fs::status(path, ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to retrieve the entry type of path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
return fs::file_type::not_found;
|
||||
}
|
||||
|
||||
return file_status.type();
|
||||
}
|
||||
|
||||
u64 GetSize(const fs::path& path) {
|
||||
std::error_code ec;
|
||||
|
||||
const auto file_size = fs::file_size(path, ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to retrieve the file size of path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
return 0;
|
||||
}
|
||||
|
||||
return file_size;
|
||||
}
|
||||
|
||||
u64 GetFreeSpaceSize(const fs::path& path) {
|
||||
std::error_code ec;
|
||||
|
||||
const auto space_info = fs::space(path, ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"Failed to retrieve the available free space of path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
return 0;
|
||||
}
|
||||
|
||||
return space_info.free;
|
||||
}
|
||||
|
||||
u64 GetTotalSpaceSize(const fs::path& path) {
|
||||
std::error_code ec;
|
||||
|
||||
const auto space_info = fs::space(path, ec);
|
||||
|
||||
if (ec) {
|
||||
LOG_ERROR(Common_Filesystem,
|
||||
"Failed to retrieve the total capacity of path={}, ec_message={}",
|
||||
PathToUTF8String(path), ec.message());
|
||||
return 0;
|
||||
}
|
||||
|
||||
return space_info.capacity;
|
||||
}
|
||||
|
||||
} // namespace Common::FS
|
||||