function(kazv_add_qml_files)
  set(options "")
  set(oneValueArgs BASE_DIRECTORY)
  set(multiValueArgs SOURCES)
  cmake_parse_arguments(PARSE_ARGV 0 kazv_add_qml_files "${options}" "${oneValueArgs}" "${multiValueArgs}")

  set(target "${kazv_add_qml_files_UNPARSED_ARGUMENTS}")
  set(allSources)
  foreach(source ${kazv_add_qml_files_SOURCES})
    message(STATUS "Adding source: ${kazv_add_qml_files_BASE_DIRECTORY} / ${source}")
    set_source_files_properties(
      "${kazv_add_qml_files_BASE_DIRECTORY}/${source}"
      PROPERTIES
      QT_RESOURCE_ALIAS "${source}"
    )
    list(APPEND allSources "${kazv_add_qml_files_BASE_DIRECTORY}/${source}")
  endforeach()
  qt_target_qml_sources(
    "${target}"
    QML_FILES ${allSources}
  )
endfunction()


if(WIN32)
  set(KAZV_IS_WINDOWS 1)
else()
  set(KAZV_IS_WINDOWS 0)
endif()
if(ANDROID)
  set(KAZV_IS_ANDROID 1)
else()
  set(KAZV_IS_ANDROID 0)
endif()
configure_file(kazv-version.cpp.in kazv-version.cpp)
configure_file(kazv-platform.hpp.in kazv-platform.hpp)
configure_file(kazv-defs.hpp.in kazv-defs.hpp)

set(kazvqmlmodule_SRCS
  qt-job-handler.cpp
  qt-job.cpp
  ${CMAKE_CURRENT_BINARY_DIR}/kazv-version.cpp
  constants.cpp
  matrix-sdk.cpp
  matrix-session.cpp
  matrix-session-controller.cpp
  sso-login-process.cpp
  kazv-session-lock-guard.cpp
  matrix-room.cpp
  matrix-room-list.cpp
  matrix-room-timeline.cpp
  matrix-room-pinned-events-timeline.cpp
  matrix-room-member.cpp
  matrix-room-member-list-model.cpp
  matrix-room-state.cpp
  matrix-event-reader.cpp
  matrix-event-reader-list-model.cpp
  matrix-event-reaction-list-model.cpp
  matrix-event-reaction.cpp
  matrix-event.cpp
  matrix-event-list.cpp
  matrix-link.cpp
  meta-types.cpp
  l10n-provider.cpp
  qt-rand-adapter.cpp
  helper.cpp
  matrix-promise.cpp
  kazv-util.cpp
  matrix-sticker-pack.cpp
  matrix-sticker.cpp
  matrix-sticker-pack-list.cpp
  matrix-sticker-pack-source.cpp
  matrix-user-given-attrs-map.cpp
  matrix-verification.cpp
  matrix-verification-list.cpp
  kazv-abstract-list-model.cpp
  qt-promise-handler.cpp

  device-mgmt/matrix-device.cpp
  device-mgmt/matrix-device-list.cpp

  kazv-config.cpp
  kazv-path-config.cpp
  kazv-io-manager.cpp
  kazv-io-job.cpp
  kazv-file.cpp
  upload-job-model.cpp
  kazv-markdown.cpp

  kazv-clipboard.cpp
  db-store.cpp
)

ecm_qt_declare_logging_category(kazvqmlmodule_SRCS
  HEADER kazv-log.hpp
  IDENTIFIER kazvLog
  CATEGORY_NAME moe.kazv.mxc.kazv
)

qt_add_qml_module(kazvqmlmodule
  STATIC
  URI moe.kazv.mxc.kazv
  VERSION 0.0
  SOURCES ${kazvqmlmodule_SRCS}
)

kconfig_target_kcfg_file(kazvqmlmodule
  FILE kazv-settings.kcfg
  CLASS_NAME KazvSettings
  MUTATORS
  GENERATE_MOC
)
kconfig_target_kcfg_file(kazvqmlmodule
  FILE kazv-sessions-settings.kcfg
  CLASS_NAME KazvSessionsSettings
  MUTATORS
  GENERATE_MOC
)

