diff --git a/CMakeLists.txt b/CMakeLists.txt index be0878d..494a72b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,64 +19,27 @@ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeR project(Projecteur LANGUAGES CXX) -add_compile_options(-Wall -Wextra -Werror) +add_compile_options(-Wall -Wextra) #set(CMAKE_CXX_CLANG_TIDY clang-tidy-12) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") include(GitVersion) include(Translation) -set(QtVersionOptions "Auto" "5" "6") -set(PROJECTEUR_QT_VERSION "Auto" CACHE STRING "Choose the Qt version") -set_property(CACHE PROJECTEUR_QT_VERSION PROPERTY STRINGS ${QtVersionOptions}) - -list(FIND QtVersionOptions ${PROJECTEUR_QT_VERSION} index) -if(index EQUAL -1) - message(FATAL_ERROR "PROJECTEUR_QT_VERSION must be one of ${QtVersionOptions}") -endif() - -if ("${PROJECTEUR_QT_VERSION}" STREQUAL "Auto") - find_package(QT NAMES Qt6 Qt5 RCOMPONENTS Core REQUIRED) -else() - set(QT_VERSION_MAJOR ${PROJECTEUR_QT_VERSION}) -endif() - -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) -set(QT_PACKAGE_NAME Qt${QT_VERSION_MAJOR}) +find_package(Qt6 REQUIRED COMPONENTS Core Gui Quick Widgets) message(STATUS "Using Qt version: ${Qt${QT_VERSION_MAJOR}_VERSION}") -if(${QT_PACKAGE_NAME}_VERSION VERSION_LESS "6.0") - set(CMAKE_CXX_STANDARD 14) -else() - set(CMAKE_CXX_STANDARD 17) -endif() - +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) - set(CMAKE_AUTOMOC ON) -find_package(${QT_PACKAGE_NAME} 5.7 REQUIRED COMPONENTS Core Gui Quick Widgets) +set(HAS_Qt_X11Extras 0) -if(${QT_PACKAGE_NAME}_VERSION VERSION_LESS "6.0") - find_package(${QT_PACKAGE_NAME} QUIET COMPONENTS X11Extras) - set(HAS_Qt_X11Extras ${${QT_PACKAGE_NAME}_FOUND}) -else() - set(HAS_Qt_X11Extras 0) -endif() - -find_package(${QT_PACKAGE_NAME} QUIET COMPONENTS DBus) -set(HAS_Qt_DBus ${${QT_PACKAGE_NAME}_FOUND}) -find_package(${QT_PACKAGE_NAME} QUIET COMPONENTS QuickCompiler) -set(HAS_Qt_QuickCompiler ${${QT_PACKAGE_NAME}_FOUND}) - -# Qt 5.8 seems to have issues with the way Projecteur shows the full screen overlay window, -# let's warn the user about it. -if(Qt5_VERSION VERSION_EQUAL "5.8" - OR (Qt5_VERSION VERSION_GREATER "5.8" AND Qt5_VERSION VERSION_LESS "5.9")) - message(WARNING "There are known issues when using Projecteur with Qt Version 5.8, " - "please use a different Qt Version.") -endif() +find_package(Qt6DBus QUIET) +set(HAS_Qt_DBus Qt6DBus_FOUND}) +find_package(Qt6QuickCompiler QUIET) +set(HAS_Qt_QuickCompiler Qt6QuickCompiler_FOUND}) if (HAS_Qt_QuickCompiler) # Off by default, since this ties the application strictly to the Qt version @@ -94,18 +57,10 @@ if (USE_QTQUICK_COMPILER) set_property(SOURCE "${resfile}" PROPERTY SKIP_AUTOMOC ON) endforeach() else() - if(${QT_PACKAGE_NAME}_VERSION VERSION_LESS "6.0") - qt5_add_resources(RESOURCES qml/qml.qrc) - else() - qt6_add_resources(RESOURCES qml/qml-qt6.qrc) - endif() + qt6_add_resources(RESOURCES qml/qml-qt6.qrc) endif() -if(${QT_PACKAGE_NAME}_VERSION VERSION_LESS "6.0") - qt5_add_resources(RESOURCES resources.qrc) -else() - qt6_add_resources(RESOURCES resources.qrc) -endif() +qt6_add_resources(RESOURCES resources.qrc) add_executable(projecteur src/main.cc src/enum-helper.h @@ -140,20 +95,11 @@ add_executable(projecteur target_include_directories(projecteur PRIVATE src) target_link_libraries(projecteur - PRIVATE ${QT_PACKAGE_NAME}::Core ${QT_PACKAGE_NAME}::Quick ${QT_PACKAGE_NAME}::Widgets + PRIVATE Qt6::Core Qt6::Quick Qt6::Widgets ) -if(HAS_Qt_X11Extras) - if(${QT_PACKAGE_NAME}_VERSION VERSION_LESS "6.0") - target_link_libraries(projecteur PRIVATE ${QT_PACKAGE_NAME}::X11Extras) - endif() - target_compile_definitions(projecteur PRIVATE HAS_Qt_X11Extras=1) -else() - message(STATUS "Compiling without Qt5::X11Extras.") -endif() - if(HAS_Qt_DBus) - target_link_libraries(projecteur PRIVATE ${QT_PACKAGE_NAME}::DBus) + target_link_libraries(projecteur PRIVATE Qt6::DBus) target_compile_definitions(projecteur PRIVATE HAS_Qt_DBus=1) else() message(STATUS "Compiling without Qt5::DBus.") diff --git a/cmake/modules/Translation.cmake b/cmake/modules/Translation.cmake index 5eccc7c..c9217a6 100644 --- a/cmake/modules/Translation.cmake +++ b/cmake/modules/Translation.cmake @@ -1,29 +1,29 @@ -find_package(Qt5 REQUIRED COMPONENTS Core) +find_package(Qt6 REQUIRED COMPONENTS Core) # Extract the qmake executable location -get_target_property(Qt5_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION) +get_target_property(Qt6_QMAKE_EXECUTABLE Qt6::qmake IMPORTED_LOCATION) # Find Qts own translations dir (containing qt_*.qm, qtbase_*.qm ...) if(NOT QT_TRANSLATIONS_DIR) - # Ask Qt5 where to put the translations - execute_process(COMMAND ${Qt5_QMAKE_EXECUTABLE} -query QT_INSTALL_TRANSLATIONS + # Ask Qt6 where to put the translations + execute_process(COMMAND ${Qt6_QMAKE_EXECUTABLE} -query QT_INSTALL_TRANSLATIONS OUTPUT_VARIABLE qt_translations_dir OUTPUT_STRIP_TRAILING_WHITESPACE) # For windows systems: replace \ with / in directory path file(TO_CMAKE_PATH "${qt_translations_dir}" qt_translations_dir) set(QT_TRANSLATIONS_DIR ${qt_translations_dir} CACHE PATH "The location of the Qt translations" FORCE) endif() -find_package(Qt5LinguistTools QUIET) -if(NOT Qt5_LRELEASE_EXECUTABLE) - execute_process(COMMAND ${Qt5_QMAKE_EXECUTABLE} -query QT_INSTALL_BINS +find_package(Qt6LinguistTools QUIET) +if(NOT Qt6_LRELEASE_EXECUTABLE) + execute_process(COMMAND ${Qt6_QMAKE_EXECUTABLE} -query QT_INSTALL_BINS OUTPUT_VARIABLE _qt_bin_dir OUTPUT_STRIP_TRAILING_WHITESPACE) # For windows systems: replace \ with / in directory path file(TO_CMAKE_PATH "${_qt_bin_dir}" _qt_bin_dir) - set(Qt5_LRELEASE_EXECUTABLE ${_qt_bin_dir}/lrelease) - set(Qt5_LCONVERT_EXECUTABLE ${_qt_bin_dir}/lconvert) - set(Qt5_LUPDATE_EXECUTABLE ${_qt_bin_dir}/lupdate) + set(Qt6_LRELEASE_EXECUTABLE ${_qt_bin_dir}/lrelease) + set(Qt6_LCONVERT_EXECUTABLE ${_qt_bin_dir}/lconvert) + set(Qt6_LUPDATE_EXECUTABLE ${_qt_bin_dir}/lupdate) else() - get_target_property(Qt5_LCONVERT_EXECUTABLE Qt5::lconvert IMPORTED_LOCATION) + get_target_property(Qt6_LCONVERT_EXECUTABLE Qt6::lconvert IMPORTED_LOCATION) endif() # Helper function, takes the .qm file to be generated and a variable list of .ts files @@ -37,7 +37,7 @@ function(add_qm_translation_file _qm_file) SET(tsfiles_blank_sep "${tsfiles_blank_sep} ${tsfile}") endforeach() add_custom_command(OUTPUT ${_qm_file} - COMMAND ${Qt5_LRELEASE_EXECUTABLE} + COMMAND ${Qt6_LRELEASE_EXECUTABLE} ARGS ${_ts_files} -qm ${_qm_file} DEPENDS ${_ts_files} VERBATIM COMMENT "Executing: lrelease -silent ${tsfiles_blank_sep} -qm ${_qm_file}" @@ -67,10 +67,10 @@ function(add_combined_qm_translation_file _combined_qm_file) endforeach() list(REMOVE_DUPLICATES _single_qm_files) add_custom_command(OUTPUT ${_combined_qm_file} - COMMAND ${Qt5_LCONVERT_EXECUTABLE} + COMMAND ${Qt6_LCONVERT_EXECUTABLE} ARGS -o ${_combined_qm_file} ${_single_qm_files} DEPENDS ${_single_qm_files} VERBATIM - COMMENT "Executing: ${Qt5_LCONVERT_EXECUTABLE} -o ${_combined_qm_file} ${_single_qm_files}" + COMMENT "Executing: ${Qt6_LCONVERT_EXECUTABLE} -o ${_combined_qm_file} ${_single_qm_files}" ) endfunction() @@ -94,7 +94,7 @@ function(add_translation_update_task _prefix _input_dirs _output_dir _languages) set_target_properties(${_ts_files_tgt} PROPERTIES FOLDER "translation") set_target_properties(${_ts_files_tgt} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD 1) add_custom_command(TARGET ${_ts_files_tgt} PRE_BUILD - COMMAND ${Qt5_LUPDATE_EXECUTABLE} + COMMAND ${Qt6_LUPDATE_EXECUTABLE} ARGS ${_input_dirs} ARGS -locations relative ARGS -ts diff --git a/src/actiondelegate.cc b/src/actiondelegate.cc index dea30b6..2db3d16 100644 --- a/src/actiondelegate.cc +++ b/src/actiondelegate.cc @@ -315,12 +315,12 @@ void ActionTypeDelegate::paint(QPainter* painter, const QStyleOptionViewItem& op const auto symbol = [&item]() -> QChar { switch(item.action->type()) { - case Action::Type::KeySequence: return QChar(Font::Icon::keyboard_4); - case Action::Type::CyclePresets: return QChar(Font::Icon::connection_8); - case Action::Type::ToggleSpotlight: return QChar(Font::Icon::power_on_off_11); - case Action::Type::ScrollHorizontal: return QChar(Font::Icon::cursor_21_rotated); - case Action::Type::ScrollVertical: return QChar(Font::Icon::cursor_21); - case Action::Type::VolumeControl: return QChar(Font::Icon::audio_6); + case Action::Type::KeySequence: return QChar(static_cast(Font::Icon::keyboard_4)); + case Action::Type::CyclePresets: return QChar(static_cast(Font::Icon::connection_8)); + case Action::Type::ToggleSpotlight: return QChar(static_cast(Font::Icon::power_on_off_11)); + case Action::Type::ScrollHorizontal: return QChar(static_cast(Font::Icon::cursor_21_rotated)); + case Action::Type::ScrollVertical: return QChar(static_cast(Font::Icon::cursor_21)); + case Action::Type::VolumeControl: return QChar(static_cast(Font::Icon::audio_6)); } return QChar(0); }(); @@ -352,12 +352,12 @@ void ActionTypeDelegate::actionContextMenu(QWidget* parent, InputMapConfigModel* }; static std::vector items { - {Action::Type::KeySequence, QChar(Font::Icon::keyboard_4), tr("Key Sequence"), false}, - {Action::Type::CyclePresets, QChar(Font::Icon::connection_8), tr("Cycle Presets"), false}, - {Action::Type::ToggleSpotlight, QChar(Font::Icon::power_on_off_11), tr("Toggle Spotlight"), false}, - {Action::Type::ScrollHorizontal, QChar(Font::Icon::cursor_21_rotated), tr("Scroll Horizontal"), true}, - {Action::Type::ScrollVertical, QChar(Font::Icon::cursor_21), tr("Scroll Vertical"), true}, - {Action::Type::VolumeControl, QChar(Font::Icon::audio_6), tr("Volume Control"), true}, + {Action::Type::KeySequence, QChar(static_cast(Font::Icon::keyboard_4)), tr("Key Sequence"), false}, + {Action::Type::CyclePresets, QChar(static_cast(Font::Icon::connection_8)), tr("Cycle Presets"), false}, + {Action::Type::ToggleSpotlight, QChar(static_cast(Font::Icon::power_on_off_11)), tr("Toggle Spotlight"), false}, + {Action::Type::ScrollHorizontal, QChar(static_cast(Font::Icon::cursor_21_rotated)), tr("Scroll Horizontal"), true}, + {Action::Type::ScrollVertical, QChar(static_cast(Font::Icon::cursor_21)), tr("Scroll Vertical"), true}, + {Action::Type::VolumeControl, QChar(static_cast(Font::Icon::audio_6)), tr("Volume Control"), true}, }; static bool initIcons = []() diff --git a/src/asynchronous.h b/src/asynchronous.h index aded391..01e7e9c 100644 --- a/src/asynchronous.h +++ b/src/asynchronous.h @@ -43,14 +43,32 @@ auto capture_call(Lambda&& lambda, Args&& ... args){ capture_args = std::make_tuple(std::forward(args) ...) ](auto&& ... original_args)mutable{ return async::apply([&lambda](auto&& ... args){ - lambda(std::forward(args) ...); - }, - std::tuple_cat( - std::forward_as_tuple(original_args ...), - async::apply([](auto&& ... args){ - return std::forward_as_tuple( - std::move(args) ...); - }, std::move(capture_args)) + + // Handle the Qt6 return argument placeholder conditionally inside the body. +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + // Check if the tuple size is greater than the expected arguments (i.e., Qt6 inserted the return placeholder). + if constexpr (std::tuple_size(args)...))>::value > sizeof...(Args)) + { + // Unpack the arguments, skip the first one (the return value placeholder), and call the user-provided lambda. + auto tuple = std::make_tuple(std::forward(args)...); + + // std::apply applies a tuple to a function. We use a nested lambda here to skip the first element. + std::apply([&lambda](auto&& /* retArg */, auto&& ... actual_args){ + lambda(std::forward(actual_args)...); + }, std::move(tuple)); + } else +#endif + { + // Qt5 or Qt6 without the return placeholder: pass arguments directly to the user-provided lambda. + lambda(std::forward(args) ...); + } + }, + std::tuple_cat( + std::forward_as_tuple(original_args ...), + async::apply([](auto&& ... args){ + return std::forward_as_tuple( + std::move(args) ...); + }, std::move(capture_args)) )); }; } diff --git a/src/device-vibration.cc b/src/device-vibration.cc index 18b29a9..32ad1e9 100644 --- a/src/device-vibration.cc +++ b/src/device-vibration.cc @@ -77,8 +77,8 @@ struct TimerWidget::Impl btnStartStop->setCheckable(true); QObject::connect(btnStartStop, &IconButton::toggled, parent, [this](bool checked) { stack->setCurrentWidget(checked ? overlay : editor); - btnStartStop->setText(checked ? QChar(Font::Icon::media_control_50) - : QChar(Font::Icon::media_control_48)); + btnStartStop->setText(checked ? QChar(static_cast(Font::Icon::media_control_50)) + : QChar(static_cast(Font::Icon::media_control_48))); if (checked) { secondsLeft = valueSeconds(); updateOverlayLabel(secondsLeft); diff --git a/src/hidpp.h b/src/hidpp.h index 9cd861c..27117bb 100644 --- a/src/hidpp.h +++ b/src/hidpp.h @@ -13,6 +13,7 @@ #include #include +#include // Hidpp specific functionality // - code is heavily inspired by this library: https://github.com/cvuchener/hidpp diff --git a/src/iconwidgets.cc b/src/iconwidgets.cc index d789bd9..c9ed43a 100644 --- a/src/iconwidgets.cc +++ b/src/iconwidgets.cc @@ -22,7 +22,7 @@ IconButton::IconButton(Font::Icon symbol, QWidget* parent) iconFont.setPointSizeF(font().pointSizeF()); setFont(iconFont); - setText(QChar(symbol)); + setText(QChar(static_cast(symbol))); auto p = palette(); p.setColor(QPalette::ColorGroup::Normal, QPalette::ButtonText, @@ -33,7 +33,7 @@ IconButton::IconButton(Font::Icon symbol, QWidget* parent) // ------------------------------------------------------------------------------------------------- IconLabel::IconLabel(Font::Icon symbol, QWidget* parent) - : QLabel(QChar(symbol), parent) + : QLabel(QChar(static_cast(symbol)), parent) { QFont iconFont("projecteur-icons"); iconFont.setPixelSize(defaultIconLabelSize);