diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..2d1a4be --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,256 @@ +name: Main + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CMAKE_BUILD_PARALLEL_LEVEL: 2 + MAKEFLAGS: '-j 2' + +jobs: + build: + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + os: [windows-latest, ubuntu-latest] + build_type: [Release] + c_compiler: [gcc, cl] + include: + - os: windows-latest + c_compiler: cl + cpp_compiler: cl + - os: ubuntu-latest + c_compiler: gcc + cpp_compiler: g++ + exclude: + - os: windows-latest + c_compiler: gcc + - os: ubuntu-latest + c_compiler: cl + + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - name: Install Qt + uses: jurplel/install-qt-action@v3 + with: + version: "6.6.*" + cache: true + modules: 'qtshadertools' + + - name: Set reusable strings + id: strings + shell: bash + run: | + echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + echo "prefix-dir=${{ github.workspace }}/prefix" >> "$GITHUB_OUTPUT" + + - name: Setup Linux dependencies + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install \ + gettext \ + gamemode-dev \ + libunshield-dev \ + + - name: Cache Prefix + id: cache-prefix-restore + uses: actions/cache/restore@v4 + with: + path: ${{ steps.strings.outputs.prefix-dir }} + key: ${{ runner.os }}-prefix + + - name: Setup Windows dependencies + if: (runner.os == 'Windows') && (steps.cache-prefix-restore.outputs.cache-hit != 'true') + shell: powershell + run: | + $ProgressPreference = 'SilentlyContinue' + + Invoke-WebRequest https://xiv.zone/distrib/dependencies/gettext.zip -OutFile gettext.zip + unzip gettext.zip -d ${{ steps.strings.outputs.prefix-dir }} + + Invoke-WebRequest https://xiv.zone/distrib/dependencies/iconv.zip -OutFile iconv.zip + unzip iconv.zip -d ${{ steps.strings.outputs.prefix-dir }} + + Invoke-WebRequest https://xiv.zone/distrib/dependencies/gcrypt.zip -OutFile gcrypt.zip + unzip gcrypt.zip -d ${{ steps.strings.outputs.prefix-dir }} + + Invoke-WebRequest https://xiv.zone/distrib/dependencies/gpg-error.zip -OutFile gpg-error.zip + unzip gpg-error.zip -d ${{ steps.strings.outputs.prefix-dir }} + + Invoke-WebRequest https://xiv.zone/distrib/dependencies/icoutils.zip -OutFile icoutils.zip + unzip icoutils.zip -d ${{ steps.strings.outputs.prefix-dir }} + + Invoke-WebRequest https://xiv.zone/distrib/dependencies/libwinpthread.zip -OutFile libwinpthread.zip + unzip libwinpthread.zip -d ${{ steps.strings.outputs.prefix-dir }}/bin + + Invoke-WebRequest https://xiv.zone/distrib/dependencies/libcrypto.zip -OutFile libcrypto.zip + unzip libcrypto.zip -d ${{ steps.strings.outputs.prefix-dir }}/bin + + - name: Build zlib + if: (runner.os == 'Windows') && (steps.cache-prefix-restore.outputs.cache-hit != 'true') + run: | + git clone https://github.com/madler/zlib.git + cmake -B ${{ steps.strings.outputs.build-output-dir }}-zlib -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S zlib -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.prefix-dir }} -DBUILD_TESTING=OFF + cmake --build ${{ steps.strings.outputs.build-output-dir }}-zlib --config ${{ matrix.build_type }} --target install + + - name: Build Extra CMake Modules + if: steps.cache-prefix-restore.outputs.cache-hit != 'true' + run: | + git clone https://invent.kde.org/frameworks/extra-cmake-modules.git + cmake -B ${{ steps.strings.outputs.build-output-dir }}-ECM -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S extra-cmake-modules -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.prefix-dir }} -DBUILD_TESTING=OFF + cmake --build ${{ steps.strings.outputs.build-output-dir }}-ECM --config ${{ matrix.build_type }} --target install + cmake --install ${{ steps.strings.outputs.build-output-dir }}-ECM --config ${{ matrix.build_type }} + + - name: Configure KI18n + if: steps.cache-prefix-restore.outputs.cache-hit != 'true' + run: | + git clone https://invent.kde.org/frameworks/ki18n.git + cmake -B ${{ steps.strings.outputs.build-output-dir }}-ki18n -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S ki18n -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.prefix-dir }} -DBUILD_TESTING=OFF + + - name: Windows KI18n workaround + if: (runner.os == 'Windows') && (steps.cache-prefix-restore.outputs.cache-hit != 'true') + run: | + (Get-Content -ReadCount 0 ${{ steps.strings.outputs.build-output-dir }}-ki18n/cmake/build-pofiles.cmake) -replace 'FATAL_ERROR', 'WARNING' | Set-Content ${{ steps.strings.outputs.build-output-dir }}-ki18n/cmake/build-pofiles.cmake + + - name: Build KI18n + if: steps.cache-prefix-restore.outputs.cache-hit != 'true' + run: | + cmake --build ${{ steps.strings.outputs.build-output-dir }}-ki18n --config ${{ matrix.build_type }} --target install + + - name: Build KCoreAddons + if: steps.cache-prefix-restore.outputs.cache-hit != 'true' + run: | + git clone https://invent.kde.org/frameworks/kcoreaddons.git + cmake -B ${{ steps.strings.outputs.build-output-dir }}-kca -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S kcoreaddons -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.prefix-dir }} -DBUILD_TESTING=OFF + cmake --build ${{ steps.strings.outputs.build-output-dir }}-kca --config ${{ matrix.build_type }} --target install + + - name: Build KConfig + if: steps.cache-prefix-restore.outputs.cache-hit != 'true' + run: | + git clone https://invent.kde.org/frameworks/kconfig.git + cmake -B ${{ steps.strings.outputs.build-output-dir }}-kconfig -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S kconfig -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.prefix-dir }} -DBUILD_TESTING=OFF + cmake --build ${{ steps.strings.outputs.build-output-dir }}-kconfig --config ${{ matrix.build_type }} --target install + + - name: Build KArchive + if: steps.cache-prefix-restore.outputs.cache-hit != 'true' + run: | + git clone https://invent.kde.org/frameworks/karchive.git + cmake -B ${{ steps.strings.outputs.build-output-dir }}-karchive -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S karchive -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.prefix-dir }} -DBUILD_TESTING=OFF -DWITH_BZIP2=OFF -DWITH_LIBLZMA=OFF -DWITH_LIBZSTD=OFF # TODO: enable bzip which we need later + cmake --build ${{ steps.strings.outputs.build-output-dir }}-karchive --config ${{ matrix.build_type }} --target install + + - name: Build Kirigami + if: steps.cache-prefix-restore.outputs.cache-hit != 'true' + run: | + git clone https://invent.kde.org/frameworks/kirigami.git + cmake -B ${{ steps.strings.outputs.build-output-dir }}-kirigami -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S kirigami -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.prefix-dir }} -DBUILD_TESTING=OFF + cmake --build ${{ steps.strings.outputs.build-output-dir }}-kirigami --config ${{ matrix.build_type }} --target install + + - name: Build Kirigami Add-ons + if: steps.cache-prefix-restore.outputs.cache-hit != 'true' + run: | + git clone https://invent.kde.org/libraries/kirigami-addons.git + cmake -B ${{ steps.strings.outputs.build-output-dir }}-kirigami-addons -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S kirigami-addons -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.prefix-dir }} -DBUILD_TESTING=OFF + cmake --build ${{ steps.strings.outputs.build-output-dir }}-kirigami-addons --config ${{ matrix.build_type }} --target install + + - name: Build Breeze Icons + if: (runner.os == 'Windows') && (steps.cache-prefix-restore.outputs.cache-hit != 'true') + continue-on-error: true + run: | + git clone https://invent.kde.org/frameworks/breeze-icons.git + cmake -B ${{ steps.strings.outputs.build-output-dir }}-breeze-icons -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S breeze-icons -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.prefix-dir }} -DICONS_LIBRARY=ON -DSKIP_INSTALL_ICONS=ON + cmake --build ${{ steps.strings.outputs.build-output-dir }}-breeze-icons --config ${{ matrix.build_type }} --target install + cmake --build ${{ steps.strings.outputs.build-output-dir }}-breeze-icons --config ${{ matrix.build_type }} --target install + + - name: Build Corrosion + if: steps.cache-prefix-restore.outputs.cache-hit != 'true' + run: | + git clone https://github.com/corrosion-rs/corrosion.git + cmake -B ${{ steps.strings.outputs.build-output-dir }}-corrosion -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S corrosion -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.prefix-dir }} -DCORROSION_BUILD_TESTS=OFF + cmake --build ${{ steps.strings.outputs.build-output-dir }}-corrosion --config ${{ matrix.build_type }} --target install + + - name: Build QCoro + if: steps.cache-prefix-restore.outputs.cache-hit != 'true' + run: | + git clone https://github.com/danvratil/qcoro.git + cmake -B ${{ steps.strings.outputs.build-output-dir }}-qcoro -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S qcoro -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.prefix-dir }} -DBUILD_TESTING=OFF -DQCORO_WITH_QTWEBSOCKETS=OFF -DQCORO_BUILD_EXAMPLES=OFF + cmake --build ${{ steps.strings.outputs.build-output-dir }}-qcoro --config ${{ matrix.build_type }} --target install + + - name: Build QtKeychain + if: steps.cache-prefix-restore.outputs.cache-hit != 'true' + run: | + git clone https://github.com/redstrate/qtkeychain.git + cmake -B ${{ steps.strings.outputs.build-output-dir }}-qtkeychain -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S qtkeychain -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.prefix-dir }} -DBUILD_TESTING=OFF -DBUILD_WITH_QT6=ON -DQTKEYCHAIN_TARGET_NAME=keychain + cmake --build ${{ steps.strings.outputs.build-output-dir }}-qtkeychain --config ${{ matrix.build_type }} --target install + + - name: Build unshield + if: steps.cache-prefix-restore.outputs.cache-hit != 'true' + run: | + git clone https://github.com/twogood/unshield.git + cmake -B ${{ steps.strings.outputs.build-output-dir }}-unshield -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S unshield -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.prefix-dir }} -DBUILD_TESTING=OFF + cmake --build ${{ steps.strings.outputs.build-output-dir }}-unshield --config ${{ matrix.build_type }} --target install + + - name: Save Prefix + id: cache-prefix-save + uses: actions/cache/save@v4 + with: + path: ${{ steps.strings.outputs.prefix-dir }} + key: ${{ steps.cache-prefix-restore.outputs.cache-primary-key }} + + - name: Configure + run: > + cmake -B ${{ steps.strings.outputs.build-output-dir }} + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + -DCMAKE_PREFIX_PATH=${{ steps.strings.outputs.prefix-dir }} + -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.build-output-dir }}/bin + -S ${{ github.workspace }} + + - name: Build + run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} --target install + + - name: Copy required DLLs + if: runner.os == 'Windows' + run: | + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/intl-8.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/iconv.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/zlib.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/q6keychain.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/KF6I18n.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/KF6ConfigGui.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/KF6CoreAddons.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/KF6Archive.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/unshield.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/libgcrypt-20.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/KF6ConfigCore.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/libgpg-error6-0.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/zlib.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/libwinpthread-1.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/libcrypto-1_1-x64.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/KF6BreezeIcons.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/Kirigami.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/KirigamiDelegates.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/bin/KirigamiPlatform.dll -Destination ${{ steps.strings.outputs.build-output-dir }}/bin/bin + + Copy-Item -Path ${{ steps.strings.outputs.prefix-dir }}/lib/qml/* -Destination ${{ steps.strings.outputs.build-output-dir }}/qml/ -Recurse + + - name: Remove extra files + if: runner.os == 'Windows' + run: | + Remove-Item -Path ${{ steps.strings.outputs.build-output-dir }}/bin/bin/opengl32sw.dll + + - name: Archive artifacts + uses: actions/upload-artifact@v4 + with: + name: ${{ runner.os }}-package + path: ${{ steps.strings.outputs.build-output-dir }}/bin \ No newline at end of file diff --git a/.gitignore b/.gitignore index e06e316..54f53e1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,7 @@ .directory *.flatpak export/ -.clang-format \ No newline at end of file +.clang-format +# Windows +local/ +prefix/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 05dc619..d9ed198 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "external/libcotp"] path = external/libcotp - url = https://github.com/paolostivanin/libcotp.git + url = https://github.com/redstrate/libcotp.git [submodule "external/libphysis"] path = external/libphysis url = ../libphysis diff --git a/CMakeLists.txt b/CMakeLists.txt index b5d30f2..e1ae3ac 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,9 +6,12 @@ project(Astra VERSION 0.6.0 LANGUAGES CXX) # build options used for distributors option(BUILD_FLATPAK "Build for Flatpak." OFF) +option(BUILD_WEBVIEW "Build support for the integrated web browser. Only used on the Steam Deck." OFF) # options for features you may want or need -option(ENABLE_GAMEMODE "Build with Feral GameMode support, requires the daemon to be installed." ON) +if (NOT WIN32 AND NOT APPLE) + option(ENABLE_GAMEMODE "Build with Feral GameMode support, requires the daemon to be installed." ON) +endif() set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -27,6 +30,7 @@ include(KDEGitCommitHooks) include(KDEClangFormat) include(ECMAddTests) include(ECMQtDeclareLoggingCategory) +include(ECMAddAppIcon) ecm_setup_version(${PROJECT_VERSION} VARIABLE_PREFIX ASTRA @@ -38,22 +42,29 @@ find_package(Qt6 ${QT_MIN_VERSION} REQUIRED COMPONENTS Widgets Network QuickControls2 - WebView Concurrent Test) +if (BUILD_WEBVIEW) + find_package(Qt6WebView ${QT_MIN_VERSION} REQUIRED) +endif () find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS Kirigami I18n Config CoreAddons Archive) -find_package(PkgConfig REQUIRED) find_package(QCoro6 REQUIRED COMPONENTS Core Network Qml) qcoro_enable_coroutines() qt_policy(SET QTP0001 NEW) if (ENABLE_GAMEMODE) + find_package(PkgConfig REQUIRED) pkg_search_module(GAMEMODE REQUIRED gamemode) endif () find_package(Qt6Keychain REQUIRED) +# TODO: we should really do this on all platforms anyway +if (WIN32) + find_package(KF6BreezeIcons REQUIRED) +endif () + add_subdirectory(external) add_subdirectory(launcher) @@ -61,18 +72,20 @@ if (BUILD_TESTING) add_subdirectory(autotests) endif() -install(FILES zone.xiv.astra.desktop DESTINATION ${KDE_INSTALL_APPDIR}) -install(FILES zone.xiv.astra.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) -install(FILES zone.xiv.astra.svg DESTINATION ${KDE_INSTALL_FULL_ICONDIR}/hicolor/scalable/apps) +if (NOT WIN32) + install(FILES zone.xiv.astra.desktop DESTINATION ${KDE_INSTALL_APPDIR}) + install(FILES zone.xiv.astra.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) + install(FILES zone.xiv.astra.svg DESTINATION ${KDE_INSTALL_FULL_ICONDIR}/hicolor/scalable/apps) + + ecm_qt_install_logging_categories( + EXPORT ASTRA + FILE astra.categories + SORT DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR} + ) +endif() feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) -ecm_qt_install_logging_categories( - EXPORT ASTRA - FILE astra.categories - SORT DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR} -) - file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES src/*.cpp src/*.h) kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES}) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index bcb8793..3ecc9fe 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -16,12 +16,20 @@ corrosion_import_crate(MANIFEST_PATH ${CMAKE_CURRENT_SOURCE_DIR}/libphysis/Cargo FEATURES game_install visual_data) # FIXME: split visual_data? we only need texture decompression add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libphysis/logger EXCLUDE_FROM_ALL) -find_package(PkgConfig REQUIRED) -pkg_check_modules(UNSHIELD REQUIRED IMPORTED_TARGET libunshield) - target_include_directories(physis INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/libphysis/target/public) -target_link_libraries(physis INTERFACE ${UNSHIELD_LIBRARIES} z) -target_link_directories(physis INTERFACE ${UNSHIELD_LIBRARY_DIRS}) + +# We should use the CMake module everywhere once distros update their packages +if (WIN32) + # FIXME: unshield should include zlib in their upstream cmake + find_package(ZLIB REQUIRED) + find_package(unshield REQUIRED) + target_link_libraries(physis INTERFACE unshield::libunshield) +else() + find_package(PkgConfig REQUIRED) + pkg_check_modules(UNSHIELD REQUIRED IMPORTED_TARGET libunshield) + target_link_directories(physis INTERFACE ${UNSHIELD_LIBRARY_DIRS}) + target_link_libraries(physis INTERFACE ${UNSHIELD_LIBRARIES}) +endif() set(KDSingleApplication_QT6 ON) set(KDSingleApplication_STATIC ON) diff --git a/external/libcotp b/external/libcotp index 60461cd..9136e0a 160000 --- a/external/libcotp +++ b/external/libcotp @@ -1 +1 @@ -Subproject commit 60461cd28c297eed476ff93d9b1123c3855c7053 +Subproject commit 9136e0a94f1b4d9afe2d8aa79bfdaf1d1699f265 diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ae3c9d7..b45195d 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -138,7 +138,6 @@ target_link_libraries(astra PRIVATE Qt6::Widgets Qt6::Quick Qt6::QuickControls2 - Qt6::WebView Qt6::Concurrent KF6::Kirigami KF6::I18n @@ -149,7 +148,22 @@ target_link_libraries(astra PRIVATE QCoro::Core QCoro::Network QCoro::Qml) -target_compile_options(astra PRIVATE -fexceptions) +if (BUILD_WEBVIEW) + target_link_libraries(astra PRIVATE + Qt6::WebView + ) + target_compile_definitions(astra PRIVATE HAVE_WEBVIEW) +endif () + +if (WIN32) + target_link_libraries(astra PRIVATE + KF6::BreezeIcons + ) +endif () + +if (NOT MSVC) + target_compile_options(astra PRIVATE -fexceptions) +endif () if (BUILD_FLATPAK) target_compile_definitions(astra PRIVATE FLATPAK) @@ -160,4 +174,28 @@ if (ENABLE_GAMEMODE) target_compile_definitions(astra PRIVATE ENABLE_GAMEMODE) endif () -install(TARGETS astra ${KF6_INSTALL_TARGETS_DEFAULT_ARGS}) \ No newline at end of file +if (WIN32) + set_target_properties(astra PROPERTIES + WIN32_EXECUTABLE TRUE + OUTPUT_NAME "Astra") +endif () + +install(TARGETS astra ${KF6_INSTALL_TARGETS_DEFAULT_ARGS}) + +ecm_add_app_icon(astra + ICONS + ${CMAKE_SOURCE_DIR}/zone.xiv.astra.svg + ${CMAKE_SOURCE_DIR}/resources/16-astra.png + ${CMAKE_SOURCE_DIR}/resources/32-astra.png + ${CMAKE_SOURCE_DIR}/resources/48-astra.png + ${CMAKE_SOURCE_DIR}/resources/256-astra.png +) + +qt_finalize_target(astra) + +qt_generate_deploy_qml_app_script( + TARGET astra + OUTPUT_SCRIPT deploy_script + NO_UNSUPPORTED_PLATFORM_ERROR +) +install(SCRIPT ${deploy_script}) \ No newline at end of file diff --git a/launcher/include/launchercore.h b/launcher/include/launchercore.h index f55d53b..cea0b8f 100755 --- a/launcher/include/launchercore.h +++ b/launcher/include/launchercore.h @@ -62,6 +62,7 @@ class LauncherCore : public QObject Q_PROPERTY(bool loadingFinished READ isLoadingFinished NOTIFY loadingFinished) Q_PROPERTY(bool isSteam READ isSteam CONSTANT) Q_PROPERTY(bool isSteamDeck READ isSteamDeck CONSTANT) + Q_PROPERTY(bool isWindows READ isWindows CONSTANT) Q_PROPERTY(LauncherSettings *settings READ settings CONSTANT) Q_PROPERTY(ProfileManager *profileManager READ profileManager CONSTANT) Q_PROPERTY(AccountManager *accountManager READ accountManager CONSTANT) @@ -110,6 +111,7 @@ public: [[nodiscard]] bool isLoadingFinished() const; [[nodiscard]] bool isSteam() const; [[nodiscard]] bool isSteamDeck() const; + [[nodiscard]] bool isWindows() const; [[nodiscard]] Q_INVOKABLE bool isPatching() const; [[nodiscard]] QNetworkAccessManager *mgr(); diff --git a/launcher/src/launchercore.cpp b/launcher/src/launchercore.cpp index de2a340..0213344 100755 --- a/launcher/src/launchercore.cpp +++ b/launcher/src/launchercore.cpp @@ -302,6 +302,15 @@ bool LauncherCore::isSteamDeck() const } } +bool LauncherCore::isWindows() const +{ +#if defined(Q_OS_WIN) + return true; +#else + return false; +#endif +} + bool LauncherCore::isPatching() const { return m_isPatching; diff --git a/launcher/src/main.cpp b/launcher/src/main.cpp index 079e085..8945646 100755 --- a/launcher/src/main.cpp +++ b/launcher/src/main.cpp @@ -8,10 +8,13 @@ #include #include #include -#include #include #include +#ifdef HAVE_WEBVIEW +#include +#endif + #include "astra-version.h" #include "compatibilitytoolinstaller.h" #include "gameinstaller.h" @@ -20,18 +23,29 @@ #include "physis_logger.h" #include "sapphirelogin.h" +#ifdef Q_OS_WIN +#include +#endif + using namespace Qt::StringLiterals; int main(int argc, char *argv[]) { +#ifdef HAVE_WEBVIEW QtWebView::initialize(); +#endif + +#ifdef Q_OS_WIN + BreezeIcons::initIcons(); + QIcon::setThemeName(QStringLiteral("Breeze")); +#endif if (qEnvironmentVariable("SteamDeck") == QStringLiteral("1")) { qputenv("QT_SCALE_FACTOR", "1.25"); qputenv("QT_QUICK_CONTROLS_MOBILE", "1"); } - QApplication app(argc, argv); + QGuiApplication app(argc, argv); KDSingleApplication singleApplication; if (!singleApplication.isPrimaryInstance()) { @@ -124,6 +138,7 @@ int main(int argc, char *argv[]) } } +#if defined(Q_OS_LINUX) // Default to org.kde.desktop style unless the user forces another style if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE")) { if (isSteamDeck) { @@ -132,6 +147,7 @@ int main(int argc, char *argv[]) QQuickStyle::setStyle(QStringLiteral("org.kde.desktop")); } } +#endif QCoro::Qml::registerTypes(); diff --git a/launcher/src/profilemanager.cpp b/launcher/src/profilemanager.cpp index 3b0ebab..adda7de 100644 --- a/launcher/src/profilemanager.cpp +++ b/launcher/src/profilemanager.cpp @@ -67,13 +67,13 @@ void ProfileManager::deleteProfile(Profile *profile) QString ProfileManager::getDefaultGamePath(const QString &uuid) { #if defined(Q_OS_WIN) - return "C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn"; + return QStringLiteral("C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn"); #endif #if defined(Q_OS_MAC) return QDir::homePath() + - "/Library/Application Support/FINAL FANTASY XIV ONLINE/Bottles/published_Final_Fantasy/drive_c/Program " - "Files (x86)/SquareEnix/FINAL FANTASY XIV - A Realm Reborn"; + QStringLiteral("/Library/Application Support/FINAL FANTASY XIV ONLINE/Bottles/published_Final_Fantasy/drive_c/Program " + "Files (x86)/SquareEnix/FINAL FANTASY XIV - A Realm Reborn"); #endif #if defined(Q_OS_LINUX) diff --git a/launcher/ui/Pages/NewsPage.qml b/launcher/ui/Pages/NewsPage.qml index a574b03..c7bb078 100644 --- a/launcher/ui/Pages/NewsPage.qml +++ b/launcher/ui/Pages/NewsPage.qml @@ -6,7 +6,7 @@ pragma ComponentBehavior: Bound import QtQuick import QtQuick.Controls as QQC2 import QtQuick.Layouts -import Qt5Compat.GraphicalEffects +import QtQuick.Effects import org.kde.kirigami as Kirigami import org.kde.kirigamiaddons.formcard as FormCard @@ -101,15 +101,18 @@ QQC2.Control { } layer.enabled: !(bannerImage.width < layout.maximumWidth) - layer.effect: OpacityMask { - maskSource: Item { - width: bannerImage.width - height: bannerImage.height - Rectangle { - anchors.centerIn: parent - width: bannerImage.width - height: bannerImage.height - radius: Kirigami.Units.smallSpacing + layer.effect: MultiEffect { + id: root + + maskEnabled: true + maskSpreadAtMax: 1 + maskSpreadAtMin: 1 + maskThresholdMin: 0.5 + maskSource: ShaderEffectSource { + sourceItem: Rectangle { + width: root.width + height: root.height + radius: Kirigami.Units.mediumSpacing } } } diff --git a/launcher/ui/Settings/ProfileSettings.qml b/launcher/ui/Settings/ProfileSettings.qml index 597bf7c..1f4b983 100644 --- a/launcher/ui/Settings/ProfileSettings.qml +++ b/launcher/ui/Settings/ProfileSettings.qml @@ -90,6 +90,8 @@ FormCard.FormCardPage { } FormCard.FormCard { + visible: !LauncherCore.isWindows + Layout.fillWidth: true FormCard.FormComboBoxDelegate { @@ -139,9 +141,12 @@ FormCard.FormCardPage { FormCard.FormHeader { title: i18n("Tools") + visible: !LauncherCore.isWindows } FormCard.FormCard { + visible: !LauncherCore.isWindows + Layout.fillWidth: true FormCard.FormCheckDelegate { diff --git a/launcher/ui/Settings/SettingsPage.qml b/launcher/ui/Settings/SettingsPage.qml index 74ef56a..7ca1591 100644 --- a/launcher/ui/Settings/SettingsPage.qml +++ b/launcher/ui/Settings/SettingsPage.qml @@ -51,6 +51,7 @@ KirigamiSettings.CategorizedSettings { text: i18n("Compatibility Tool") icon.name: "system-run" page: Qt.resolvedUrl("/qt/qml/zone/xiv/astra/ui/Settings/CompatibilityToolSetup.qml") + visible: !LauncherCore.isWindows }, KirigamiSettings.SettingAction { actionName: "devtool" diff --git a/resources/16-astra.png b/resources/16-astra.png new file mode 100644 index 0000000..dabb747 Binary files /dev/null and b/resources/16-astra.png differ diff --git a/resources/256-astra.png b/resources/256-astra.png new file mode 100644 index 0000000..a5b1033 Binary files /dev/null and b/resources/256-astra.png differ diff --git a/resources/32-astra.png b/resources/32-astra.png new file mode 100644 index 0000000..0de2b69 Binary files /dev/null and b/resources/32-astra.png differ diff --git a/resources/48-astra.png b/resources/48-astra.png new file mode 100644 index 0000000..3afac01 Binary files /dev/null and b/resources/48-astra.png differ diff --git a/resources/zone.xiv.astra.png b/resources/zone.xiv.astra.png new file mode 100644 index 0000000..dabb747 Binary files /dev/null and b/resources/zone.xiv.astra.png differ diff --git a/scripts/windows-build.ps1 b/scripts/windows-build.ps1 new file mode 100644 index 0000000..7b7adfb --- /dev/null +++ b/scripts/windows-build.ps1 @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2024 NotNite +# SPDX-License-Identifier: CC0-1.0 + +$ErrorActionPreference = "Stop" +$PSNativeCommandUseErrorActionPreference = $true + +$LocalDir = "./local" +$BuildDir = "./build" +$PrefixDir = (Get-Location).Path + "/prefix" + +cmake -B "$BuildDir" "-DCMAKE_PREFIX_PATH=$PrefixDir" "-DCMAKE_CXX_COMPILER=cl" "-DCMAKE_C_COMPILER=cl" "-DCMAKE_BUILD_TYPE=Debug" "-S" . "-DCMAKE_INSTALL_PREFIX=$BuildDir" +cmake --build "$BuildDir" --config Debug --target install + +Copy-Item -Path "$PrefixDir/bin/KF6ItemViews.dll" -Destination "$BuildDir/bin" +Copy-Item -Path "$PrefixDir/bin/KF6IconWidgets.dll" -Destination "$BuildDir/bin" +Copy-Item -Path "$PrefixDir/bin/KF6GuiAddons.dll" -Destination "$BuildDir/bin" +Copy-Item -Path "$PrefixDir/bin/KF6ColorScheme.dll" -Destination "$BuildDir/bin" +Copy-Item -Path "$PrefixDir/bin/intl-8.dll" -Destination "$BuildDir/bin" +Copy-Item -Path "$PrefixDir/bin/KF6IconThemes.dll" -Destination "$BuildDir/bin" +Copy-Item -Path "$PrefixDir/bin/iconv.dll" -Destination "$BuildDir/bin" +Copy-Item -Path "$PrefixDir/bin/zlibd.dll" -Destination "$BuildDir/bin" +Copy-Item -Path "$env:QTDIR/bin/Qt6PrintSupportd.dll" -Destination "$BuildDir/bin" diff --git a/scripts/windows-setup.ps1 b/scripts/windows-setup.ps1 new file mode 100644 index 0000000..6620ffd --- /dev/null +++ b/scripts/windows-setup.ps1 @@ -0,0 +1,145 @@ +# SPDX-FileCopyrightText: 2024 NotNite +# SPDX-License-Identifier: CC0-1.0 + +$ErrorActionPreference = "Stop" +$PSNativeCommandUseErrorActionPreference = $true + +$LocalDir = "./local" +$BuildDir = "$LocalDir/build" +$PrefixDir = (Get-Location).Path + "/prefix" + +$NumCores = [Environment]::ProcessorCount + +function Configure($Name, $ExtraArgs = "") { + $Command = "cmake -B $BuildDir-$Name -DCMAKE_PREFIX_PATH=$PrefixDir -DCMAKE_CXX_COMPILER=cl -DCMAKE_C_COMPILER=cl -DCMAKE_BUILD_TYPE=Debug -S $LocalDir/$Name -DCMAKE_INSTALL_PREFIX=$PrefixDir $ExtraArgs" + Write-Output "Running $Command" + Invoke-Expression $Command + if ($LASTEXITCODE -ne 0) { + throw "Failed to configure $Name" + } +} + +function Clone($Name, $Url) { + if (Test-Path "$LocalDir/$Name") { + Write-Information "Skipping clone of $Name because it's source directory already exists" + } else { + git clone --depth=1 $Url "$LocalDir/$Name" + + if ($LASTEXITCODE -ne 0) { + throw "Failed to clone $Name from $Url" + } + } +} + +function CheckCompileResult($Name) { + if ($LASTEXITCODE -ne 0) { + throw "Failed to build $Name!" + } +} + +if (!(Test-Path $LocalDir)) { + New-Item -ItemType Directory -Path $LocalDir +} + +# Setup Windows dependencies +Invoke-WebRequest https://xiv.zone/distrib/dependencies/gettext.zip -OutFile "$LocalDir/gettext.zip" +Expand-Archive -Path "$LocalDir/gettext.zip" -DestinationPath $PrefixDir -Force + +Invoke-WebRequest https://xiv.zone/distrib/dependencies/iconv.zip -OutFile "$LocalDir/iconv.zip" +Expand-Archive -Path "$LocalDir/iconv.zip" -DestinationPath $PrefixDir -Force + +Invoke-WebRequest https://xiv.zone/distrib/dependencies/icoutils.zip -OutFile "$LocalDir/icoutils.zip" +Expand-Archive -Path "$LocalDir/icoutils.zip" -DestinationPath $PrefixDir -Force + +Invoke-WebRequest https://xiv.zone/distrib/dependencies/gcrypt.zip -OutFile "$LocalDir/gcrypt.zip" +Expand-Archive -Path "$LocalDir/gcrypt.zip" -DestinationPath $PrefixDir -Force + +Invoke-WebRequest https://xiv.zone/distrib/dependencies/gpg-error.zip -OutFile "$LocalDir/gpg-error.zip" +Expand-Archive -Path "$LocalDir/gpg-error.zip" -DestinationPath $PrefixDir -Force + +Invoke-WebRequest https://xiv.zone/distrib/dependencies/libwinpthread.zip -OutFile "$LocalDir/libwinpthread.zip" +Expand-Archive -Path "$LocalDir/libwinpthread.zip" -DestinationPath $PrefixDir -Force + +# Build zlib +Clone "zlib" "https://github.com/madler/zlib.git" +Configure "zlib" "-DBUILD_TESTING=OFF" +cmake --build "$BuildDir-zlib" --config Debug --target install +CheckCompileResult "zlib" + +# Build Extra CMake Modules +Clone "extra-cmake-modules" "https://invent.kde.org/frameworks/extra-cmake-modules.git" +Configure "extra-cmake-modules" "-DBUILD_TESTING=OFF" +cmake --build "$BuildDir-extra-cmake-modules" --config Debug --target install --parallel $NumCores +cmake --install "$BuildDir-extra-cmake-modules" --config Debug +CheckCompileResult "extra-cmake-modules" + +# Build KI18n +Clone "ki18n" "https://invent.kde.org/frameworks/ki18n.git" +# Workaround for Windows +Configure "ki18n" "-DBUILD_TESTING=OFF" + +(Get-Content -ReadCount 0 "$BuildDir-ki18n/cmake/build-pofiles.cmake") -replace 'FATAL_ERROR', 'WARNING' | Set-Content "$BuildDir-ki18n/cmake/build-pofiles.cmake" +cmake --build "$BuildDir-ki18n" --config Debug --target install --parallel $NumCores +CheckCompileResult "ki18n" + +# Build KCoreAddons +Clone "kcoreaddons" "https://invent.kde.org/frameworks/kcoreaddons.git" +Configure "kcoreaddons" "-DBUILD_TESTING=OFF" +cmake --build "$BuildDir-kcoreaddons" --config Debug --target install --parallel $NumCores +CheckCompileResult "kcoreaddons" + +# Build KConfig +Clone "kconfig" "https://invent.kde.org/frameworks/kconfig.git" +Configure "kconfig" "-DBUILD_TESTING=OFF" +cmake --build "$BuildDir-kconfig" --config Debug --target install --parallel $NumCores +CheckCompileResult "kconfig" + +# Build KArchive +Clone "karchive" "https://invent.kde.org/frameworks/karchive.git" +Configure "karchive" "-DBUILD_TESTING=OFF -DWITH_BZIP2=OFF -DWITH_LIBLZMA=OFF -DWITH_LIBZSTD=OFF" +cmake --build "$BuildDir-karchive" --config Debug --target install --parallel $NumCores +CheckCompileResult "karchive" + +# Build Kirigami +Clone "kirigami" "https://invent.kde.org/frameworks/kirigami.git" +Configure "kirigami" "-DBUILD_TESTING=OFF" +cmake --build "$BuildDir-kirigami" --config Debug --target install --parallel $NumCores +CheckCompileResult "kirigami" + +# Build Kirigami Add-ons +Clone "kirigami-addons" "https://invent.kde.org/libraries/kirigami-addons.git" +Configure "kirigami-addons" "-DBUILD_TESTING=OFF" +cmake --build "$BuildDir-kirigami-addons" --config Debug --target install --parallel $NumCores +CheckCompileResult "kirigami-addons" + +# Build Corrosion +Clone "corrosion" "https://github.com/corrosion-rs/corrosion.git" +Configure "corrosion" "-DCORROSION_BUILD_TESTS=OFF" +cmake --build "$BuildDir-corrosion" --config Debug --target install --parallel $NumCores +CheckCompileResult "corrosion" + +# Build QCoro +Clone "qcoro" "https://github.com/danvratil/qcoro.git" +Configure "qcoro" "-DBUILD_TESTING=OFF -DQCORO_WITH_QTWEBSOCKETS=OFF -DQCORO_BUILD_EXAMPLES=OFF" +cmake --build "$BuildDir-qcoro" --config Debug --target install --parallel $NumCores +CheckCompileResult "qcoro" + +# Build QtKeychain +Clone "qtkeychain" "https://github.com/redstrate/qtkeychain.git" +Configure "qtkeychain" "-DBUILD_TESTING=OFF -DBUILD_WITH_QT6=ON" +cmake --build "$BuildDir-qtkeychain" --config Debug --target install --parallel $NumCores +CheckCompileResult "qtkeychain" + +# Build unshield +Clone "unshield" "https://github.com/twogood/unshield.git" +Configure "unshield" "-DBUILD_TESTING=OFF" +cmake --build "$BuildDir-unshield" --config Debug --target install --parallel $NumCores +CheckCompileResult "unshield" + +# Build breeze icons +Clone "breeze-icons" "https://invent.kde.org/frameworks/breeze-icons.git" +Configure "breeze-icons" "-DICONS_LIBRARY=ON -DSKIP_INSTALL_ICONS=ON" +# Building it twice is intentional, the first time will always fail +cmake --build "$BuildDir-breeze-icons" --config Debug --target install --parallel $NumCores +cmake --build "$BuildDir-breeze-icons" --config Debug --target install --parallel $NumCores +CheckCompileResult "breeze-icons" \ No newline at end of file