target_link_libraries(kazvqmlmodule PUBLIC
  libkazv::kazvall
  Qt${QT_MAJOR_VERSION}::Core
  Qt${QT_MAJOR_VERSION}::Network
  Threads::Threads
  Qt${QT_MAJOR_VERSION}::Gui
  Qt${QT_MAJOR_VERSION}::Qml
  Qt${QT_MAJOR_VERSION}::Quick
  Qt${QT_MAJOR_VERSION}::QuickControls2
  Qt${QT_MAJOR_VERSION}::Svg
  Qt${QT_MAJOR_VERSION}::Concurrent
  Qt${QT_MAJOR_VERSION}::Widgets
  Qt${QT_MAJOR_VERSION}::Sql
  Qt${QT_MAJOR_VERSION}::HttpServer
  KF${KF_MAJOR_VERSION}::ConfigCore
  KF${KF_MAJOR_VERSION}::ConfigGui
  KF${KF_MAJOR_VERSION}::Notifications
  KF${KF_MAJOR_VERSION}::CoreAddons
  QCoro::Core
  ${CMARK_TARGET_NAME}
)
if(ANDROID)
  target_link_libraries(kazvqmlmodule PUBLIC
    KF${KF_MAJOR_VERSION}::Kirigami
    OpenSSL::SSL
  )
endif()

