1
0
mirror of https://gitlab.com/kelteseth/ScreenPlay.git synced 2024-11-25 04:02:50 +01:00

Change all plugins to be QML_ELEMENT

Add ScreenPlayWeather
This commit is contained in:
Elias Steurer 2022-02-20 17:55:26 +01:00
parent 1d81117f6e
commit fb5d6581ec
61 changed files with 1421 additions and 181 deletions

View File

@ -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}

View File

@ -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)

View File

@ -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()

10
Common/CMakeLists.txt Normal file
View File

@ -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)

View File

@ -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 $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
qt_add_library(ScreenPlayQml STATIC)
qt_add_qml_module(
ScreenPlayQml
OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/bin/ScreenPlayQml
URI
ScreenPlayQml
VERSION

View File

@ -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 $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>: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 $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
endif()

View File

@ -1,14 +0,0 @@
<RCC>
<qresource prefix="/">
<file>lightning.frag</file>
<file>lightning.vert</file>
<file>water.frag</file>
<file>water.vert</file>
<file>assets/Shadertoy_Bayer.png</file>
<file>assets/Shadertoy_Gray_Noise_Medium.png</file>
<file>assets/Shadertoy_Lichen.jpg</file>
</qresource>
<qresource prefix="/ShaderWrapper">
<file>ShadertoyShader.qml</file>
</qresource>
</RCC>

View File

@ -1,18 +0,0 @@
#include "screenplayshader_plugin.h"
#include <QQmlEngine>
#include <QUrl>
#include <qqml.h>
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<ShaderLibrary>(uri, 1, 0, "ShaderLibrary", ScreenPlayShaderLibrarySingleton);
}

View File

@ -1,15 +0,0 @@
#pragma once
#include <QQmlExtensionPlugin>
#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;
};

View File

@ -0,0 +1,26 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QVersionNumber>
#include <QtQml/qqmlextensionplugin.h>
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();
}

View File

@ -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")
}

View File

@ -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<Shader>(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<Shader>(waterVertFile.readAll(), waterFragFile.readAll());
}

View File

@ -4,6 +4,7 @@
#include <QQuickItem>
#include <QString>
#include <memory>
#include <QQmlEngine>
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);

View File

@ -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 $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>: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 $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
endif()

View File

@ -1,18 +0,0 @@
#include "screenplaysysinfo_plugin.h"
#include "sysinfo.h"
#include <qmetatype.h>
#include <qqml.h>
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<SysInfo>(uri, 1, 0, "SysInfo", ScreenPlaySysInfoSingleton);
}

View File

@ -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 <QQmlExtensionPlugin>
class ScreenPlaySysInfoPlugin : public QQmlExtensionPlugin {
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char* uri);
};

View File

@ -0,0 +1,26 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QVersionNumber>
#include <QtQml/qqmlextensionplugin.h>
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();
}

View File

@ -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
}
}
}
}
}
}

View File

@ -38,6 +38,7 @@
#include <QObject>
#include <QString>
#include <QTimer>
#include <QQmlEngine>
#ifdef Q_OS_WIN
#include <qt_windows.h>
@ -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);

View File

@ -1,5 +1,6 @@
#pragma once
#include <QObject>
#include <QQmlEngine>
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);

View File

@ -37,6 +37,7 @@
#include <QDebug>
#include <QObject>
#include <QTimer>
#include <QQmlEngine>
#ifdef Q_OS_WIN
#include <qt_windows.h>
@ -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);

View File

@ -39,9 +39,11 @@
#include <QStorageInfo>
#include <QTimer>
#include <QVector>
#include <QQmlEngine>
class Storage : public QAbstractListModel {
Q_OBJECT
QML_ELEMENT
public:
explicit Storage(QObject* parent = nullptr);

View File

@ -34,6 +34,7 @@
#pragma once
#include <QQmlEngine>
#include <QQuickItem>
#include <memory>
@ -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);

View File

@ -1,15 +1,16 @@
#pragma once
#include <QObject>
#include <QQmlEngine>
#include <QTimer>
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);

View File

@ -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

View File

@ -0,0 +1,76 @@
#pragma once
#include <QObject>
#include "HelpersCommon.h"
#define AUTO_GETTER(type, name) \
public: \
CheapestType<type>::type_def MAKE_GETTER_NAME(name)() const { return m_##name; }
#define AUTO_SETTER(type, name) \
public: \
void set_##name(CheapestType<type>::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)
};

View File

@ -0,0 +1,63 @@
#pragma once
#include <QObject>
#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"))
};

View File

@ -0,0 +1,40 @@
#pragma once
#include <QMetaEnum>
#include <QMetaObject>
#include <QObject>
#include <QQmlEngine>
#include <QString>
#include <QtQml/QtQml>
#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<NAME>(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

View File

