From 1f09650721efb3c920453d28cabf65d6e04910a7 Mon Sep 17 00:00:00 2001 From: Henk Kalkwater Date: Tue, 23 Mar 2021 02:13:56 +0100 Subject: [PATCH] WIP: Experimenting with Lager for Redux like implementation --- CMakeLists.txt | 3 + cmake/ExternalProjectBackCompat.cmake | 10 +++ cmake/TargetLinkSys.cmake | 29 +++++++ core/CMakeLists.txt | 79 +++++++++++++++---- core/include/JellyfinQt/library/actions.h | 41 ++++++++++ core/include/JellyfinQt/library/reducer.h | 41 ++++++++++ core/include/JellyfinQt/library/store.h | 46 +++++++++++ core/include/JellyfinQt/network/actions.h | 39 +++++++++ .../JellyfinQt/network/networkrequest.h | 44 +++++++++++ core/include/JellyfinQt/network/reducer.h | 32 ++++++++ core/include/JellyfinQt/network/store.h | 38 +++++++++ .../JellyfinQt/network/store.h.autosave | 40 ++++++++++ core/src/library/reducer.cpp | 37 +++++++++ qtquick/CMakeLists.txt | 3 +- 14 files changed, 465 insertions(+), 17 deletions(-) create mode 100644 cmake/ExternalProjectBackCompat.cmake create mode 100644 cmake/TargetLinkSys.cmake create mode 100644 core/include/JellyfinQt/library/actions.h create mode 100644 core/include/JellyfinQt/library/reducer.h create mode 100644 core/include/JellyfinQt/library/store.h create mode 100644 core/include/JellyfinQt/network/actions.h create mode 100644 core/include/JellyfinQt/network/networkrequest.h create mode 100644 core/include/JellyfinQt/network/reducer.h create mode 100644 core/include/JellyfinQt/network/store.h create mode 100644 core/include/JellyfinQt/network/store.h.autosave create mode 100644 core/src/library/reducer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c75656..06c4ac1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,9 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") set(CMAKE_AUTOMOC ON) cmake_policy(SET CMP0048 NEW) set(CMAKE_CXX_STANDARD 17) +include(ExternalProjectBackCompat) +include(TargetLinkSys) + # Options option(PLATFORM_SAILFISHOS "Build SailfishOS version of application" OFF) diff --git a/cmake/ExternalProjectBackCompat.cmake b/cmake/ExternalProjectBackCompat.cmake new file mode 100644 index 0000000..9b5313f --- /dev/null +++ b/cmake/ExternalProjectBackCompat.cmake @@ -0,0 +1,10 @@ +# Provides backwards compatibility for FetchContent_MakeAvailable +if(${CMAKE_VERSION} VERSION_LESS 3.14) + macro(FetchContent_MakeAvailable NAME) + FetchContent_GetProperties(${NAME}) + if(NOT ${NAME}_POPULATED) + FetchContent_Populate(${NAME}) + add_subdirectory(${${NAME}_SOURCE_DIR} ${${NAME}_BINARY_DIR}) + endif() + endmacro() +endif() diff --git a/cmake/TargetLinkSys.cmake b/cmake/TargetLinkSys.cmake new file mode 100644 index 0000000..ecf94c9 --- /dev/null +++ b/cmake/TargetLinkSys.cmake @@ -0,0 +1,29 @@ +# From https://stackoverflow.com/questions/52135983/cmake-target-link-libraries-include-as-system-to-suppress-compiler-warnings +function(target_link_libraries_system target) + set(options PRIVATE PUBLIC INTERFACE) + cmake_parse_arguments(TLLS "${options}" "" "" ${ARGN}) + foreach(op ${options}) + if(TLLS_${op}) + set(scope ${op}) + endif() + endforeach(op) + set(libs ${TLLS_UNPARSED_ARGUMENTS}) + + foreach(lib ${libs}) + get_target_property(lib_include_dirs ${lib} INTERFACE_INCLUDE_DIRECTORIES) + if(lib_include_dirs) + if(scope) + target_include_directories(${target} SYSTEM ${scope} ${lib_include_dirs}) + else() + target_include_directories(${target} SYSTEM PRIVATE ${lib_include_dirs}) + endif() + else() + message("Warning: ${lib} doesn't set INTERFACE_INCLUDE_DIRECTORIES. No include_directories set.") + endif() + if(scope) + target_link_libraries(${target} ${scope} ${lib}) + else() + target_link_libraries(${target} ${lib}) + endif() + endforeach() +endfunction(target_link_libraries_system) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index a589af8..934495d 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -1,45 +1,72 @@ project(jellyfin-qt VERSION 0.1.0) -find_package(Qt5 5.6 COMPONENTS Multimedia Network Qml WebSockets REQUIRED) include(GNUInstallDirs) include(FetchContent) +################################################################################ +# Libraries # +################################################################################ + +find_package(Qt5 5.6 COMPONENTS Multimedia Network Qml WebSockets REQUIRED) + find_package(Boost REQUIRED) + +find_package(Zug) +if(NOT Zug_FOUND) + message(STATUS "Using zug from FetchContent") + set(zug_BUILD_TESTS OFF) + set(zug_BUILD_EXAMPLES OFF) + set(zug_BUILD_DOCS OFF) + FetchContent_Declare(zug + GIT_REPOSITORY https://github.com/arximboldi/zug + GIT_TAG 266cc7fcc01f546c4fd0dabf3a26c71ddc7f3e7d) + FetchContent_MakeAvailable(zug) +endif() + find_package(Immer) if(NOT Immer_FOUND) - message(STATUS "Using Immer from FetchContent") + message(STATUS "Immer not installed; Retrieving Immer with FetchContent") set(immer_BUILD_TESTS OFF) set(immer_BUILD_EXAMPLES OFF) set(immer_BUILD_DOCS OFF) set(immer_BUILD_EXTRAS OFF) - FetchContent_Declare(immer GIT_REPOSITORY https://github.com/arximboldi/immer GIT_TAG - 800ddb04e528a3e83e69e8021d7e872e7c34cbcd) + FetchContent_Declare(immer + GIT_REPOSITORY https://github.com/arximboldi/immer + GIT_TAG 800ddb04e528a3e83e69e8021d7e872e7c34cbcd) FetchContent_MakeAvailable(immer) endif() find_package(Lager) if(NOT Lager_FOUND) - message(STATUS "Using lager from FetchContent") + message(STATUS "Lager not installed; Retrieving lager with FetchContent") set(lager_BUILD_TESTS OFF) set(lager_BUILD_EXAMPLES OFF) set(lager_BUILD_DOCS OFF) set(lager_EMBED_RESOURCES_PATH OFF) - FetchContent_Declare(lager GIT_REPOSITORY https://github.com/arximboldi/lager GIT_TAG - 71eca6b0ebbccf3e0e54324b6967f047e49ba92d) + FetchContent_Declare(lager + GIT_REPOSITORY https://github.com/arximboldi/lager + GIT_TAG 71eca6b0ebbccf3e0e54324b6967f047e49ba92d) FetchContent_MakeAvailable(lager) endif() find_package(cereal) if(NOT cereal_FOUND) set(JUST_INSTALL_CEREAL ON) - FetchContent_Declare(cereal GIT_REPOSITORY https://github.com/USCiLab/cereal GIT_TAG v1.3.0) + FetchContent_Declare(cereal + GIT_REPOSITORY https://github.com/USCiLab/cereal + GIT_TAG v1.3.0) FetchContent_MakeAvailable(cereal) endif() +################################################################################ +# TARGETS # +################################################################################ +# Includes the automatically generated files. include(GeneratedSources.cmake) set(jellyfin-qt_SOURCES # src/DTO/dto.cpp + src/library/reducer.cpp src/model/item.cpp src/support/jsonconv.cpp src/support/loader.cpp @@ -58,6 +85,13 @@ list(APPEND jellyfin-qt_SOURCES ${openapi_SOURCES}) set(jellyfin-qt_HEADERS # include/JellyfinQt/DTO/dto.h + include/JellyfinQt/network/actions.h + include/JellyfinQt/network/networkrequest.h + include/JellyfinQt/network/reducer.h + include/JellyfinQt/network/store.h + include/JellyfinQt/library/actions.h + include/JellyfinQt/library/reducer.h + include/JellyfinQt/library/store.h include/JellyfinQt/model/item.h include/JellyfinQt/support/jsonconv.h include/JellyfinQt/support/loader.h @@ -72,25 +106,38 @@ set(jellyfin-qt_HEADERS include/JellyfinQt/serverdiscoverymodel.h include/JellyfinQt/websocket.h) -list(APPEND jellyfin-qt_SOURCES ${openapi_HEADERS}) +list(APPEND jellyfin-qt_HEADERS ${openapi_HEADERS}) add_definitions(-DSAILFIN_VERSION=\"${SAILFIN_VERSION}\") if (PLATFORM_SAILFISHOS) add_definitions(-DPLATFORM_SAILFISHOS=1) endif() -add_library(jellyfin-qt ${jellyfin-qt_SOURCES} ${jellyfin-qt_HEADERS}) + +add_library(JellyfinQt ${jellyfin-qt_SOURCES} ${jellyfin-qt_HEADERS}) + if(${CMAKE_VERSION} VERSION_GREATER "3.16.0") - target_precompile_headers(jellyfin-qt PRIVATE ${jellyfin-qt_HEADERS}) + target_precompile_headers(JellyfinQt PRIVATE ${jellyfin-qt_HEADERS}) endif() -target_include_directories(jellyfin-qt + +target_include_directories(JellyfinQt PUBLIC "include" "generated/include" ) -target_link_libraries(jellyfin-qt PUBLIC Qt5::Core Qt5::Multimedia Qt5::Network Qt5::Qml Qt5::WebSockets) -set_target_properties(jellyfin-qt PROPERTIES CXX_VISIBILITY_PRESET default) -install(TARGETS jellyfin-qt +target_link_libraries(JellyfinQt + PUBLIC Qt5::Core Qt5::Multimedia Qt5::Network Qt5::Qml Qt5::WebSockets) + +target_link_libraries_system(JellyfinQt + PUBLIC + cereal + zug + immer + lager) + +set_target_properties(JellyfinQt PROPERTIES CXX_VISIBILITY_PRESET default) +install(TARGETS JellyfinQt LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") -export(TARGETS jellyfin-qt FILE JellyfinQtConfig.cmake) +install(TARGETS JellyfinQt EXPORT JellyfinQtTargets) +# export(TARGETS jellyfin-qt lager immer cereal FILE JellyfinQtConfig.cmake) diff --git a/core/include/JellyfinQt/library/actions.h b/core/include/JellyfinQt/library/actions.h new file mode 100644 index 0000000..f0d9fac --- /dev/null +++ b/core/include/JellyfinQt/library/actions.h @@ -0,0 +1,41 @@ +/* +Sailfin: a Jellyfin client written using Qt +Copyright (C) 2021 Chris Josten + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef JELLYFIN_LIBRARY_ACTIONS_H +#define JELLYFIN_LIBRARY_ACTIONS_H + +#include +#include + +namespace Jellyfin { +namespace Library { + +struct fetchItem { + std::string itemId; +}; + +struct fetchItemChildren { + std::string parentItemId; +}; + +using Action = std::variant; + +} // NS Library +} // NS Jellyfin + +#endif //JELLYFIN_LIBRARY_ACTIONS_H diff --git a/core/include/JellyfinQt/library/reducer.h b/core/include/JellyfinQt/library/reducer.h new file mode 100644 index 0000000..65f0bea --- /dev/null +++ b/core/include/JellyfinQt/library/reducer.h @@ -0,0 +1,41 @@ +/* +Sailfin: a Jellyfin client written using Qt +Copyright (C) 2021 Chris Josten + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef JELLYFIN_LIBRARY_REDUCER_H +#define JELLYFIN_LIBRARY_REDUCER_H + +#include + +#include +#include + + +#include "actions.h" +#include "store.h" + +namespace Jellyfin { +namespace Library { + +using ItemListResult = std::pair>; + +ItemListResult update(ItemListStore store, Action action); + +} +} + +#endif // JELLYFIN_LIBRARY_REDUCER_H diff --git a/core/include/JellyfinQt/library/store.h b/core/include/JellyfinQt/library/store.h new file mode 100644 index 0000000..d9e24c6 --- /dev/null +++ b/core/include/JellyfinQt/library/store.h @@ -0,0 +1,46 @@ +/* + * Sailfin: a Jellyfin client written using Qt + * Copyright (C) 2021 Chris Josten and the Sailfin Contributors. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef JELLYFIN_LIBRARY_STORE_H +#define JELLYFIN_LIBRARY_STORE_H + +#include + +#include + +#include "../DTO/baseitemdto.h" + +namespace Jellyfin { +namespace Library { + +/** + * @brief Stores information about one Jellyfin Item. + */ +struct ItemStore { + std::string id; + std::string name; +}; + +struct ItemListStore { + immer::map itemList; +}; + +} +} + +#endif // JELLYFIN_LIBRARY_STORE_H diff --git a/core/include/JellyfinQt/network/actions.h b/core/include/JellyfinQt/network/actions.h new file mode 100644 index 0000000..472b976 --- /dev/null +++ b/core/include/JellyfinQt/network/actions.h @@ -0,0 +1,39 @@ +/* + * Sailfin: a Jellyfin client written using Qt + * Copyright (C) 2021 Chris Josten and the Sailfin Contributors. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef JELLYFIN_NETWORK_ACTIONS_H +#define JELLYFIN_NETWORK_ACTIONS_H + +#include + +#include "reducer.h" + +namespace Jellyfin { +namespace Network { + +struct makeRequest { + +}; + +using Action = std::variant; + +} // NS Network +} // NS Jellyfin + +#endif // JELLYFIN_NETWORK_ACTIONS_H diff --git a/core/include/JellyfinQt/network/networkrequest.h b/core/include/JellyfinQt/network/networkrequest.h new file mode 100644 index 0000000..4059189 --- /dev/null +++ b/core/include/JellyfinQt/network/networkrequest.h @@ -0,0 +1,44 @@ +/* + * Sailfin: a Jellyfin client written using Qt + * Copyright (C) 2021 Chris Josten and the Sailfin Contributors. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef JELLYFIN_NETWORK_NETWORKREQUEST_H +#define JELLYFIN_NETWORK_NETWORKREQUEST_H + +#include + +namespace Jellyfin { +namespace Network { + +enum HttpMethod { + GET, + PUT, + POST, + DELETE +}; + +struct NetworkRequest { + std::string url; + HttpMethod method; +}; + + +} // NS Network +} // NS Jellyfin + +#endif // JELLYFIN_NETWORK_NETWORKREQUEST_H diff --git a/core/include/JellyfinQt/network/reducer.h b/core/include/JellyfinQt/network/reducer.h new file mode 100644 index 0000000..3557ca4 --- /dev/null +++ b/core/include/JellyfinQt/network/reducer.h @@ -0,0 +1,32 @@ +/* + * Sailfin: a Jellyfin client written using Qt + * Copyright (C) 2021 Chris Josten and the Sailfin Contributors. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef JELLYFIN_NETWORK_REDUCER_H +#define JELLYFIN_NETWORK_REDUCER_H + +namespace Jellyfin { +namespace Network { + + + + +} // NS Network +} // NS Jellyfin + +#endif // JELLYFIN_NETWORK_REDUCER_H diff --git a/core/include/JellyfinQt/network/store.h b/core/include/JellyfinQt/network/store.h new file mode 100644 index 0000000..8f323c9 --- /dev/null +++ b/core/include/JellyfinQt/network/store.h @@ -0,0 +1,38 @@ +/* + * Sailfin: a Jellyfin client written using Qt + * Copyright (C) 2021 Chris Josten and the Sailfin Contributors. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef JELLYFIN_NETWORK_STORE_H +#define JELLYFIN_NETWORK_STORE_H + +#include + +#include "networkrequest.h" + +namespace Jellyfin { +namespace Network { + +struct NetworkRequestStore { + +}; + + +} // NS Network +} // NS Jellyfin + +#endif // JELLYFIN_NETWORK_STORE_H diff --git a/core/include/JellyfinQt/network/store.h.autosave b/core/include/JellyfinQt/network/store.h.autosave new file mode 100644 index 0000000..4d3e876 --- /dev/null +++ b/core/include/JellyfinQt/network/store.h.autosave @@ -0,0 +1,40 @@ +/* + * Sailfin: a Jellyfin client written using Qt + * Copyright (C) 2021 Chris Josten and the Sailfin Contributors. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef JELLYFIN_NETWORK_STORE_H +#define JELLYFIN_NETWORK_STORE_H + +#include + +#include + +#include "networkrequest.h" + +namespace Jellyfin { +namespace Network { + +struct NetworkRequestStore { + immer::vector +}; + + +} // NS Network +} // NS Jellyfin + +#endif // JELLYFIN_NETWORK_STORE_H diff --git a/core/src/library/reducer.cpp b/core/src/library/reducer.cpp new file mode 100644 index 0000000..d119a28 --- /dev/null +++ b/core/src/library/reducer.cpp @@ -0,0 +1,37 @@ +/* + * Sailfin: a Jellyfin client written using Qt + * Copyright (C) 2021 Chris Josten and the Sailfin Contributors. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include + +namespace Jellyfin { +namespace Library { + +ItemListResult update(ItemListStore store, Action action) { + return std::visit( + lager::visitor { + [&](const fetchItem &a) -> ItemListResult { + return {store, lager::noop}; + }, + [&](const fetchItemChildren &a) -> ItemListResult { + return {store, lager::noop}; + }, + }, action); +} + +} // NS Library +} // NS Jellyfin diff --git a/qtquick/CMakeLists.txt b/qtquick/CMakeLists.txt index 34dbf06..c681fd0 100644 --- a/qtquick/CMakeLists.txt +++ b/qtquick/CMakeLists.txt @@ -4,12 +4,13 @@ set(sailfin_SOURCES qt5_add_resources(sailfin_RESOURCES qml.qrc) add_executable(sailfin ${sailfin_SOURCES} ${sailfin_RESOURCES}) -target_link_libraries(sailfin PUBLIC Qt5::Gui Qt5::Qml Qt5::Quick jellyfin-qt) +target_link_libraries(sailfin PRIVATE Qt5::Gui Qt5::Qml Qt5::Quick JellyfinQt) install(TARGETS sailfin RUNTIME DESTINATION bin ) + install(DIRECTORY translations DESTINATION share/harbour-sailfin FILES_MATCHING PATTERN "*.qm"