target_include_directories(kazvqmlmodule PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(kazvqmlmodule PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/device-mgmt)

qt_add_qml_module(kazvshortcutsqmlmodule
  STATIC
  URI moe.kazv.mxc.kazvshortcuts
  VERSION 0.0
  SOURCES
  shortcuts/shortcut-util.cpp
)

target_link_libraries(kazvshortcutsqmlmodule PUBLIC
  libkazv::kazvall
  Qt${QT_MAJOR_VERSION}::Core
  Qt${QT_MAJOR_VERSION}::Gui
  Qt${QT_MAJOR_VERSION}::Qml
)

target_include_directories(kazvshortcutsqmlmodule
  PUBLIC
  ${CMAKE_CURRENT_SOURCE_DIR}/shortcuts
)

add_library(kazvprivlib INTERFACE)
target_link_libraries(kazvprivlib
  INTERFACE
  kazvqmlmodule
  kazvqmlmoduleplugin
  kazvshortcutsqmlmodule
  kazvshortcutsqmlmoduleplugin
)

qt_add_qml_module(kazvqmlqmlmodule
  STATIC
  URI moe.kazv.mxc.kazvqml
  VERSION 0.0
)
kazv_add_qml_files(kazvqmlqmlmodule
  BASE_DIRECTORY contents/ui
  SOURCES
  Main.qml
  About.qml
  PageManager.qml
  LoginPage.qml
  LoginFlows.qml
  MainPage.qml
  TabView.qml
  Tab.qml
  ClosableScrollablePage.qml
  ClosableScrollableOverlay.qml
  SelfDestroyableOverlaySheet.qml
  FocusRingBackground.qml
  RoomListView.qml
  RoomListViewItemDelegate.qml
  RoomPage.qml
  RoomPinnedEventsPage.qml
  RoomTimelineView.qml
  SendMessageBox.qml
  EventView.qml
  EventViewWrapper.qml
  EventViewCompact.qml
  EventSourceView.qml
  EventHistoryView.qml
  EventReactions.qml
  Bubble.qml
  MediaFileMenu.qml
  KazvIOMenu.qml
  ConfirmUploadPopup.qml
  StickerPicker.qml
  AddStickerPopup.qml
  StickerPackNameProvider.qml
  ConfirmationOverlay.qml
  AcceptRejectNoopOverlay.qml
  VerificationsPage.qml
  SasCodes.qml
  event-types/Simple.qml
  event-types/Text.qml
  event-types/Emote.qml
  event-types/Notice.qml
  event-types/State.qml
  event-types/TextTemplate.qml
  event-types/Image.qml
  event-types/File.qml
  event-types/Video.qml
  event-types/Audio.qml
  event-types/MediaBubble.qml
  event-types/Redacted.qml
  event-types/Reaction.qml
  event-types/Fallback.qml
  TypingIndicator.qml
  EventReadIndicator.qml
  SelectableText.qml
  ReactToEventPopup.qml
  FileHandler.qml
  media/PlayButton.qml

  ActionSettingsPage.qml
  CreateRoomPage.qml
  JoinRoomPage.qml
  RoomMemberListView.qml
  RoomMemberListViewItemDelegate.qml
  UserNameProvider.qml
  RoomNameProvider.qml
  Completion.qml

  AsyncHandler.qml
  UploadFileHelper.qml
  SettingsPage.qml
  settings/ProfileSettings.qml
  settings/CacheSettings.qml
  settings/SecuritySettings.qml

  room-settings/RoomSettingsPage.qml
  room-settings/RoomTagHandler.qml
  room-settings/RoomMemberListPage.qml
  room-settings/RoomInvitePage.qml
  room-settings/RoomStickerPacksPage.qml
  room-settings/RoomStickerPackItemDelegate.qml
  room-settings/RoomStatePage.qml

  device-mgmt/Device.qml
  device-mgmt/DeviceList.qml

  UserPage.qml
  KazvAction.qml

  shortcuts/ActionCollection.qml
  shortcuts/ActionItem.qml
  shortcuts/ActionSettings.qml
  shortcuts/ShortcutInput.qml

  actions/GlobalDrawerActions.qml
  actions/RoomPageActions.qml
  actions/BubbleActions.qml
  actions/RoomListActions.qml
  actions/DialogActions.qml
  actions/SettingsActions.qml
  actions/AllActions.qml

  MessageNotification.qml
  Notifier.qml
  NotificationAction.qml
  AvatarAdapter.qml
  ImageAdapter.qml
  FileDialogAdapter.qml
  FolderDialogAdapter.qml
  ScrollablePageAdapter.qml

  emoji/Activities.qml
  emoji/Flags.qml
  emoji/Objects.qml
  emoji/SmileysAndEmotion.qml
  emoji/TravelAndPlaces.qml
  emoji/AnimalsAndNature.qml
  emoji/FoodAndDrink.qml
  emoji/PeopleAndBody.qml
  emoji/Symbols.qml

)
kazv_add_qml_files(kazvqmlqmlmodule
  BASE_DIRECTORY js
  SOURCES
  l10n.js
  global-this.js
  matrix-helpers.js
  sas-emoji-defs.js
)

kazv_add_qml_files(kazvqmlqmlmodule
  BASE_DIRECTORY js/transformed-libs
  SOURCES
  fluent-bundle.js
  fluent-sequence.js
  fluent-langneg.js
  bundled-deps.js
)

target_link_libraries(kazvqmlqmlmodule PUBLIC kazvprivlib)

set(kazv_SRCS
  main.cpp
  l10n/translations.qrc
)

add_executable(kazv ${kazv_SRCS})

target_link_libraries(kazv
  PRIVATE
  kazvqmlqmlmodule
  kazvqmlqmlmoduleplugin
  kazvprivlib
)
if(kazv_LINK_BREEZE_ICONS)
  target_link_libraries(kazv PRIVATE KF${KF_MAJOR_VERSION}::BreezeIcons)
endif()
if(ANDROID)
  message(STATUS "Collecting icons for apk deployment")
  execute_process(
    COMMAND
    ${PERL_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/scan-icons
    RESULT_VARIABLE KAZV_SCAN_ICONS_RESULT
    OUTPUT_VARIABLE KAZV_FOUND_ICONS
    COMMAND_ERROR_IS_FATAL ANY
  )
  kirigami_package_breeze_icons(ICONS ${KAZV_FOUND_ICONS})
endif()

set(kazv_INSTALL_ARGS ${KF_INSTALL_TARGETS_DEFAULT_ARGS})
if(NOT kazv_INSTALL_ARGS)
  set(kazv_INSTALL_ARGS ${KF${KF_MAJOR_VERSION}_INSTALL_TARGETS_DEFAULT_ARGS})
endif()
install(TARGETS kazv ${kazv_INSTALL_ARGS})

if(ANDROID)
  ecm_add_android_apk(kazv ANDROID_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android)
endif()

if(kazv_BUILD_TESTS)
  add_subdirectory(tests)
endif()