@ -0,0 +1,73 @@
#pragma once
#include <QtGlobal>
// NOTE : SFINAE trickery to find which type is the cheapest between T and const T &
template <typename T>
struct CheapestType {
using type_def = const T&;
};
template <>
struct CheapestType<bool> {
using type_def = bool;
};
template <>
struct CheapestType<quint8> {
using type_def = quint8;
};
template <>
struct CheapestType<quint16> {
using type_def = quint16;
};
template <>
struct CheapestType<quint32> {
using type_def = quint32;
};
template <>
struct CheapestType<quint64> {
using type_def = quint64;
};
template <>
struct CheapestType<qint8> {
using type_def = qint8;
};
template <>
struct CheapestType<qint16> {
using type_def = qint16;
};
template <>
struct CheapestType<qint32> {
using type_def = qint32;
};
template <>
struct CheapestType<qint64> {
using type_def = qint64;
};
template <>
struct CheapestType<float> {
using type_def = float;
};
template <>
struct CheapestType<double> {
using type_def = double;
};
template <typename T>
struct CheapestType<T*> {
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();

View File

@ -0,0 +1,65 @@
#pragma once
#include <QQmlListProperty>
#include <QVector>
#include "HelpersCommon.h"
template <class ObjType>
class QQmlSmartListWrapper : public QQmlListProperty<ObjType> {
public:
typedef QVector<ObjType*> CppListType;
typedef QQmlListProperty<ObjType> QmlListPropertyType;
typedef QQmlSmartListWrapper<ObjType> 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<CppListType*>(prop->data)->count(); }
static void callbackClear(QmlListPropertyType* prop) { static_cast<CppListType*>(prop->data)->clear(); }
static void callbackAppend(QmlListPropertyType* prop, ObjType* obj)
{
static_cast<CppListType*>(prop->data)->append(obj);
}
static ObjType* callbackAt(QmlListPropertyType* prop, qsizetype idx)
{
return static_cast<CppListType*>(prop->data)->at(idx);
}
private:
CppListType m_items;
};
#define LIST_PROPERTY(TYPE, NAME) \
private: \
Q_PROPERTY(QQmlListProperty<TYPE> NAME READ MAKE_GETTER_NAME(NAME) CONSTANT) \
public: \
const QQmlSmartListWrapper<TYPE>& MAKE_GETTER_NAME(NAME)() const { return m_##NAME; } \
\
private: \
QQmlSmartListWrapper<TYPE> m_##NAME;

View File

@ -0,0 +1,66 @@
#pragma once
#include <QObject>
#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)
};

View File

@ -0,0 +1,126 @@
#pragma once
#include <QObject>
#include <memory>
#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<type>, name) \
SMART_PTR_GETTER(type, name) \
SMART_PTR_SETTER(std::unique_ptr<type>&, 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<type>, name, std::make_unique<type>()) \
SMART_PTR_GETTER(type, name) \
SMART_PTR_SETTER(std::unique_ptr<type>&, name) \
NOTIFIER(name) \
private:
#define SHARED_PTR_PROPERTY(type, name) \
protected: \
Q_PROPERTY(type* name READ name NOTIFY name##Changed) \
\
MEMBER(std::shared_ptr<type>, name) \
SMART_PTR_GETTER(type, name) \
SMART_PTR_SETTER(std::unique_ptr<type>&, 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<type>, name, std::make_shared<type>()) \
SMART_PTR_GETTER(type, name) \
SMART_PTR_SETTER(std::shared_ptr<type>, 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)
};

View File

@ -0,0 +1,2 @@
# Qt Super-Macros
Based on: https://github.com/DoozyX/qt-property-macros

View File

@ -0,0 +1,31 @@
#pragma once
#include <QJSEngine>
#include <QObject>
#include <QQmlEngine>
#include <qqml.h>
#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<CLASS>(uri, majorVersion, minorVersion, name, &CLASS::qmlSingletonFactory); \
}
class _test_QmlSingleton_ : public QObject {
Q_OBJECT
QML_SINGLETON_IMPL(_test_QmlSingleton_)
};

View File

@ -49,7 +49,9 @@
#include <QJsonObject>
#include <QString>
#include <QVersionNumber>
#include <QMetaEnum>
#include <optional>
#include <cmath>
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<QVector<int>> parseStringToIntegerList(const QString string);
float roundDecimalPlaces(const float number);
}

View File

@ -394,4 +394,10 @@ std::optional<QVector<int>> parseStringToIntegerList(const QString string)
return list;
}
float roundDecimalPlaces(const float number)
{
float big = number * 100.0;
return std::ceil(big * 0.01);
}
}

View File

@ -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

View File

@ -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);

View File

@ -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 $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
endif()

View File

@ -0,0 +1 @@
https://open-meteo.com/en/docs

View File

@ -0,0 +1,26 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QVersionNumber>
#include <QtQml/qqmlextensionplugin.h>
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();
}

View File

@ -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)
}
}
}
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "ScreenPlayUtil/PropertyHelpers.h"
#include <QDateTime>
#include <QObject>
#include <QQmlEngine>
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)
};

View File

@ -0,0 +1,145 @@
#include "screenplayweather.h"
#include "ScreenPlayUtil/util.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrlQuery>
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;
}

View File

@ -0,0 +1,115 @@
#pragma once
#include "ScreenPlayUtil/ListPropertyHelper.h"
#include <QDebug>
#include <QObject>
#include <QQmlEngine>
#include <QSettings>
#include <QSize>
#include <QString>
#include <QUrl>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <memory>
#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;
};

View File

@ -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})

View File

@ -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();

View File

@ -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)

View File

@ -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}