From fb5d6581ecb820ee3a8b846110c9335e7466fa6f Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Sun, 20 Feb 2022 17:55:26 +0100 Subject: [PATCH] Change all plugins to be QML_ELEMENT Add ScreenPlayWeather --- CMake/CMakeLists.txt | 4 +- CMake/FetchContentThirdParty.cmake | 11 ++ CMakeLists.txt | 3 +- Common/CMakeLists.txt | 10 + ScreenPlay/CMakeLists.txt | 18 +- ScreenPlayShader/CMakeLists.txt | 57 ++++-- ScreenPlayShader/Resources.qrc | 14 -- ScreenPlayShader/screenplayshader_plugin.cpp | 18 -- ScreenPlayShader/screenplayshader_plugin.h | 15 -- ScreenPlayShader/{ => shader}/lightning.frag | 0 ScreenPlayShader/{ => shader}/lightning.vert | 0 ScreenPlayShader/{ => shader}/water.frag | 0 ScreenPlayShader/{ => shader}/water.vert | 0 .../{ => src}/ShadertoyShader.qml | 0 ScreenPlayShader/src/TestMain.cpp | 26 +++ ScreenPlayShader/src/TestMain.qml | 16 ++ ScreenPlayShader/{ => src}/shaderlibrary.cpp | 8 +- ScreenPlayShader/{ => src}/shaderlibrary.h | 2 + ScreenPlaySysInfo/CMakeLists.txt | 67 ++++--- .../screenplaysysinfo_plugin.cpp | 18 -- ScreenPlaySysInfo/screenplaysysinfo_plugin.h | 45 ----- ScreenPlaySysInfo/src/TestMain.cpp | 26 +++ ScreenPlaySysInfo/src/TestMain.qml | 183 ++++++++++++++++++ ScreenPlaySysInfo/{ => src}/cpu.cpp | 0 ScreenPlaySysInfo/{ => src}/cpu.h | 3 +- ScreenPlaySysInfo/{ => src}/gpu.cpp | 0 ScreenPlaySysInfo/{ => src}/gpu.h | 2 + ScreenPlaySysInfo/{ => src}/mathhelper.h | 0 ScreenPlaySysInfo/{ => src}/ram.cpp | 0 ScreenPlaySysInfo/{ => src}/ram.h | 5 +- ScreenPlaySysInfo/{ => src}/storage.cpp | 0 ScreenPlaySysInfo/{ => src}/storage.h | 2 + ScreenPlaySysInfo/{ => src}/sysinfo.cpp | 0 ScreenPlaySysInfo/{ => src}/sysinfo.h | 3 +- ScreenPlaySysInfo/{ => src}/uptime.cpp | 0 ScreenPlaySysInfo/{ => src}/uptime.h | 3 +- ScreenPlayUtil/CMakeLists.txt | 18 +- .../ScreenPlayUtil/AutoPropertyHelpers.h | 76 ++++++++ .../ScreenPlayUtil/ConstRefPropertyHelpers.h | 63 ++++++ .../public/ScreenPlayUtil/EnumClassHelper.h | 40 ++++ .../inc/public/ScreenPlayUtil/HelpersCommon.h | 73 +++++++ .../ScreenPlayUtil/ListPropertyHelper.h | 65 +++++++ .../public/ScreenPlayUtil/PropertyHelpers.h | 66 +++++++ .../ScreenPlayUtil/PtrPropertyHelpers.h | 126 ++++++++++++ .../inc/public/ScreenPlayUtil/Readme.md | 2 + .../public/ScreenPlayUtil/SingletonHelper.h | 31 +++ .../inc/public/ScreenPlayUtil/util.h | 3 + ScreenPlayUtil/src/util.cpp | 6 + ScreenPlayWallpaper/CMakeLists.txt | 4 + ScreenPlayWallpaper/main.cpp | 4 + ScreenPlayWeather/CMakeLists.txt | 49 +++++ ScreenPlayWeather/Readme.md | 1 + ScreenPlayWeather/src/TestMain.cpp | 26 +++ ScreenPlayWeather/src/TestMain.qml | 96 +++++++++ ScreenPlayWeather/src/day.h | 20 ++ ScreenPlayWeather/src/screenplayweather.cpp | 145 ++++++++++++++ ScreenPlayWeather/src/screenplayweather.h | 115 +++++++++++ ScreenPlayWidget/CMakeLists.txt | 4 + ScreenPlayWidget/main.cpp | 3 + ScreenPlayWorkshop/CMakeLists.txt | 4 +- Tools/CMakeLists.txt | 3 +- 61 files changed, 1421 insertions(+), 181 deletions(-) create mode 100644 CMake/FetchContentThirdParty.cmake create mode 100644 Common/CMakeLists.txt delete mode 100644 ScreenPlayShader/Resources.qrc delete mode 100644 ScreenPlayShader/screenplayshader_plugin.cpp delete mode 100644 ScreenPlayShader/screenplayshader_plugin.h rename ScreenPlayShader/{ => shader}/lightning.frag (100%) rename ScreenPlayShader/{ => shader}/lightning.vert (100%) rename ScreenPlayShader/{ => shader}/water.frag (100%) rename ScreenPlayShader/{ => shader}/water.vert (100%) rename ScreenPlayShader/{ => src}/ShadertoyShader.qml (100%) create mode 100644 ScreenPlayShader/src/TestMain.cpp create mode 100644 ScreenPlayShader/src/TestMain.qml rename ScreenPlayShader/{ => src}/shaderlibrary.cpp (73%) rename ScreenPlayShader/{ => src}/shaderlibrary.h (98%) delete mode 100644 ScreenPlaySysInfo/screenplaysysinfo_plugin.cpp delete mode 100644 ScreenPlaySysInfo/screenplaysysinfo_plugin.h create mode 100644 ScreenPlaySysInfo/src/TestMain.cpp create mode 100644 ScreenPlaySysInfo/src/TestMain.qml rename ScreenPlaySysInfo/{ => src}/cpu.cpp (100%) rename ScreenPlaySysInfo/{ => src}/cpu.h (98%) rename ScreenPlaySysInfo/{ => src}/gpu.cpp (100%) rename ScreenPlaySysInfo/{ => src}/gpu.h (98%) rename ScreenPlaySysInfo/{ => src}/mathhelper.h (100%) rename ScreenPlaySysInfo/{ => src}/ram.cpp (100%) rename ScreenPlaySysInfo/{ => src}/ram.h (99%) rename ScreenPlaySysInfo/{ => src}/storage.cpp (100%) rename ScreenPlaySysInfo/{ => src}/storage.h (98%) rename ScreenPlaySysInfo/{ => src}/sysinfo.cpp (100%) rename ScreenPlaySysInfo/{ => src}/sysinfo.h (98%) rename ScreenPlaySysInfo/{ => src}/uptime.cpp (100%) rename ScreenPlaySysInfo/{ => src}/uptime.h (98%) create mode 100644 ScreenPlayUtil/inc/public/ScreenPlayUtil/AutoPropertyHelpers.h create mode 100644 ScreenPlayUtil/inc/public/ScreenPlayUtil/ConstRefPropertyHelpers.h create mode 100644 ScreenPlayUtil/inc/public/ScreenPlayUtil/EnumClassHelper.h create mode 100644 ScreenPlayUtil/inc/public/ScreenPlayUtil/HelpersCommon.h create mode 100644 ScreenPlayUtil/inc/public/ScreenPlayUtil/ListPropertyHelper.h create mode 100644 ScreenPlayUtil/inc/public/ScreenPlayUtil/PropertyHelpers.h create mode 100644 ScreenPlayUtil/inc/public/ScreenPlayUtil/PtrPropertyHelpers.h create mode 100644 ScreenPlayUtil/inc/public/ScreenPlayUtil/Readme.md create mode 100644 ScreenPlayUtil/inc/public/ScreenPlayUtil/SingletonHelper.h create mode 100644 ScreenPlayWeather/CMakeLists.txt create mode 100644 ScreenPlayWeather/Readme.md create mode 100644 ScreenPlayWeather/src/TestMain.cpp create mode 100644 ScreenPlayWeather/src/TestMain.qml create mode 100644 ScreenPlayWeather/src/day.h create mode 100644 ScreenPlayWeather/src/screenplayweather.cpp create mode 100644 ScreenPlayWeather/src/screenplayweather.h diff --git a/CMake/CMakeLists.txt b/CMake/CMakeLists.txt index 9484c3fe..bfafb093 100644 --- a/CMake/CMakeLists.txt +++ b/CMake/CMakeLists.txt @@ -1,9 +1,7 @@ project(CMake) set(FILES # cmake-format: sortable - CopyRecursive.cmake - CreateIFWInstaller.cmake - QtUpdateTranslations.cmake) + CopyRecursive.cmake CreateIFWInstaller.cmake FetchContentThirdParty.cmake QtUpdateTranslations.cmake) add_custom_target( ${PROJECT_NAME} diff --git a/CMake/FetchContentThirdParty.cmake b/CMake/FetchContentThirdParty.cmake new file mode 100644 index 00000000..ef683f63 --- /dev/null +++ b/CMake/FetchContentThirdParty.cmake @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.16.0) + +include(FetchContent) + +FetchContent_Declare( + qml-plausible + GIT_REPOSITORY https://gitlab.com/kelteseth/qml-plausible.git + GIT_TAG 00398446c7a2882a11d34c007a1ed8205c72e123 +) + +FetchContent_MakeAvailable(qml-plausible) diff --git a/CMakeLists.txt b/CMakeLists.txt index a3a226e9..d005681a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,8 +84,10 @@ add_subdirectory(ScreenPlayShader) add_subdirectory(ScreenPlayWallpaper) add_subdirectory(ScreenPlayWidget) add_subdirectory(ScreenPlayUtil) +add_subdirectory(ScreenPlayWeather) add_subdirectory(CMake) add_subdirectory(Tools) +include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/FetchContentThirdParty.cmake) if(${SCREENPLAY_STEAM}) add_subdirectory(ScreenPlayWorkshop) @@ -114,4 +116,3 @@ message(STATUS "[PROJECT] CMAKE_VERSION = ${CMAKE_VERSION}") if(${SCREENPLAY_CREATE_INSTALLER}) include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/CreateIFWInstaller.cmake) endif() - diff --git a/Common/CMakeLists.txt b/Common/CMakeLists.txt new file mode 100644 index 00000000..0eb6f575 --- /dev/null +++ b/Common/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.16.0) + +include(FetchContent) + +FetchContent_Declare( + qml-plausible + GIT_REPOSITORY https://gitlab.com/kelteseth/qml-plausible.git + GIT_TAG 00398446c7a2882a11d34c007a1ed8205c72e123) + +FetchContent_MakeAvailable(qml-plausible) diff --git a/ScreenPlay/CMakeLists.txt b/ScreenPlay/CMakeLists.txt index ec4f3940..6c790231 100644 --- a/ScreenPlay/CMakeLists.txt +++ b/ScreenPlay/CMakeLists.txt @@ -180,7 +180,6 @@ find_package( qt_add_resources(RESOURCES Resources.qrc) qt_add_big_resources(FONTS fonts.qrc) - add_library(ScreenPlayLib ${SOURCES} ${HEADER} ${RESOURCES} ${FONTS}) target_link_libraries( @@ -197,7 +196,8 @@ target_link_libraries( Qt6::WebSockets Qt6::Svg ScreenPlayQmlplugin - SteamSDKQtEnums) + SteamSDKQtEnums + Plausibleplugin) if(${TESTS_ENABLED}) add_executable(tst_ScreenPlay tests/tst_main.cpp) @@ -207,27 +207,25 @@ endif() qt_add_executable(${PROJECT_NAME} main.cpp) target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlayLib) -set_source_files_properties(${TS_FILES} - PROPERTIES OUTPUT_LOCATION "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/translations") +set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/translations") # qt_add_lupdate does not work for some reason. Lets do it manually: find_program(LUPDATE_EXECUTABLE lupdate) foreach(_ts_file ${TS_FILES}) message(STATUS "Update Translation: ${_ts_file}") - execute_process(COMMAND ${LUPDATE_EXECUTABLE} -noobsolete -locations none -recursive ${CMAKE_CURRENT_SOURCE_DIR}/qml -ts ${CMAKE_CURRENT_SOURCE_DIR}/${_ts_file} OUTPUT_QUIET) + execute_process(COMMAND ${LUPDATE_EXECUTABLE} -noobsolete -locations none -recursive ${CMAKE_CURRENT_SOURCE_DIR}/qml -ts + ${CMAKE_CURRENT_SOURCE_DIR}/${_ts_file} OUTPUT_QUIET) endforeach() -qt_add_lrelease( - ${PROJECT_NAME} - TS_FILES - ${TS_FILES} - ) +qt_add_lrelease(${PROJECT_NAME} TS_FILES ${TS_FILES}) target_compile_definitions(${PROJECT_NAME} PRIVATE $<$,$>:QT_QML_DEBUG>) qt_add_library(ScreenPlayQml STATIC) qt_add_qml_module( ScreenPlayQml + OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/bin/ScreenPlayQml URI ScreenPlayQml VERSION diff --git a/ScreenPlayShader/CMakeLists.txt b/ScreenPlayShader/CMakeLists.txt index 41636337..3846d670 100644 --- a/ScreenPlayShader/CMakeLists.txt +++ b/ScreenPlayShader/CMakeLists.txt @@ -6,30 +6,63 @@ set(CMAKE_AUTOMOC ON) find_package( Qt6 - COMPONENTS Quick Core + COMPONENTS Quick Core ShaderTools REQUIRED) -set(SOURCES # cmake-format: sortable - screenplayshader_plugin.cpp shaderlibrary.cpp) +# Because this is a plugin, we need this for testing and development. This can be disabled when using the plugin in your project directly. +option(tst_ScreenPlayShader "Builds TextProject" ON) -set(HEADER # cmake-format: sortable - screenplayshader_plugin.h shaderlibrary.h) +set(QML_RESOURCES # cmake-format: sortable + shader/lightning.frag + shader/lightning.vert + shader/water.frag + shader/water.vert + ) -qt_add_resources(RESOURCES Resources.qrc) +# https://doc.qt.io/qt-6/qtshadertools-build.html +qt6_add_shaders(${PROJECT_NAME} "${PROJECT_NAME}Shaders" + PREFIX + "/shaders" + FILES + shader/lightning.frag + shader/lightning.vert + shader/water.frag + shader/water.vert +) -add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADER} ${RESOURCES}) +set(QML # cmake-format: sortable + src/ShadertoyShader.qml + src/TestMain.qml) + +set(QML_PLUGIN_SOURCES # cmake-format: sortable + src/shaderlibrary.cpp) + +set(QML_PLUGIN_HEADER # cmake-format: sortable + src/shaderlibrary.h) + +add_library(${PROJECT_NAME} STATIC) +target_include_directories(${PROJECT_NAME} PUBLIC src/) qt_add_qml_module( ${PROJECT_NAME} URI ${PROJECT_NAME} + OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/bin/${PROJECT_NAME} VERSION 1.0 QML_FILES - ShadertoyShader.qml) - -target_include_directories(${PROJECT_NAME} PRIVATE inc) - -target_compile_definitions(${PROJECT_NAME} PRIVATE $<$,$>:QT_QML_DEBUG>) + ${QML} + SOURCES + ${QML_PLUGIN_SOURCES} + ${QML_PLUGIN_HEADER} + RESOURCES + ${QML_RESOURCES}) target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick Qt6::Gui) + +if(${tst_ScreenPlayShader}) + qt_add_executable(tst_ScreenPlayShader src/TestMain.cpp) + target_link_libraries(tst_ScreenPlayShader PRIVATE Qt6::Quick ${PROJECT_NAME}plugin) + target_compile_definitions(tst_ScreenPlayShader PRIVATE $<$,$>:QT_QML_DEBUG>) +endif() diff --git a/ScreenPlayShader/Resources.qrc b/ScreenPlayShader/Resources.qrc deleted file mode 100644 index beb6f9cd..00000000 --- a/ScreenPlayShader/Resources.qrc +++ /dev/null @@ -1,14 +0,0 @@ - - - lightning.frag - lightning.vert - water.frag - water.vert - assets/Shadertoy_Bayer.png - assets/Shadertoy_Gray_Noise_Medium.png - assets/Shadertoy_Lichen.jpg - - - ShadertoyShader.qml - - diff --git a/ScreenPlayShader/screenplayshader_plugin.cpp b/ScreenPlayShader/screenplayshader_plugin.cpp deleted file mode 100644 index 561066dd..00000000 --- a/ScreenPlayShader/screenplayshader_plugin.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "screenplayshader_plugin.h" - -#include -#include -#include - -QObject* ScreenPlayShaderLibrarySingleton(QQmlEngine* engine, QJSEngine* scriptEngine) -{ - Q_UNUSED(scriptEngine) - return new ShaderLibrary(); -} - -void ScreenPlayShaderPlugin::registerTypes(const char* uri) -{ - - qmlRegisterType(QUrl("qrc:/ShaderWrapper/ShadertoyShader.qml"), "ScreenPlay.ShadertoyShader", 1, 0, "ShadertoyShader"); - qmlRegisterSingletonType(uri, 1, 0, "ShaderLibrary", ScreenPlayShaderLibrarySingleton); -} diff --git a/ScreenPlayShader/screenplayshader_plugin.h b/ScreenPlayShader/screenplayshader_plugin.h deleted file mode 100644 index 0594cf28..00000000 --- a/ScreenPlayShader/screenplayshader_plugin.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include - -#include "shaderlibrary.h" - -class ScreenPlayShaderPlugin : public QQmlExtensionPlugin { - Q_OBJECT - Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) - -public: - void registerTypes(const char* uri) override; - -private: - ShaderLibrary m_shaderLibrary; -}; diff --git a/ScreenPlayShader/lightning.frag b/ScreenPlayShader/shader/lightning.frag similarity index 100% rename from ScreenPlayShader/lightning.frag rename to ScreenPlayShader/shader/lightning.frag diff --git a/ScreenPlayShader/lightning.vert b/ScreenPlayShader/shader/lightning.vert similarity index 100% rename from ScreenPlayShader/lightning.vert rename to ScreenPlayShader/shader/lightning.vert diff --git a/ScreenPlayShader/water.frag b/ScreenPlayShader/shader/water.frag similarity index 100% rename from ScreenPlayShader/water.frag rename to ScreenPlayShader/shader/water.frag diff --git a/ScreenPlayShader/water.vert b/ScreenPlayShader/shader/water.vert similarity index 100% rename from ScreenPlayShader/water.vert rename to ScreenPlayShader/shader/water.vert diff --git a/ScreenPlayShader/ShadertoyShader.qml b/ScreenPlayShader/src/ShadertoyShader.qml similarity index 100% rename from ScreenPlayShader/ShadertoyShader.qml rename to ScreenPlayShader/src/ShadertoyShader.qml diff --git a/ScreenPlayShader/src/TestMain.cpp b/ScreenPlayShader/src/TestMain.cpp new file mode 100644 index 00000000..442de16c --- /dev/null +++ b/ScreenPlayShader/src/TestMain.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +Q_IMPORT_QML_PLUGIN(ScreenPlayShaderPlugin) + +int main(int argc, char* argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + // The first subfolder is the libraryName followed by the regular + // folder strucutre: LibararyName/Subfolder + const QUrl url(u"qrc:/ScreenPlayShader/src/TestMain.qml"_qs); + QObject::connect( + &engine, &QQmlApplicationEngine::objectCreated, + &app, [url](QObject* obj, const QUrl& objUrl) { + if (!obj && url == objUrl) + QCoreApplication::exit(-1); + }, + Qt::QueuedConnection); + engine.load(url); + + return app.exec(); +} diff --git a/ScreenPlayShader/src/TestMain.qml b/ScreenPlayShader/src/TestMain.qml new file mode 100644 index 00000000..22a2f56c --- /dev/null +++ b/ScreenPlayShader/src/TestMain.qml @@ -0,0 +1,16 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Controls.Material +import ScreenPlayShader 1.0 + +Window { + id: root + width: 1366 + height: 768 + visible: true + title: qsTr("ScreenPlayShader") + + + +} diff --git a/ScreenPlayShader/shaderlibrary.cpp b/ScreenPlayShader/src/shaderlibrary.cpp similarity index 73% rename from ScreenPlayShader/shaderlibrary.cpp rename to ScreenPlayShader/src/shaderlibrary.cpp index 5fccb64c..b4723d7f 100644 --- a/ScreenPlayShader/shaderlibrary.cpp +++ b/ScreenPlayShader/src/shaderlibrary.cpp @@ -21,15 +21,15 @@ ShaderLibrary::ShaderLibrary(QQuickItem* parent) : QQuickItem(parent) { - QFile lightningFragFile(":/lightning.frag"); + QFile lightningFragFile("qrc:/ScreenPlaySysInfo/src/lightning.frag"); lightningFragFile.open(QIODevice::ReadOnly); - QFile lightningVertFile(":/lightning.vert"); + QFile lightningVertFile("qrc:/ScreenPlaySysInfo/src/lightning.vert"); lightningVertFile.open(QIODevice::ReadOnly); m_lightning = std::make_unique(lightningVertFile.readAll(), lightningFragFile.readAll()); - QFile waterFragFile(":/water.frag"); + QFile waterFragFile("qrc:/ScreenPlaySysInfo/src/water.frag"); waterFragFile.open(QIODevice::ReadOnly); - QFile waterVertFile(":/water.vert"); + QFile waterVertFile("qrc:/ScreenPlaySysInfo/src/water.vert"); waterVertFile.open(QIODevice::ReadOnly); m_water = std::make_unique(waterVertFile.readAll(), waterFragFile.readAll()); } diff --git a/ScreenPlayShader/shaderlibrary.h b/ScreenPlayShader/src/shaderlibrary.h similarity index 98% rename from ScreenPlayShader/shaderlibrary.h rename to ScreenPlayShader/src/shaderlibrary.h index 6747f92c..f17ba63b 100644 --- a/ScreenPlayShader/shaderlibrary.h +++ b/ScreenPlayShader/src/shaderlibrary.h @@ -4,6 +4,7 @@ #include #include #include +#include class Shader : public QObject { Q_OBJECT @@ -63,6 +64,7 @@ class ShaderLibrary : public QQuickItem { Q_PROPERTY(Shader* lightning READ lightning WRITE setLightning NOTIFY lightningChanged) Q_PROPERTY(Shader* water READ water WRITE setWater NOTIFY waterChanged) + QML_ELEMENT public: explicit ShaderLibrary(QQuickItem* parent = nullptr); diff --git a/ScreenPlaySysInfo/CMakeLists.txt b/ScreenPlaySysInfo/CMakeLists.txt index 6026ab85..4d78c5b0 100644 --- a/ScreenPlaySysInfo/CMakeLists.txt +++ b/ScreenPlaySysInfo/CMakeLists.txt @@ -1,7 +1,10 @@ -project(ScreenPlaySysInfo LANGUAGES CXX) +project( + ScreenPlaySysInfo + VERSION 0.1 + LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) -set(CMAKE_AUTORCC ON) +set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) find_package(infoware CONFIG REQUIRED) @@ -11,38 +14,46 @@ find_package( COMPONENTS Quick Core REQUIRED) -set(SOURCES - # cmake-format: sortable - screenplaysysinfo_plugin.cpp - sysinfo.cpp - cpu.cpp - ram.cpp - storage.cpp - uptime.cpp - gpu.cpp) +# Because this is a plugin, we need this for testing and development. This can be disabled when using the plugin in your project directly. +option(tst_ScreenPlaySysInfo "Builds TextProject" ON) -set(HEADER - # cmake-format: sortable - screenplaysysinfo_plugin.h - sysinfo.h - cpu.h - ram.h - mathhelper.h - storage.h - uptime.h - gpu.h) +set(QML # cmake-format: sortable + src/TestMain.qml) + +set(QML_PLUGIN_SOURCES # cmake-format: sortable + src/sysinfo.cpp src/cpu.cpp src/ram.cpp src/storage.cpp src/uptime.cpp src/gpu.cpp) + +set(QML_PLUGIN_HEADER + # cmake-format: sortable + src/sysinfo.h + src/cpu.h + src/ram.h + src/mathhelper.h + src/storage.h + src/uptime.h + src/gpu.h) + +add_library(${PROJECT_NAME} STATIC) +target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick infoware) +target_include_directories(${PROJECT_NAME} PUBLIC src/) -add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADER}) qt_add_qml_module( ${PROJECT_NAME} - OUTPUT_DIRECTORY - ${CMAKE_BINARY_DIR}/bin/SysInfo URI ${PROJECT_NAME} VERSION - 1.0) + 1.0 + OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/bin/${PROJECT_NAME} + QML_FILES + ${QML} + SOURCES + ${QML_PLUGIN_SOURCES} + ${QML_PLUGIN_HEADER}) -target_compile_definitions(${PROJECT_NAME} PRIVATE $<$,$>:QT_QML_DEBUG>) - -target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick infoware) +if(${tst_ScreenPlaySysInfo}) + qt_add_executable(tst_ScreenPlaySysInfo src/TestMain.cpp) + target_link_libraries(tst_ScreenPlaySysInfo PRIVATE Qt6::Quick ${PROJECT_NAME}plugin) + target_compile_definitions(tst_ScreenPlaySysInfo PRIVATE $<$,$>:QT_QML_DEBUG>) +endif() diff --git a/ScreenPlaySysInfo/screenplaysysinfo_plugin.cpp b/ScreenPlaySysInfo/screenplaysysinfo_plugin.cpp deleted file mode 100644 index ebd4f750..00000000 --- a/ScreenPlaySysInfo/screenplaysysinfo_plugin.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "screenplaysysinfo_plugin.h" -#include "sysinfo.h" -#include -#include - -QObject* ScreenPlaySysInfoSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) -{ - Q_UNUSED(engine) - Q_UNUSED(scriptEngine) - - return new SysInfo(); -} - -void ScreenPlaySysInfoPlugin::registerTypes(const char* uri) -{ - // @uri ScreenPlay.Sysinfo - qmlRegisterSingletonType(uri, 1, 0, "SysInfo", ScreenPlaySysInfoSingleton); -} diff --git a/ScreenPlaySysInfo/screenplaysysinfo_plugin.h b/ScreenPlaySysInfo/screenplaysysinfo_plugin.h deleted file mode 100644 index 5dd35de4..00000000 --- a/ScreenPlaySysInfo/screenplaysysinfo_plugin.h +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 Elias Steurer (Kelteseth) -** Contact: https://screen-play.app -** -** This file is part of ScreenPlay. ScreenPlay is licensed under a dual license in -** order to ensure its sustainability. When you contribute to ScreenPlay -** you accept that your work will be available under the two following licenses: -** -** $SCREENPLAY_BEGIN_LICENSE$ -** -** #### Affero General Public License Usage (AGPLv3) -** Alternatively, this file may be used under the terms of the GNU Affero -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file "ScreenPlay License.md" included in the -** packaging of this App. Please review the following information to -** ensure the GNU Affero Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/agpl-3.0.en.html. -** -** #### Commercial License -** This code is owned by Elias Steurer. By changing/adding to the code you agree to the -** terms written in: -** * Legal/corporate_contributor_license_agreement.md - For corporate contributors -** * Legal/individual_contributor_license_agreement.md - For individual contributors -** -** #### Additional Limitations to the AGPLv3 and Commercial Lincese -** This License does not grant any rights in the trademarks, -** service marks, or logos. -** -** -** $SCREENPLAY_END_LICENSE$ -** -****************************************************************************/ - -#pragma once - -#include - -class ScreenPlaySysInfoPlugin : public QQmlExtensionPlugin { - Q_OBJECT - Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) - -public: - void registerTypes(const char* uri); -}; diff --git a/ScreenPlaySysInfo/src/TestMain.cpp b/ScreenPlaySysInfo/src/TestMain.cpp new file mode 100644 index 00000000..bc9a96e2 --- /dev/null +++ b/ScreenPlaySysInfo/src/TestMain.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +Q_IMPORT_QML_PLUGIN(ScreenPlaySysInfoPlugin) + +int main(int argc, char* argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + // The first subfolder is the libraryName followed by the regular + // folder strucutre: LibararyName/Subfolder + const QUrl url(u"qrc:/ScreenPlaySysInfo/src/TestMain.qml"_qs); + QObject::connect( + &engine, &QQmlApplicationEngine::objectCreated, + &app, [url](QObject* obj, const QUrl& objUrl) { + if (!obj && url == objUrl) + QCoreApplication::exit(-1); + }, + Qt::QueuedConnection); + engine.load(url); + + return app.exec(); +} diff --git a/ScreenPlaySysInfo/src/TestMain.qml b/ScreenPlaySysInfo/src/TestMain.qml new file mode 100644 index 00000000..26cd5b99 --- /dev/null +++ b/ScreenPlaySysInfo/src/TestMain.qml @@ -0,0 +1,183 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Controls.Material +import ScreenPlaySysInfo 1.0 + +Window { + id: root + width: 1366 + height: 768 + visible: true + title: qsTr("ScreenPlaySysInfo") + color: "#19181E" + + property color accentColor: "#FF9800" + property string fontFamily: "Arial" + property int fontPointSize: 16 + + SysInfo { + id:sysInfo + } + + Rectangle { + anchors.fill: wrapper + anchors.margins: -50 + color: "#212128" + border.color: root.accentColor + border.width: 10 + } + + ColumnLayout { + id: wrapper + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + + Text { + id: txtGPU + text: "GPU" + color: root.accentColor + font.family: root.fontFamily + font.pointSize: 60 + horizontalAlignment: Text.AlignHCenter + } + + RowLayout { + Text { + id: name + text: sysInfo.gpu.vendor + color: root.accentColor + horizontalAlignment: Text.AlignHCenter + font { + pointSize: 16 + family: "Fira Code" + } + } + Text { + text: sysInfo.gpu.name + color: root.accentColor + horizontalAlignment: Text.AlignHCenter + font { + pointSize: 16 + family: root.fontFamily + } + } + } + + Text { + id: txtUptime + text: "UPTIME" + color: root.accentColor + font.family: root.fontFamily + font.pointSize: 60 + horizontalAlignment: Text.AlignHCenter + } + + RowLayout { + id: valuesLayout + spacing: 20 + Text { + id: txtYears + text: "YEARS " + sysInfo.uptime.years + color: root.accentColor + font.family: root.fontFamily + font.pointSize: root.fontPointSize + } + Text { + text: "DAYS " + sysInfo.uptime.days + color: root.accentColor + font.family: root.fontFamily + font.pointSize: root.fontPointSize + } + Text { + text: "HOURS " + sysInfo.uptime.hours + color: root.accentColor + font.family: root.fontFamily + font.pointSize: root.fontPointSize + } + Text { + text: "MINUTES " + sysInfo.uptime.minutes + color: root.accentColor + font.family: root.fontFamily + font.pointSize: root.fontPointSize + } + + Text { + id: txtSeconds + text: "SECONDS " + sysInfo.uptime.seconds + color: root.accentColor + font.family: root.fontFamily + font.pointSize: root.fontPointSize + } + } + Text { + id: txtCPU + text: "CPU" + color: root.accentColor + font.family: root.fontFamily + font.pointSize: 60 + horizontalAlignment: Text.AlignHCenter + } + Row { + id: row + spacing: 10 + Layout.fillWidth: true + Text { + id: txtCPUValue + text: Math.floor(sysInfo.cpu.usage) + color: root.accentColor + font.family: root.fontFamily + width: 70 + } + ProgressBar { + from: 0 + to: 100 + value: Math.floor(sysInfo.cpu.usage) + Layout.fillWidth: true + } + } + + Text { + id: txtStorage + text: "STORAGE" + color: root.accentColor + font.family: root.fontFamily + font.pointSize: 60 + horizontalAlignment: Text.AlignHCenter + } + + Item { + Layout.fillWidth: true + Layout.preferredHeight: 20 + } + + ListView { + id: storageListView + Layout.fillWidth: true + Layout.preferredHeight: 100 + model: sysInfo.storage + delegate: Item { + width: storageListView.width + height: 40 + Row { + spacing: 10 + Text { + id: txtStorageName + text: name + color: root.accentColor + font.family: root.fontFamily + width: 70 + } + ProgressBar { + from: 0 + to: bytesTotal + value: bytesAvailable + width: storageListView.width - txtStorageName.width - row.spacing + } + } + } + } + } +} diff --git a/ScreenPlaySysInfo/cpu.cpp b/ScreenPlaySysInfo/src/cpu.cpp similarity index 100% rename from ScreenPlaySysInfo/cpu.cpp rename to ScreenPlaySysInfo/src/cpu.cpp diff --git a/ScreenPlaySysInfo/cpu.h b/ScreenPlaySysInfo/src/cpu.h similarity index 98% rename from ScreenPlaySysInfo/cpu.h rename to ScreenPlaySysInfo/src/cpu.h index 0339a9b8..06704f98 100644 --- a/ScreenPlaySysInfo/cpu.h +++ b/ScreenPlaySysInfo/src/cpu.h @@ -38,6 +38,7 @@ #include #include #include +#include #ifdef Q_OS_WIN #include @@ -46,9 +47,9 @@ class CPU : public QObject { Q_OBJECT - Q_PROPERTY(float usage READ usage NOTIFY usageChanged) Q_PROPERTY(int tickRate READ tickRate WRITE setTickRate NOTIFY tickRateChanged) + QML_ELEMENT public: explicit CPU(QObject* parent = nullptr); diff --git a/ScreenPlaySysInfo/gpu.cpp b/ScreenPlaySysInfo/src/gpu.cpp similarity index 100% rename from ScreenPlaySysInfo/gpu.cpp rename to ScreenPlaySysInfo/src/gpu.cpp diff --git a/ScreenPlaySysInfo/gpu.h b/ScreenPlaySysInfo/src/gpu.h similarity index 98% rename from ScreenPlaySysInfo/gpu.h rename to ScreenPlaySysInfo/src/gpu.h index 3c6f34d5..17b388aa 100644 --- a/ScreenPlaySysInfo/gpu.h +++ b/ScreenPlaySysInfo/src/gpu.h @@ -1,5 +1,6 @@ #pragma once #include +#include class GPU : public QObject { Q_OBJECT @@ -8,6 +9,7 @@ class GPU : public QObject { Q_PROPERTY(int ramSize READ ramSize WRITE setRamSize NOTIFY ramSizeChanged) Q_PROPERTY(int cacheSize READ cacheSize WRITE setCacheSize NOTIFY cacheSizeChanged) Q_PROPERTY(int maxFrequency READ maxFrequency WRITE setMaxFrequency NOTIFY maxFrequencyChanged) + QML_ELEMENT public: explicit GPU(QObject* parent = nullptr); diff --git a/ScreenPlaySysInfo/mathhelper.h b/ScreenPlaySysInfo/src/mathhelper.h similarity index 100% rename from ScreenPlaySysInfo/mathhelper.h rename to ScreenPlaySysInfo/src/mathhelper.h diff --git a/ScreenPlaySysInfo/ram.cpp b/ScreenPlaySysInfo/src/ram.cpp similarity index 100% rename from ScreenPlaySysInfo/ram.cpp rename to ScreenPlaySysInfo/src/ram.cpp diff --git a/ScreenPlaySysInfo/ram.h b/ScreenPlaySysInfo/src/ram.h similarity index 99% rename from ScreenPlaySysInfo/ram.h rename to ScreenPlaySysInfo/src/ram.h index 3a723f74..d5c80e00 100644 --- a/ScreenPlaySysInfo/ram.h +++ b/ScreenPlaySysInfo/src/ram.h @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef Q_OS_WIN #include @@ -48,15 +49,13 @@ class RAM : public QObject { Q_OBJECT Q_PROPERTY(float usage READ usage NOTIFY usageChanged) - Q_PROPERTY(unsigned long long usedPhysicalMemory READ usedPhysicalMemory NOTIFY usedPhysicalMemoryChanged) Q_PROPERTY(unsigned long long totalPhysicalMemory READ totalPhysicalMemory NOTIFY totalPhysicalMemoryChanged) - Q_PROPERTY(unsigned long long usedVirtualMemory READ usedVirtualMemory NOTIFY usedVirtualMemoryChanged) Q_PROPERTY(unsigned long long totalVirtualMemory READ totalVirtualMemory NOTIFY totalVirtualMemoryChanged) - Q_PROPERTY(unsigned long long usedPagingMemory READ usedPagingMemory NOTIFY usedPagingMemoryChanged) Q_PROPERTY(unsigned long long totalPagingMemory READ totalPagingMemory NOTIFY totalPagingMemoryChanged) + QML_ELEMENT public: explicit RAM(QObject* parent = nullptr); diff --git a/ScreenPlaySysInfo/storage.cpp b/ScreenPlaySysInfo/src/storage.cpp similarity index 100% rename from ScreenPlaySysInfo/storage.cpp rename to ScreenPlaySysInfo/src/storage.cpp diff --git a/ScreenPlaySysInfo/storage.h b/ScreenPlaySysInfo/src/storage.h similarity index 98% rename from ScreenPlaySysInfo/storage.h rename to ScreenPlaySysInfo/src/storage.h index 1b89dd29..25cce9b1 100644 --- a/ScreenPlaySysInfo/storage.h +++ b/ScreenPlaySysInfo/src/storage.h @@ -39,9 +39,11 @@ #include #include #include +#include class Storage : public QAbstractListModel { Q_OBJECT + QML_ELEMENT public: explicit Storage(QObject* parent = nullptr); diff --git a/ScreenPlaySysInfo/sysinfo.cpp b/ScreenPlaySysInfo/src/sysinfo.cpp similarity index 100% rename from ScreenPlaySysInfo/sysinfo.cpp rename to ScreenPlaySysInfo/src/sysinfo.cpp diff --git a/ScreenPlaySysInfo/sysinfo.h b/ScreenPlaySysInfo/src/sysinfo.h similarity index 98% rename from ScreenPlaySysInfo/sysinfo.h rename to ScreenPlaySysInfo/src/sysinfo.h index 6293b7c3..bd59f3e6 100644 --- a/ScreenPlaySysInfo/sysinfo.h +++ b/ScreenPlaySysInfo/src/sysinfo.h @@ -34,6 +34,7 @@ #pragma once +#include #include #include @@ -45,12 +46,12 @@ class SysInfo : public QQuickItem { Q_OBJECT - Q_PROPERTY(GPU* gpu READ gpu NOTIFY gpuChanged) Q_PROPERTY(RAM* ram READ ram NOTIFY ramChanged) Q_PROPERTY(CPU* cpu READ cpu NOTIFY cpuChanged) Q_PROPERTY(Storage* storage READ storage NOTIFY storageChanged) Q_PROPERTY(Uptime* uptime READ uptime NOTIFY uptimeChanged) + QML_ELEMENT public: SysInfo(QQuickItem* parent = nullptr); diff --git a/ScreenPlaySysInfo/uptime.cpp b/ScreenPlaySysInfo/src/uptime.cpp similarity index 100% rename from ScreenPlaySysInfo/uptime.cpp rename to ScreenPlaySysInfo/src/uptime.cpp diff --git a/ScreenPlaySysInfo/uptime.h b/ScreenPlaySysInfo/src/uptime.h similarity index 98% rename from ScreenPlaySysInfo/uptime.h rename to ScreenPlaySysInfo/src/uptime.h index 444864ab..86906f64 100644 --- a/ScreenPlaySysInfo/uptime.h +++ b/ScreenPlaySysInfo/src/uptime.h @@ -1,15 +1,16 @@ #pragma once #include +#include #include class Uptime : public QObject { Q_OBJECT - Q_PROPERTY(int days READ days WRITE setDays NOTIFY daysChanged) Q_PROPERTY(int years READ years WRITE setYears NOTIFY yearsChanged) Q_PROPERTY(int hours READ hours WRITE setHours NOTIFY hoursChanged) Q_PROPERTY(int minutes READ minutes WRITE setMinutes NOTIFY minutesChanged) Q_PROPERTY(int seconds READ seconds WRITE setSeconds NOTIFY secondsChanged) + QML_ELEMENT public: Uptime(QObject* parent = nullptr); diff --git a/ScreenPlayUtil/CMakeLists.txt b/ScreenPlayUtil/CMakeLists.txt index 2d66b427..2cdc05e9 100644 --- a/ScreenPlayUtil/CMakeLists.txt +++ b/ScreenPlayUtil/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_AUTOMOC ON) find_package( Qt6 - COMPONENTS Core + COMPONENTS Core Quick REQUIRED) set(SOURCES # cmake-format: sortable @@ -14,8 +14,18 @@ set(SOURCES # cmake-format: sortable set(HEADER # cmake-format: sortable - inc/public/ScreenPlayUtil/util.h inc/public/ScreenPlayUtil/httpfileserver.h inc/public/ScreenPlayUtil/contenttypes.h - inc/public/ScreenPlayUtil/projectfile.h) + inc/public/ScreenPlayUtil/util.h + inc/public/ScreenPlayUtil/httpfileserver.h + inc/public/ScreenPlayUtil/contenttypes.h + inc/public/ScreenPlayUtil/projectfile.h + inc/public/ScreenPlayUtil/AutoPropertyHelpers.h + inc/public/ScreenPlayUtil/ConstRefPropertyHelpers.h + inc/public/ScreenPlayUtil/EnumClassHelper.h + inc/public/ScreenPlayUtil/HelpersCommon.h + inc/public/ScreenPlayUtil/ListPropertyHelper.h + inc/public/ScreenPlayUtil/PropertyHelpers.h + inc/public/ScreenPlayUtil/PtrPropertyHelpers.h + inc/public/ScreenPlayUtil/SingletonHelper.h) add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADER}) @@ -27,7 +37,7 @@ target_include_directories( PUBLIC inc/public/ PRIVATE src/) -target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core) +target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick) if(WIN32) # Used for query windows monitor data diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/AutoPropertyHelpers.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/AutoPropertyHelpers.h new file mode 100644 index 00000000..eca0a787 --- /dev/null +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/AutoPropertyHelpers.h @@ -0,0 +1,76 @@ +#pragma once + +#include + +#include "HelpersCommon.h" + +#define AUTO_GETTER(type, name) \ +public: \ + CheapestType::type_def MAKE_GETTER_NAME(name)() const { return m_##name; } + +#define AUTO_SETTER(type, name) \ +public: \ + void set_##name(CheapestType::type_def name) \ + { \ + if (m_##name != name) { \ + m_##name = name; \ + Q_EMIT name##Changed(); \ + } \ + } + +#define W_AUTO_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ + \ + MEMBER(type, name) \ + AUTO_GETTER(type, name) \ + AUTO_SETTER(type, name) \ + NOTIFIER(name) \ +private: + +#define R_AUTO_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) NOTIFY name##Changed) \ + \ + MEMBER(type, name) \ + AUTO_GETTER(type, name) \ + AUTO_SETTER(type, name) \ + NOTIFIER(name) \ +private: + +#define C_AUTO_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) CONSTANT) \ + \ + MEMBER(type, name) \ + AUTO_GETTER(type, name) \ +private: + +#define W_AUTO_PROPERTY_DEFAULT(type, name, defaultValue) \ + Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ + \ + MEMBER_DEFAULT(type, name, defaultValue) \ + AUTO_GETTER(type, name) \ + AUTO_SETTER(type, name) \ + NOTIFIER(name) \ +private: + +// NOTE : test class for all cases + +class _Test_QmlAutoProperty_ : public QObject { + Q_OBJECT + + W_AUTO_PROPERTY(bool, var1) + W_AUTO_PROPERTY(QString, var2) + W_AUTO_PROPERTY(QObject*, var3) + + R_AUTO_PROPERTY(bool, var4) + R_AUTO_PROPERTY(QString, var5) + R_AUTO_PROPERTY(QObject*, var6) + + C_AUTO_PROPERTY(bool, var7) + C_AUTO_PROPERTY(QString, var8) + C_AUTO_PROPERTY(QObject*, var9) + + W_AUTO_PROPERTY_DEFAULT(bool, var10, true) +}; diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/ConstRefPropertyHelpers.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/ConstRefPropertyHelpers.h new file mode 100644 index 00000000..ea3ef2a5 --- /dev/null +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/ConstRefPropertyHelpers.h @@ -0,0 +1,63 @@ +#pragma once + +#include + +#include "HelpersCommon.h" + +#define CONST_SETTER(type, name) \ +public: \ + void set_##name(const type& name) \ + { \ + if (m_##name != name) { \ + m_##name = name; \ + Q_EMIT name##Changed(); \ + } \ + } + +#define CONST_GETTER(type, name) \ +public: \ + const type& MAKE_GETTER_NAME(name)() const { return m_##name; } + +#define W_CREF_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ +private: \ + MEMBER(type, name) \ + CONST_GETTER(type, name) \ + CONST_SETTER(type, name) \ + NOTIFIER(name) + +#define R_CREF_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) NOTIFY name##Changed) \ + MEMBER(type, name) \ + CONST_GETTER(type, name) \ + CONST_SETTER(type, name) \ + NOTIFIER(name) \ +private: + +#define C_CREF_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) CONSTANT) \ + MEMBER(type, name) \ + CONST_GETTER(type, name) \ +private: + +#define W_CREF_PROPERTY_DEFAULT(type, name, defaultValue) \ +protected: \ + Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ +private: \ + MEMBER_DEFAULT(type, name, defaultValue) \ + CONST_GETTER(type, name) \ + CONST_SETTER(type, name) \ + NOTIFIER(name) + +class Test : public QObject { + Q_OBJECT + + W_CREF_PROPERTY(QString, var1) + R_CREF_PROPERTY(QString, var2) + C_CREF_PROPERTY(QString, var3) + + W_CREF_PROPERTY_DEFAULT(QString, var4, QStringLiteral("test")) +}; diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/EnumClassHelper.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/EnumClassHelper.h new file mode 100644 index 00000000..eed66637 --- /dev/null +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/EnumClassHelper.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#ifdef Q_ENUM +#define QML_EXPORT_ENUM Q_ENUM +#else +#define QML_EXPORT_ENUM Q_ENUMS +#endif + +#define QML_ENUM_CLASS(NAME, ...) \ + struct NAME { \ + Q_GADGET \ + public: \ + enum Type { __VA_ARGS__ }; \ + QML_EXPORT_ENUM(Type) \ + static QString asString(const int value) \ + { \ + return QString::fromLatin1(staticMetaObject.enumerator(0).valueToKey(value)); \ + } \ + static void registerQmlModule(const char* uri, const int majorVersion, const int minorVersion, const char* name) \ + { \ + qmlRegisterUncreatableType(uri, majorVersion, minorVersion, name, \ + QStringLiteral("Enum class, can't be instanciated !")); \ + } \ + \ + private: \ + explicit NAME() { } \ + NAME(const NAME&); \ + NAME& operator=(const NAME&); \ + ~NAME(); \ + }; \ + Q_DECLARE_METATYPE(NAME::Type) + +QML_ENUM_CLASS(_Test_QmlEnumClass_) // NOTE : to avoid "no suitable class found" MOC note diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/HelpersCommon.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/HelpersCommon.h new file mode 100644 index 00000000..f13637b1 --- /dev/null +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/HelpersCommon.h @@ -0,0 +1,73 @@ +#pragma once + +#include + +// NOTE : SFINAE trickery to find which type is the cheapest between T and const T & + +template +struct CheapestType { + using type_def = const T&; +}; +template <> +struct CheapestType { + using type_def = bool; +}; +template <> +struct CheapestType { + using type_def = quint8; +}; +template <> +struct CheapestType { + using type_def = quint16; +}; +template <> +struct CheapestType { + using type_def = quint32; +}; +template <> +struct CheapestType { + using type_def = quint64; +}; +template <> +struct CheapestType { + using type_def = qint8; +}; +template <> +struct CheapestType { + using type_def = qint16; +}; +template <> +struct CheapestType { + using type_def = qint32; +}; +template <> +struct CheapestType { + using type_def = qint64; +}; +template <> +struct CheapestType { + using type_def = float; +}; +template <> +struct CheapestType { + using type_def = double; +}; +template +struct CheapestType { + using type_def = T*; +}; + +// NOTE : define to add/remove 'get_' prefix on getters +#define MAKE_GETTER_NAME(name) name + +#define MEMBER(type, name) \ +private: \ + type m_##name {}; + +#define MEMBER_DEFAULT(type, name, value) \ +private: \ + type m_##name { value }; + +#define NOTIFIER(name) \ +Q_SIGNALS: \ + void name##Changed(); diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/ListPropertyHelper.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/ListPropertyHelper.h new file mode 100644 index 00000000..f46d1722 --- /dev/null +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/ListPropertyHelper.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include + +#include "HelpersCommon.h" + +template +class QQmlSmartListWrapper : public QQmlListProperty { +public: + typedef QVector CppListType; + typedef QQmlListProperty QmlListPropertyType; + typedef QQmlSmartListWrapper SmartListWrapperType; + + typedef typename CppListType::const_iterator const_iterator; + + explicit QQmlSmartListWrapper(QObject* object, const int reserve = 0) + : QmlListPropertyType(object, + &m_items, + &SmartListWrapperType::callbackAppend, + &SmartListWrapperType::callbackCount, + &SmartListWrapperType::callbackAt, + &SmartListWrapperType::callbackClear) + { + if (reserve > 0) { + m_items.reserve(reserve); + } + } + + const CppListType& items() const { return m_items; } + + const_iterator begin() const { return m_items.begin(); } + + const_iterator end() const { return m_items.end(); } + + const_iterator constBegin() const { return m_items.constBegin(); } + + const_iterator constEnd() const { return m_items.constEnd(); } + + static qsizetype callbackCount(QmlListPropertyType* prop) { return static_cast(prop->data)->count(); } + + static void callbackClear(QmlListPropertyType* prop) { static_cast(prop->data)->clear(); } + + static void callbackAppend(QmlListPropertyType* prop, ObjType* obj) + { + static_cast(prop->data)->append(obj); + } + + static ObjType* callbackAt(QmlListPropertyType* prop, qsizetype idx) + { + return static_cast(prop->data)->at(idx); + } + +private: + CppListType m_items; +}; + +#define LIST_PROPERTY(TYPE, NAME) \ +private: \ + Q_PROPERTY(QQmlListProperty NAME READ MAKE_GETTER_NAME(NAME) CONSTANT) \ +public: \ + const QQmlSmartListWrapper& MAKE_GETTER_NAME(NAME)() const { return m_##NAME; } \ + \ +private: \ + QQmlSmartListWrapper m_##NAME; diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/PropertyHelpers.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/PropertyHelpers.h new file mode 100644 index 00000000..908d563f --- /dev/null +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/PropertyHelpers.h @@ -0,0 +1,66 @@ +#pragma once + +#include + +#include "HelpersCommon.h" + +#define PROP_GETTER(type, name) \ +public: \ + type MAKE_GETTER_NAME(name)() const { return m_##name; } + +#define PROP_SETTER(type, name) \ +public: \ + void set_##name(type name) \ + { \ + if (m_##name != name) { \ + m_##name = name; \ + Q_EMIT name##Changed(); \ + } \ + } + +#define W_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ + \ + MEMBER(type, name) \ + PROP_GETTER(type, name) \ + PROP_SETTER(type, name) \ + NOTIFIER(name) \ +private: + +#define R_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) NOTIFY name##Changed) \ + \ + MEMBER(type, name) \ + PROP_GETTER(type, name) \ + PROP_SETTER(type, name) \ + NOTIFIER(name) \ +private: + +#define C_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) CONSTANT) \ + \ + MEMBER(type, name) \ + PROP_GETTER(type, name) \ +private: + +#define W_PROPERTY_DEFAULT(type, name, defaultValue) \ +protected: \ + Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ + \ + MEMBER_DEFAULT(type, name, defaultValue) \ + PROP_GETTER(type, name) \ + PROP_SETTER(type, name) \ + NOTIFIER(name) \ +private: + +class _QmlVarProperty_ : public QObject { + Q_OBJECT + W_PROPERTY(int, var1) + R_PROPERTY(bool, var2) + C_PROPERTY(int, var3) + + W_PROPERTY_DEFAULT(int, var4, 5) +}; diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/PtrPropertyHelpers.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/PtrPropertyHelpers.h new file mode 100644 index 00000000..7df55db5 --- /dev/null +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/PtrPropertyHelpers.h @@ -0,0 +1,126 @@ +#pragma once + +#include +#include + +#include "HelpersCommon.h" + +#define PTR_GETTER(type, name) \ +public: \ + type* MAKE_GETTER_NAME(name)() const { return m_##name; } + +#define PTR_SETTER(type, name) \ +public: \ + void set_##name(type* name) \ + { \ + if (m_##name != name) { \ + m_##name = name; \ + Q_EMIT name##Changed(); \ + } \ + } + +#define SMART_PTR_GETTER(type, name) \ +public: \ + type* MAKE_GETTER_NAME(name)() const { return m_##name.get(); } + +#define SMART_PTR_SETTER(type, name) \ +public: \ + void set_##name(type name) \ + { \ + m_##name = std::move(name); \ + Q_EMIT name##Changed(); \ + } + +#define W_PTR_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type* name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ + \ + MEMBER(type*, name) \ + PTR_GETTER(type, name) \ + PTR_SETTER(type, name) \ + NOTIFIER(name) \ +private: + +#define R_PTR_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type* name READ MAKE_GETTER_NAME(name) NOTIFY name##Changed) \ + \ + MEMBER(type*, name) \ + PTR_GETTER(type, name) \ + PTR_SETTER(type, name) \ + NOTIFIER(name) \ +private: + +#define C_PTR_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type* name READ MAKE_GETTER_NAME(name) CONSTANT) \ + \ + MEMBER(type*, name) \ + PTR_GETTER(type, name) \ +private: + +#define W_PTR_PROPERTY_DEFAULT(type, name, defaultValue) \ +protected: \ + Q_PROPERTY(type* name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ + \ + MEMBER_DEFAULT(type*, name, defaultValue) \ + PTR_GETTER(type, name) \ + PTR_SETTER(type, name) \ + NOTIFIER(name) \ +private: + +#define UNIQUE_PTR_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type* name READ name NOTIFY name##Changed) \ + \ + MEMBER(std::unique_ptr, name) \ + SMART_PTR_GETTER(type, name) \ + SMART_PTR_SETTER(std::unique_ptr&, name) \ + NOTIFIER(name) \ +private: + +#define UNIQUE_PTR_PROPERTY_INIT(type, name) \ +protected: \ + Q_PROPERTY(type* name READ name NOTIFY name##Changed) \ + \ + MEMBER_DEFAULT(std::unique_ptr, name, std::make_unique()) \ + SMART_PTR_GETTER(type, name) \ + SMART_PTR_SETTER(std::unique_ptr&, name) \ + NOTIFIER(name) \ +private: + +#define SHARED_PTR_PROPERTY(type, name) \ +protected: \ + Q_PROPERTY(type* name READ name NOTIFY name##Changed) \ + \ + MEMBER(std::shared_ptr, name) \ + SMART_PTR_GETTER(type, name) \ + SMART_PTR_SETTER(std::unique_ptr&, name) \ + NOTIFIER(name) \ +private: + +#define SHARED_PTR_PROPERTY_INIT(type, name) \ +protected: \ + Q_PROPERTY(type* name READ name NOTIFY name##Changed) \ + \ + MEMBER_DEFAULT(std::shared_ptr, name, std::make_shared()) \ + SMART_PTR_GETTER(type, name) \ + SMART_PTR_SETTER(std::shared_ptr, name) \ + NOTIFIER(name) \ +private: + +class _QmlPtrProperty_ : public QObject { + Q_OBJECT + + W_PTR_PROPERTY(int, var1) + R_PTR_PROPERTY(bool, var2) + C_PTR_PROPERTY(QString, test) + + // W_PTR_PROPERTY_DEFAULT(QString, var4, nullptr) + + // UNIQUE_PTR_PROPERTY(QString, test2) + // UNIQUE_PTR_PROPERTY_INIT(QString, test3) + + // SHARED_PTR_PROPERTY(QString, test4) + // SHARED_PTR_PROPERTY_INIT(QString, test5) +}; diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/Readme.md b/ScreenPlayUtil/inc/public/ScreenPlayUtil/Readme.md new file mode 100644 index 00000000..59023c7a --- /dev/null +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/Readme.md @@ -0,0 +1,2 @@ +# Qt Super-Macros +Based on: https://github.com/DoozyX/qt-property-macros \ No newline at end of file diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/SingletonHelper.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/SingletonHelper.h new file mode 100644 index 00000000..1b58691e --- /dev/null +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/SingletonHelper.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include + +#define QML_SINGLETON_IMPL(CLASS) \ +public: \ + static CLASS& instance() \ + { \ + static CLASS ret; \ + return ret; \ + } \ + static QObject* qmlSingletonFactory(QQmlEngine* qmlEngine, QJSEngine* jsEngine) \ + { \ + Q_UNUSED(jsEngine) \ + Q_UNUSED(qmlEngine) \ + QObject* ret = &instance(); \ + QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership); \ + return ret; \ + } \ + static void registerQmlModule(const char* uri, const int majorVersion, const int minorVersion, const char* name) \ + { \ + qmlRegisterSingletonType(uri, majorVersion, minorVersion, name, &CLASS::qmlSingletonFactory); \ + } + +class _test_QmlSingleton_ : public QObject { + Q_OBJECT + QML_SINGLETON_IMPL(_test_QmlSingleton_) +}; diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h index 0448a21a..53eda37b 100644 --- a/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h @@ -49,7 +49,9 @@ #include #include #include +#include #include +#include namespace ScreenPlayUtil { #if defined(Q_OS_WIN) @@ -116,4 +118,5 @@ QStringList getAvailableFillModes(); bool isWallpaper(const ScreenPlay::InstalledType::InstalledType type); bool isWidget(const ScreenPlay::InstalledType::InstalledType type); std::optional> parseStringToIntegerList(const QString string); +float roundDecimalPlaces(const float number); } diff --git a/ScreenPlayUtil/src/util.cpp b/ScreenPlayUtil/src/util.cpp index 339c5a10..e2718095 100644 --- a/ScreenPlayUtil/src/util.cpp +++ b/ScreenPlayUtil/src/util.cpp @@ -394,4 +394,10 @@ std::optional> parseStringToIntegerList(const QString string) return list; } +float roundDecimalPlaces(const float number) +{ + float big = number * 100.0; + return std::ceil(big * 0.01); +} + } diff --git a/ScreenPlayWallpaper/CMakeLists.txt b/ScreenPlayWallpaper/CMakeLists.txt index f3ea021c..3c5ccb85 100644 --- a/ScreenPlayWallpaper/CMakeLists.txt +++ b/ScreenPlayWallpaper/CMakeLists.txt @@ -51,6 +51,8 @@ qt_add_qml_module( ${PROJECT_NAME} VERSION 1.0 + OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/bin/${PROJECT_NAME} QML_FILES ${QML}) @@ -58,6 +60,8 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE ScreenPlaySDK ScreenPlayUtil + ScreenPlayWeatherplugin + ScreenPlaySysInfoplugin Qt6::Quick Qt6::Gui Qt6::Widgets diff --git a/ScreenPlayWallpaper/main.cpp b/ScreenPlayWallpaper/main.cpp index 899fe96d..4b39b904 100644 --- a/ScreenPlayWallpaper/main.cpp +++ b/ScreenPlayWallpaper/main.cpp @@ -15,6 +15,10 @@ #include "src/macwindow.h" #endif + +Q_IMPORT_QML_PLUGIN(ScreenPlayWeatherPlugin) +Q_IMPORT_QML_PLUGIN(ScreenPlaySysInfoPlugin) + int main(int argc, char* argv[]) { QApplication::setAttribute(Qt::AA_ShareOpenGLContexts); diff --git a/ScreenPlayWeather/CMakeLists.txt b/ScreenPlayWeather/CMakeLists.txt new file mode 100644 index 00000000..a1a8f0a7 --- /dev/null +++ b/ScreenPlayWeather/CMakeLists.txt @@ -0,0 +1,49 @@ +project( + ScreenPlayWeather + VERSION 0.1 + LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_AUTOMOC ON) + +find_package( + Qt6 6.2 + COMPONENTS Core Quick + REQUIRED) + +# Because this is a plugin, we need this for testing and development. This can be disabled when using the plugin in your project directly. +option(tst_ScreenPlayWeather "Builds TextProject" ON) + +set(QML # cmake-format: sortable + src/TestMain.qml) + +set(QML_PLUGIN_SOURCES # cmake-format: sortable + src/screenplayweather.cpp) + +set(QML_PLUGIN_HEADER # cmake-format: sortable + src/screenplayweather.h src/day.h) + +qt_add_library(${PROJECT_NAME} STATIC) +target_link_libraries(${PROJECT_NAME} PUBLIC ScreenPlayUtil) +target_include_directories(${PROJECT_NAME} PUBLIC src/) + +qt_add_qml_module( + ${PROJECT_NAME} + URI + ${PROJECT_NAME} + OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/bin/${PROJECT_NAME} + VERSION + 1.0 + QML_FILES + ${QML} + SOURCES + ${QML_PLUGIN_SOURCES} + ${QML_PLUGIN_HEADER}) + +if(${tst_ScreenPlayWeather}) + qt_add_executable(tst_ScreenPlayWeather src/TestMain.cpp) + target_link_libraries(tst_ScreenPlayWeather PRIVATE Qt6::Quick ${PROJECT_NAME}plugin) + target_compile_definitions(tst_ScreenPlayWeather PRIVATE $<$,$>:QT_QML_DEBUG>) +endif() diff --git a/ScreenPlayWeather/Readme.md b/ScreenPlayWeather/Readme.md new file mode 100644 index 00000000..5e8b1536 --- /dev/null +++ b/ScreenPlayWeather/Readme.md @@ -0,0 +1 @@ +https://open-meteo.com/en/docs diff --git a/ScreenPlayWeather/src/TestMain.cpp b/ScreenPlayWeather/src/TestMain.cpp new file mode 100644 index 00000000..8f3c452c --- /dev/null +++ b/ScreenPlayWeather/src/TestMain.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +Q_IMPORT_QML_PLUGIN(ScreenPlayWeatherPlugin) + +int main(int argc, char* argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + // The first subfolder is the libraryName followed by the regular + // folder strucutre: LibararyName/Subfolder + const QUrl url(u"qrc:/ScreenPlayWeather/src/TestMain.qml"_qs); + QObject::connect( + &engine, &QQmlApplicationEngine::objectCreated, + &app, [url](QObject* obj, const QUrl& objUrl) { + if (!obj && url == objUrl) + QCoreApplication::exit(-1); + }, + Qt::QueuedConnection); + engine.load(url); + + return app.exec(); +} diff --git a/ScreenPlayWeather/src/TestMain.qml b/ScreenPlayWeather/src/TestMain.qml new file mode 100644 index 00000000..b111a25d --- /dev/null +++ b/ScreenPlayWeather/src/TestMain.qml @@ -0,0 +1,96 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Controls.Material +import ScreenPlayWeather 1.0 + +Window { + id: root + width: 1366 + height: 768 + visible: true + title: qsTr("ScreenPlayWeather") + + ScreenPlayWeather { + id: weather + city: "Friedrichshafen" + onReady: { + + rp.model = weather.days + print("onReady" ,weather.days.count) +// for (var i = 0; i < rp.count; i++) { +// rp.itemAt(i).day = weather.getDay(i) +// } + } + } + ColumnLayout { + anchors.fill: parent + anchors.margins: 20 + TextField { + Layout.alignment: Qt.AlignHCenter + onEditingFinished: weather.setCity(text) + text: "Friedrichshafen" + } + Text { + Layout.alignment: Qt.AlignHCenter + text: "longtitude: " + weather.longtitude + " - latitude: " + + weather.latitude + " - elevation: " + weather.elevation + + "m - population: " + weather.population + } + + RowLayout { + Layout.alignment: Qt.AlignHCenter + Repeater { + id: rp + onCountChanged: print(count) + ColumnLayout { + id: cl + spacing: 20 + Text { + horizontalAlignment: Text.AlignHCenter + text: day + "\nday" + } + Text { + horizontalAlignment: Text.AlignHCenter + text: dateTime + "\ndateTime" + } + Text { + horizontalAlignment: Text.AlignHCenter + text: sunrise + "\nsunrise" + } + Text { + horizontalAlignment: Text.AlignHCenter + text: sunset + "\nsunset" + } + Text { + horizontalAlignment: Text.AlignHCenter + text: weatherCode + "\nweatherCode" + } + Text { + horizontalAlignment: Text.AlignHCenter + text:temperature_2m_min + "\ntemperature_2m_min" + } + Text { + horizontalAlignment: Text.AlignHCenter + text: temperature_2m_max + "\ntemperature_2m_max" + } + Text { + horizontalAlignment: Text.AlignHCenter + text: precipitationHours + "\nprecipitationHours" + } + Text { + horizontalAlignment: Text.AlignHCenter + text: precipitationSum + "\nprecipitationSum" + } + } + } + } + Button { + text: "getDay" + onClicked: { + var day = weather.getDay(1) + print("weatherCode:", day.weatherCode, day.precipitationSum) + } + } + } +} diff --git a/ScreenPlayWeather/src/day.h b/ScreenPlayWeather/src/day.h new file mode 100644 index 00000000..11e8fe8f --- /dev/null +++ b/ScreenPlayWeather/src/day.h @@ -0,0 +1,20 @@ +#pragma once +#include "ScreenPlayUtil/PropertyHelpers.h" +#include +#include +#include + +class Day : public QObject { + Q_OBJECT + QML_ELEMENT +public: + W_PROPERTY(int, day) + W_PROPERTY(QDateTime, dateTime) + W_PROPERTY(QDateTime, sunrise) + W_PROPERTY(QDateTime, sunset) + W_PROPERTY_DEFAULT(int, weatherCode, 0) + W_PROPERTY_DEFAULT(float, temperature_2m_min, 0.0f) + W_PROPERTY_DEFAULT(float, temperature_2m_max, 0.0f) + W_PROPERTY_DEFAULT(int, precipitationHours, 0) + W_PROPERTY_DEFAULT(float, precipitationSum, 0.0f) +}; diff --git a/ScreenPlayWeather/src/screenplayweather.cpp b/ScreenPlayWeather/src/screenplayweather.cpp new file mode 100644 index 00000000..e1c61300 --- /dev/null +++ b/ScreenPlayWeather/src/screenplayweather.cpp @@ -0,0 +1,145 @@ +#include "screenplayweather.h" + +#include "ScreenPlayUtil/util.h" +#include +#include +#include +#include +#include + +ScreenPlayWeather::ScreenPlayWeather() + : m_days(this) +{ + + QObject::connect(this, &ScreenPlayWeather::cityChanged, this, &ScreenPlayWeather::updateLatitudeLongtitude); + QObject::connect(this, &ScreenPlayWeather::latitudeLongtitudeChanged, this, &ScreenPlayWeather::update); +} + +void ScreenPlayWeather::updateLatitudeLongtitude(const QString& city) +{ + auto request = defaultRequest(); + QUrl url = m_geocoding_open_metro_v1 + "search"; + QUrlQuery parameter; + parameter.addQueryItem("name", city); + url.setQuery(parameter); + request.setUrl(url); + auto* reply = m_networkAccessManager.get(request); + + QObject::connect(reply, &QNetworkReply::readyRead, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (data.size() <= 0) + return; + + const auto msgOpt = ScreenPlayUtil::parseQByteArrayToQJsonObject(data); + if (!msgOpt.has_value()) + return; + + auto results = msgOpt->value("results").toArray(); + if (results.size() == 0) + return; + + QJsonObject result = results.first().toObject(); + if (result.contains("latitude") && result.contains("longitude")) { + setLatitude(result.value("latitude").toDouble()); + setLongtitude(result.value("longitude").toDouble()); + emit latitudeLongtitudeChanged(); + } + + if (result.contains("elevation")) + setElevation(result.value("elevation").toInt()); + if (result.contains("population")) + setPopulation(result.value("population").toInt()); + }); + QObject::connect(reply, &QNetworkReply::finished, this, []() { qInfo() << "finished!"; }); + QObject::connect(reply, &QNetworkReply::errorOccurred, this, []() { qInfo() << "errorOccurred!"; }); +} + +void ScreenPlayWeather::update() +{ + auto request = defaultRequest(); + const QString timezone = "Europe%2FLondon"; + const QString temperature_unit = QVariant::fromValue(m_temperatureUnit).toString().toLower(); + QString query = QString( + "forecast?latitude=%1&" + "longitude=%2&" + "hourly=temperature_2m&" + "daily=weathercode," + "temperature_2m_max," + "temperature_2m_min," + "sunrise,sunset," + "precipitation_sum," + "precipitation_hours&" + "temperature_unit=celsius&" + "timezone=%3") + .arg(m_latitude) + .arg(m_longtitude) + .arg(timezone); + + QUrl url = m_weather_open_metro_v1 + query; + request.setUrl(url); + qInfo() << url; + auto* reply = m_networkAccessManager.get(request); + + QObject::connect(reply, &QNetworkReply::readyRead, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (data.size() <= 0) + return; + + const auto msgOpt = ScreenPlayUtil::parseQByteArrayToQJsonObject(data); + if (!msgOpt.has_value()) + return; + + if (msgOpt->contains("error")) { + qWarning() << msgOpt->value("reason").toString(); + return; + } + + const auto daily = msgOpt->value("daily").toObject(); + + const auto sunrise = daily.value("sunrise").toArray(); + const auto sunset = daily.value("sunset").toArray(); + const auto time = daily.value("time").toArray(); + const auto weathercode = daily.value("weathercode").toArray(); + const auto temperature_2m_min = daily.value("temperature_2m_min").toArray(); + const auto temperature_2m_max = daily.value("temperature_2m_max").toArray(); + const auto precipitation_hours = daily.value("precipitation_hours").toArray(); + const auto precipitation_sum = daily.value("precipitation_sum").toArray(); + + for (int i = 0; i < time.size(); ++i) { + auto day = new Day(); + day->set_day(i); + day->set_sunrise(QDateTime::fromString(sunrise.at(i).toString(), m_dataTimeFormat)); + day->set_sunset(QDateTime::fromString(sunset.at(i).toString(), m_dataTimeFormat)); + day->set_dateTime(QDateTime::fromString(time.at(i).toString(), m_dataTimeFormat)); + day->set_weatherCode(weathercode.at(i).toInt()); + day->set_temperature_2m_min(ScreenPlayUtil::roundDecimalPlaces(temperature_2m_min.at(i).toDouble())); + day->set_temperature_2m_max(ScreenPlayUtil::roundDecimalPlaces(temperature_2m_max.at(i).toDouble())); + day->set_precipitationHours(precipitation_hours.at(i).toInt()); + day->set_precipitationSum(ScreenPlayUtil::roundDecimalPlaces(precipitation_sum.at(i).toDouble())); + m_days.append(&m_days, std::move(day)); + } + const auto hourly = msgOpt->value("hourly").toObject(); + emit ready(); + }); + QObject::connect(reply, &QNetworkReply::finished, this, []() { qInfo() << "finished!"; }); + QObject::connect(reply, &QNetworkReply::errorOccurred, this, []() { qInfo() << "errorOccurred!"; }); +} + +Day* ScreenPlayWeather::getDay(const int index) const +{ + // if ((index >= m_days.count()) || index < 0) { + // qWarning() << "Invalid getDay index: " << index; + // return nullptr; + // } + + return nullptr; // m_days.at(index); +} + +QNetworkRequest ScreenPlayWeather::defaultRequest() const +{ + QNetworkRequest request; + const QString userAgent = "ScreenPlay"; + request.setHeader(QNetworkRequest::KnownHeaders::UserAgentHeader, userAgent); + request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json"); + return request; +} diff --git a/ScreenPlayWeather/src/screenplayweather.h b/ScreenPlayWeather/src/screenplayweather.h new file mode 100644 index 00000000..355f9cd6 --- /dev/null +++ b/ScreenPlayWeather/src/screenplayweather.h @@ -0,0 +1,115 @@ +#pragma once + +#include "ScreenPlayUtil/ListPropertyHelper.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "day.h" + +class ScreenPlayWeather : public QObject { + Q_OBJECT + + Q_PROPERTY(double latitude READ latitude WRITE setLatitude NOTIFY latitudeChanged) + Q_PROPERTY(double longtitude READ longtitude WRITE setLongtitude NOTIFY longtitudeChanged) + Q_PROPERTY(QString city READ city WRITE setCity NOTIFY cityChanged) + Q_PROPERTY(int elevation READ elevation WRITE setElevation NOTIFY elevationChanged) + Q_PROPERTY(int population READ population WRITE setPopulation NOTIFY populationChanged) + QML_ELEMENT + + LIST_PROPERTY(Day, days) + +public: + explicit ScreenPlayWeather(); + + double latitude() const { return m_latitude; } + double longtitude() const { return m_longtitude; } + const QString& city() const { return m_city; } + int elevation() const { return m_elevation; } + int population() const { return m_population; } + + enum class TemperatureUnit { + Celsius, + Fahrenheit + }; + +public slots: + Day* getDay(const int index) const; + + void setLatitude(double latitude) + { + if (qFuzzyCompare(m_latitude, latitude)) + return; + m_latitude = latitude; + emit latitudeChanged(m_latitude); + } + + void setLongtitude(double longtitude) + { + if (qFuzzyCompare(m_longtitude, longtitude)) + return; + m_longtitude = longtitude; + emit longtitudeChanged(m_longtitude); + } + + void setCity(const QString& city) + { + if (m_city == city) + return; + m_city = city; + emit cityChanged(m_city); + } + + void setElevation(int elevation) + { + if (m_elevation == elevation) + return; + m_elevation = elevation; + emit elevationChanged(m_elevation); + } + + void setPopulation(int population) + { + if (m_population == population) + return; + m_population = population; + emit populationChanged(m_population); + } + +private slots: + void updateLatitudeLongtitude(const QString& city); + void update(); + +signals: + void latitudeChanged(double latitude); + void longtitudeChanged(double longtitude); + void cityChanged(const QString& city); + void latitudeLongtitudeChanged(); + void elevationChanged(int elevation); + void populationChanged(int population); + void ready(); + +private: + QNetworkRequest defaultRequest() const; + +private: + QNetworkAccessManager m_networkAccessManager; + double m_latitude = 0.0l; + double m_longtitude = 0.0l; + QString m_city; + const QString m_geocoding_open_metro_v1 = "https://geocoding-api.open-meteo.com/v1/"; + const QString m_weather_open_metro_v1 = "https://api.open-meteo.com/v1/"; + const QString m_dataTimeFormat = "yyyy-MM-ddTmm:ss"; + int m_elevation; + int m_population; + int FORCAST_DAYS = 6; + TemperatureUnit m_temperatureUnit = TemperatureUnit::Celsius; +}; diff --git a/ScreenPlayWidget/CMakeLists.txt b/ScreenPlayWidget/CMakeLists.txt index 9f708e83..06813aaf 100644 --- a/ScreenPlayWidget/CMakeLists.txt +++ b/ScreenPlayWidget/CMakeLists.txt @@ -34,6 +34,8 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE ScreenPlaySDK ScreenPlayUtil + ScreenPlayWeatherplugin + ScreenPlaySysInfoplugin Qt6::Quick Qt6::Gui Qt6::Widgets @@ -49,6 +51,8 @@ qt_add_qml_module( ${PROJECT_NAME} VERSION 1.0 + OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/bin/${PROJECT_NAME} QML_FILES ${QML}) diff --git a/ScreenPlayWidget/main.cpp b/ScreenPlayWidget/main.cpp index be3c5418..c53f44e8 100644 --- a/ScreenPlayWidget/main.cpp +++ b/ScreenPlayWidget/main.cpp @@ -5,6 +5,9 @@ #include "src/widgetwindow.h" +Q_IMPORT_QML_PLUGIN(ScreenPlayWeatherPlugin) +Q_IMPORT_QML_PLUGIN(ScreenPlaySysInfoPlugin) + int main(int argc, char* argv[]) { QtWebEngineQuick::initialize(); diff --git a/ScreenPlayWorkshop/CMakeLists.txt b/ScreenPlayWorkshop/CMakeLists.txt index 00211656..d2394756 100644 --- a/ScreenPlayWorkshop/CMakeLists.txt +++ b/ScreenPlayWorkshop/CMakeLists.txt @@ -64,7 +64,9 @@ qt_add_qml_module( ${SOURCES} ${HEADER} VERSION - 1.0) + 1.0 + OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/bin/${PROJECT_NAME}) if(${SCREENPLAY_STEAM}) if(APPLE) diff --git a/Tools/CMakeLists.txt b/Tools/CMakeLists.txt index 164ecaaa..7cbb9ccf 100644 --- a/Tools/CMakeLists.txt +++ b/Tools/CMakeLists.txt @@ -3,8 +3,7 @@ project(Tools LANGUAGES CXX) file(GLOB PYTHON *.py) set(FILES # cmake-format: sortable - Installer/package.xml - Installer/installscript.qs) + Installer/package.xml Installer/installscript.qs) add_custom_target( ${PROJECT_NAME}