1
0
mirror of https://gitlab.com/kelteseth/ScreenPlay.git synced 2024-09-15 06:52:34 +02:00
This commit is contained in:
Elias Steurer 2021-02-04 16:47:52 +01:00
commit 799a795e92
53 changed files with 776 additions and 556 deletions

View File

@ -26,7 +26,12 @@ if(APPLE)
set(THREADS_PREFER_PTHREAD_FLAG ON)
endif()
set(VCPKG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../ScreenPlay-vcpkg")
if(${SCREENPLAY_FOSS})
set(VCPKG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../ScreenPlay-vcpkg")
else()
set(VCPKG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../ScreenPlay-vcpkg")
endif()
set(VCPKG_INSTALLED_PATH "${VCPKG_PATH}/installed/${VCPKG_ARCH}")
set(QT_TELEMTRY_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/Common/qt-google-analytics/)
@ -68,6 +73,7 @@ add_subdirectory(ScreenPlaySDK)
add_subdirectory(ScreenPlayShader)
add_subdirectory(ScreenPlayWallpaper)
add_subdirectory(ScreenPlayWidget)
add_subdirectory(ScreenPlayUtil)
if(WIN32)
add_subdirectory(ScreenPlaySysInfo)

View File

@ -34,6 +34,12 @@
<li>The main ScreenPlay App UI with Create, Installed, Community and Settings.</li>
</ul>
</li>
<li>
<strong>ScreenPlayUtil</strong>
<ul>
<li>Contains functions like json project file loading/saving and enums like FillMode and ContentType that is needed by all projects.</li>
</ul>
</li>
<li>
<strong>ScreenPlaySDK</strong>
<ul>

View File

@ -10,7 +10,10 @@ ScreenPlay [![pipeline status](https://gitlab.com/kelteseth/ScreenPlay/badges/ma
Dev. Docs [![pipeline status](https://gitlab.com/kelteseth/ScreenPlayDeveloperDocs/badges/master/pipeline.svg)](https://gitlab.com/kelteseth/ScreenPlayDeveloperDocs/-/commits/master) <br><br>
<a href="https://twitter.com/kelteseth">![Twitter Follow](https://img.shields.io/twitter/follow/kelteseth?style=for-the-badge)</a>
<a href="https://www.reddit.com/r/ScreenPlayApp/">![Subreddit subscribers](https://img.shields.io/reddit/subreddit-subscribers/screenplayapp?style=for-the-badge)</a>
<br><br>
User Chat (Discord)
<a href="https://discord.com/invite/rUvjNSV?utm_source=Discord%20Widget&utm_medium=Connect">![Discord](https://img.shields.io/discord/516635043435773970?style=for-the-badge)</a>
Developer Chat [![Gitter](https://badges.gitter.im/ScreenPlayApp/community.svg)](https://gitter.im/ScreenPlayApp/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)

View File

@ -1,7 +1,6 @@
project(ScreenPlay LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)
@ -56,7 +55,6 @@ set(headers
src/settings.h
src/profilelistmodel.h
src/profile.h
src/projectfile.h
src/installedlistfilter.h
src/projectsettingslistmodel.h
src/screenplaymanager.h
@ -110,6 +108,7 @@ target_link_libraries(
Qt5::WebEngine
Qt5::WebSockets
ScreenPlaySDK
ScreenPlayUtil
benchmark::benchmark
benchmark::benchmark_main
doctest::doctest)

View File

@ -1,13 +0,0 @@
{
"Screens":
[
{ "ScreenName1": {"id": "abc", "fillmode": "stretch"} },
{ "ScreenName2": {"id": "xyz"} }
],
"Widgets":
[
{ "WidgetName1": {"id": "abc"} },
{ "WidgetName2": {"id": "aaa"} }
],
"Plays": []
}

View File

@ -48,8 +48,7 @@
#include <QtQml>
#include <QtWebEngine>
#include <memory>
#include "ganalytics.h"
#include "src/create.h"
#include "src/globalvariables.h"
#include "src/installedlistfilter.h"
@ -61,7 +60,8 @@
#include "src/util.h"
#include "src/wizards.h"
#include "ganalytics.h"
#include <memory>
#ifdef Q_OS_WIN
#include <sentry.h>
#endif

View File

@ -76,6 +76,7 @@ int main(int argc, char* argv[])
ScreenPlay::App app;
if (app.m_isAnotherScreenPlayInstanceRunning) {
return 0;
} else {
@ -85,6 +86,7 @@ int main(int argc, char* argv[])
#ifdef Q_OS_WIN
sentry_shutdown();
#endif
return status;
}
}

View File

@ -167,6 +167,7 @@ Item {
}
}
property bool isDragging: false
property bool isScrolling: gridView.verticalVelocity != 0
onDragStarted: isDragging = true
onDragEnded: isDragging = false
onContentYChanged: {
@ -193,6 +194,7 @@ Item {
absoluteStoragePath: m_absoluteStoragePath
publishedFileID: m_publishedFileID
itemIndex: index
isScrolling: gridView.isScrolling
onOpenContextMenu: {
// Set the menu to the current item informations
contextMenu.publishedFileID = delegate.publishedFileID

View File

@ -18,6 +18,7 @@ Item {
property var type: InstalledType.Unknown
property var publishedFileID: 0
property int itemIndex
property bool isScrolling: false
signal openContextMenu(point position)
@ -157,7 +158,7 @@ Item {
MouseArea {
anchors.fill: parent
hoverEnabled: true
hoverEnabled: !root.isScrolling
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onEntered: {

View File

@ -1,6 +1,4 @@
import QtQuick 2.12
import ScreenPlay 1.0
import ScreenPlay.Enums.InstalledType 1.0
Item {
id: root
@ -12,48 +10,31 @@ Item {
property string sourceImage
property string sourceImageGIF
property var type: InstalledType.Unknown
onTypeChanged: {
if (root.sourceImage === "" && root.sourceImageGIF === "") {
image.source = "qrc:/assets/images/missingPreview.png"
return
}
if (root.type === InstalledType.GifWallpaper) {
image.source = Qt.resolvedUrl(
absoluteStoragePath + "/" + root.sourceImageGIF)
print(image.source)
} else {
if (root.sourceImage !== "") {
image.source = Qt.resolvedUrl(
absoluteStoragePath + "/" + root.sourceImage)
}
}
}
function enter() {
if (root.type !== InstalledType.GifWallpaper) {
if (root.sourceImageGIF !== "")
image.source = Qt.resolvedUrl(
absoluteStoragePath + "/" + root.sourceImageGIF)
if (root.sourceImageGIF != "") {
loader_imgGIFPreview.sourceComponent = component_imgGIFPreview
}
image.playing = true
}
function exit() {
image.playing = false
if (root.type !== InstalledType.GifWallpaper) {
image.source = Qt.resolvedUrl(
absoluteStoragePath + "/" + root.sourceImage)
}
root.state = "loaded"
loader_imgGIFPreview.sourceComponent = null
}
AnimatedImage {
Image {
id: image
anchors.fill: parent
asynchronous: true
cache: true
playing: false
fillMode: Image.PreserveAspectCrop
source: {
if (root.sourceImage === "")
return "qrc:/assets/images/missingPreview.png"
return root.screenPreview === "" ? "qrc:/assets/images/missingPreview.png" : Qt.resolvedUrl(
absoluteStoragePath + "/" + root.sourceImage)
}
onStatusChanged: {
if (image.status === Image.Ready) {
@ -64,4 +45,62 @@ Item {
}
}
}
Component {
id: component_imgGIFPreview
AnimatedImage {
id: imgGIFPreview
asynchronous: true
playing: true
source: root.sourceImageGIF
=== "" ? "qrc:/assets/images/missingPreview.png" : Qt.resolvedUrl(
absoluteStoragePath + "/" + root.sourceImageGIF)
fillMode: Image.PreserveAspectCrop
}
}
Loader {
id: loader_imgGIFPreview
anchors.fill: parent
opacity: 0
}
transitions: [
Transition {
from: "loading"
to: "loaded"
OpacityAnimator {
target: image
duration: 300
from: 0
to: 1
easing.type: Easing.OutQuart
}
},
Transition {
from: "hover"
to: "loaded"
OpacityAnimator {
target: loader_imgGIFPreview
duration: 300
from: 1
to: 0
easing.type: Easing.OutQuart
}
},
Transition {
from: "loaded"
to: "hover"
reversible: true
OpacityAnimator {
target: loader_imgGIFPreview
duration: 400
from: 0
to: 1
easing.type: Easing.OutQuart
}
}
]
}

View File

@ -100,12 +100,12 @@ Popup {
id: delegate
focus: true
width: gridView.cellWidth - 30
customTitle: screenTitle
type: screenType
screenId: screenFolderId
absoluteStoragePath: screenAbsoluteStoragePath
publishedFileID: screenPublishedFileID
preview: screenPreview
customTitle: m_title
type: m_type
screenId: m_folderId
absoluteStoragePath: m_absoluteStoragePath
publishedFileID: m_publishedFileID
preview: m_preview
itemIndex: index
onItemClicked: {
for (let childItem in gridView.contentItem.children) {

View File

@ -21,7 +21,7 @@ Item {
property string absoluteStoragePath: ""
property string screenId: ""
property string preview: ""
property string type: ""
property var type
property bool hasMenuOpen: false
property var publishedFileID: 0
property int itemIndex
@ -103,7 +103,7 @@ Item {
Text {
id: name
text: screenTitle
text: m_title
color: Material.foreground
font.pointSize: 18
font.family: ScreenPlay.settings.font
@ -111,7 +111,7 @@ Item {
}
Text {
text: qsTr("Type: ") + screenType
text: qsTr("Type: ") + m_type
color: Material.foreground
font.family: ScreenPlay.settings.font
}

View File

@ -48,7 +48,7 @@ Create::Create()
void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, const int quality)
{
clearFfmpegOutput();
videoPath = Util::toLocal(videoPath);
videoPath = ScreenPlayUtil::toLocal(videoPath);
const QDir dir(m_globalVariables->localStoragePath().toLocalFile());
@ -99,8 +99,8 @@ void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, c
*/
void Create::saveWallpaper(QString title, QString description, QString filePath, QString previewImagePath, QString youtube, Create::VideoCodec codec, QVector<QString> tags)
{
filePath = Util::toLocal(filePath);
previewImagePath = Util::toLocal(previewImagePath);
filePath = ScreenPlayUtil::toLocal(filePath);
previewImagePath = ScreenPlayUtil::toLocal(previewImagePath);
emit createWallpaperStateChanged(CreateImportVideo::ImportVideoState::CopyFiles);
@ -146,7 +146,7 @@ void Create::saveWallpaper(QString title, QString description, QString filePath,
obj.insert("preview", previewImageFile.exists() ? previewImageFile.fileName() : "preview.jpg");
obj.insert("previewThumbnail", "previewThumbnail.jpg");
obj.insert("type", "videoWallpaper");
obj.insert("tags", Util::fillArray(tags));
obj.insert("tags", ScreenPlayUtil::fillArray(tags));
QFile audioFile { m_workingDir + "/audio.mp3" };
if (audioFile.exists() && audioFile.size() > 0) {

View File

@ -56,6 +56,7 @@
#include <memory>
#include "ScreenPlayUtil/util.h"
#include "createimportvideo.h"
#include "globalvariables.h"
#include "util.h"

View File

@ -1,4 +1,5 @@
#include "createimportvideo.h"
#include "ScreenPlayUtil/util.h"
namespace ScreenPlay {
@ -38,8 +39,8 @@ CreateImportVideo::CreateImportVideo(const QString& videoPath, const QString& ex
m_codec = codec;
m_process = std::make_unique<QProcess>(this);
m_ffprobeExecutable = QApplication::applicationDirPath() + "/ffprobe" + Util::executableEnding();
m_ffmpegExecutable = QApplication::applicationDirPath() + "/ffmpeg" + Util::executableEnding();
m_ffprobeExecutable = QApplication::applicationDirPath() + "/ffprobe" + ScreenPlayUtil::executableEnding();
m_ffmpegExecutable = QApplication::applicationDirPath() + "/ffmpeg" + ScreenPlayUtil::executableEnding();
}
/*!
@ -165,7 +166,7 @@ bool CreateImportVideo::createWallpaperInfo()
args.append(m_videoPath);
emit processOutput("ffprobe " + Util::toString(args));
emit processOutput("ffprobe " + ScreenPlayUtil::toString(args));
emit createWallpaperStateChanged(ImportVideoState::AnalyseVideo);
@ -174,7 +175,7 @@ bool CreateImportVideo::createWallpaperInfo()
emit createWallpaperStateChanged(ImportVideoState::AnalyseVideoFinished);
auto obj = Util::parseQByteArrayToQJsonObject(QByteArray::fromStdString(ffmpegOut.toStdString()));
auto obj = ScreenPlayUtil::parseQByteArrayToQJsonObject(QByteArray::fromStdString(ffmpegOut.toStdString()));
if (!obj) {
QString error = ffmpegOut;
@ -386,7 +387,7 @@ bool CreateImportVideo::createWallpaperVideoPreview()
// Disable audio
args.append("-an");
args.append(m_exportPath + "/preview.webm");
emit processOutput("ffmpeg " + Util::toString(args));
emit processOutput("ffmpeg " + ScreenPlayUtil::toString(args));
const QString ffmpegOut = waitForFinished(args);
const QFile previewVideo(m_exportPath + "/preview.webm");
@ -429,7 +430,7 @@ bool CreateImportVideo::createWallpaperGifPreview()
args.append("-filter_complex");
args.append("[0:v] fps=12,scale=w=480:h=-1,split [a][b];[a] palettegen=stats_mode=single [p];[b][p] paletteuse=new=1");
args.append(m_exportPath + "/preview.gif");
emit processOutput("ffmpeg " + Util::toString(args));
emit processOutput("ffmpeg " + ScreenPlayUtil::toString(args));
const QString ffmpegOut = waitForFinished(args);
@ -488,7 +489,7 @@ bool CreateImportVideo::createWallpaperImageThumbnailPreview()
}
args.append(m_exportPath + "/previewThumbnail.jpg");
emit processOutput("ffmpeg " + Util::toString(args));
emit processOutput("ffmpeg " + ScreenPlayUtil::toString(args));
const QString ffmpegOut = waitForFinished(args);
if (!ffmpegOut.isEmpty()) {
@ -533,7 +534,7 @@ bool CreateImportVideo::createWallpaperImagePreview()
}
args.append(m_exportPath + "/preview.jpg");
emit processOutput("ffmpeg " + Util::toString(args));
emit processOutput("ffmpeg " + ScreenPlayUtil::toString(args));
const QString ffmpegOut = waitForFinished(args);
if (!ffmpegOut.isEmpty()) {
const QFile previewImg(m_exportPath + "/preview.jpg");

View File

@ -41,84 +41,10 @@
#include <QUrl>
#include <QVersionNumber>
#include "ScreenPlayUtil/contenttypes.h"
namespace ScreenPlay {
/*!
\class ScreenPlay::GlobalVariables
\inmodule ScreenPlay
\brief GlobalVariables.
A header only class used only for storing some global variables like localStoragePath.
*/
namespace SearchType {
Q_NAMESPACE
enum class SearchType {
All,
Text,
Scene, //QML, HTML, Godot, Gif, Website wallpaper
Wallpaper,
Widget,
};
Q_ENUM_NS(SearchType)
}
namespace FillMode {
Q_NAMESPACE
enum class FillMode {
Stretch,
Fill,
Contain,
Cover,
Scale_Down
};
Q_ENUM_NS(FillMode)
}
namespace InstalledType {
Q_NAMESPACE
// When changing the enum, one also needs to change:
// GlobalVariables::getAvailableWallpaper
// GlobalVariables::getAvailableWidgets
// Common/Util.js isWallpaper() and isWidget()
// ScreenPlayWallpaper: BaseWindow::parseWallpaperType()
enum class InstalledType {
Unknown,
//Wallpaper
VideoWallpaper,
QMLWallpaper,
HTMLWallpaper,
GodotWallpaper,
GifWallpaper,
WebsiteWallpaper,
//Widgets
QMLWidget,
HTMLWidget,
};
Q_ENUM_NS(InstalledType)
static bool isWallpaper(const InstalledType type)
{
return (type == InstalledType::VideoWallpaper
|| type == InstalledType::QMLWallpaper
|| type == InstalledType::HTMLWallpaper
|| type == InstalledType::GifWallpaper
|| type == InstalledType::WebsiteWallpaper
|| type == InstalledType::GodotWallpaper);
}
static bool isWidget(const InstalledType type)
{
return (type == InstalledType::QMLWidget || type == InstalledType::HTMLWidget);
}
}
class GlobalVariables : public QObject {
Q_OBJECT
@ -131,30 +57,6 @@ class GlobalVariables : public QObject {
public:
explicit GlobalVariables(QObject* parent = nullptr);
static QStringList getAvailableWallpaper()
{
return {
"qmlWallpaper",
"htmlWallpaper",
"videoWallpaper",
"godotWallpaper",
"gifWallpaper",
"websiteWallpaper"
};
}
static QStringList getAvailableWidgets()
{
return {
"qmlWidget",
"htmlWidget",
};
}
static QStringList getAvailableTypes()
{
return { getAvailableWallpaper() + getAvailableWidgets() };
}
/*!
\property GlobalVariables::localStoragePath
\brief Returns the localStoragePath.

View File

@ -89,7 +89,7 @@ QVariant InstalledListModel::data(const QModelIndex& index, int role) const
if (!index.isValid())
return QVariant();
int row = index.row();
const int row = index.row();
if (row < 0 || row >= m_screenPlayFiles.count()) {
return QVariant();
}
@ -127,8 +127,7 @@ QVariant InstalledListModel::data(const QModelIndex& index, int role) const
*/
QHash<int, QByteArray> InstalledListModel::roleNames() const
{
static const QHash<int, QByteArray> roles {
return {
{ static_cast<int>(ScreenPlayItem::Title), "m_title" },
{ static_cast<int>(ScreenPlayItem::Type), "m_type" },
{ static_cast<int>(ScreenPlayItem::Preview), "m_preview" },
@ -140,7 +139,6 @@ QHash<int, QByteArray> InstalledListModel::roleNames() const
{ static_cast<int>(ScreenPlayItem::Tags), "m_tags" },
{ static_cast<int>(ScreenPlayItem::SearchType), "m_searchType" },
};
return roles;
}
/*!
@ -161,12 +159,12 @@ void InstalledListModel::loadInstalledContent()
QtConcurrent::run([this]() {
QFileInfoList list = QDir(m_globalVariables->localStoragePath().toLocalFile()).entryInfoList(QDir::NoDotAndDotDot | QDir::AllDirs);
QString projectItemPath;
int counter {};
int counter = 0;
for (auto&& item : list) {
for (const auto& item : list) {
projectItemPath = m_globalVariables->localStoragePath().toLocalFile() + "/" + item.baseName() + "/project.json";
if (auto obj = Util::openJsonFileToObject(projectItemPath)) {
if (auto obj = ScreenPlayUtil::openJsonFileToObject(projectItemPath)) {
if (obj->isEmpty())
continue;
@ -174,8 +172,8 @@ void InstalledListModel::loadInstalledContent()
if (!obj->contains("type"))
continue;
if (GlobalVariables::getAvailableTypes().contains(obj->value("type").toString())) {
if (GlobalVariables::getAvailableTypes().contains(obj->value("type").toString(), Qt::CaseInsensitive)) {
if (ScreenPlayUtil::getAvailableTypes().contains(obj->value("type").toString())) {
if (ScreenPlayUtil::getAvailableTypes().contains(obj->value("type").toString(), Qt::CaseInsensitive)) {
emit addInstalledItem(*obj, item.baseName());
}

View File

@ -55,7 +55,7 @@
#include "globalvariables.h"
#include "profilelistmodel.h"
#include "projectfile.h"
#include "ScreenPlayUtil/projectfile.h"
#include "util.h"
#include <memory>

View File

@ -33,6 +33,7 @@
****************************************************************************/
#pragma once
#include <QRect>
#include <QString>
#include <QUrl>

View File

@ -34,7 +34,6 @@
#pragma once
#include "profile.h"
#include <QAbstractListModel>
#include <QDebug>
#include <QDir>
@ -45,6 +44,7 @@
#include <QVector>
#include "globalvariables.h"
#include "profile.h"
#include <memory>

View File

@ -130,7 +130,7 @@ void ScreenPlayManager::createWallpaper(
}
const QString path = QUrl::fromUserInput(absoluteStoragePath).toLocalFile();
const QString appID = Util::generateRandomString();
const QString appID = ScreenPlayUtil::generateRandomString();
// Only support remove wallpaper that spans over 1 monitor
if (monitorIndex.length() == 1) {
@ -195,7 +195,7 @@ void ScreenPlayManager::createWidget(
}
});
const QString appID = Util::generateRandomString();
const QString appID = ScreenPlayUtil::generateRandomString();
const QString path = QUrl::fromUserInput(absoluteStoragePath).toLocalFile();
if (path.isEmpty()) {
@ -402,6 +402,7 @@ void ScreenPlayManager::newConnection()
return;
}
}
qWarning() << "No matching connection found!";
});
m_clients.append(connection);
}
@ -420,7 +421,7 @@ void ScreenPlayManager::closeAllWallpapers()
if (m_screenPlayWallpapers.empty() && m_activeWallpaperCounter == 0)
return;
closeConntectionByType(GlobalVariables::getAvailableWallpaper());
closeConntectionByType(ScreenPlayUtil::getAvailableWallpaper());
setActiveWallpaperCounter(0);
}
@ -437,7 +438,7 @@ void ScreenPlayManager::closeAllWidgets()
if (m_screenPlayWidgets.empty() && m_activeWidgetsCounter == 0)
return;
closeConntectionByType(GlobalVariables::getAvailableWidgets());
closeConntectionByType(ScreenPlayUtil::getAvailableWidgets());
setActiveWidgetsCounter(0);
}
@ -452,11 +453,13 @@ bool ScreenPlayManager::closeConntectionByType(const QStringList& types)
for (auto& client : m_clients) {
if (types.contains(client->type(), Qt::CaseInsensitive)) {
client->close();
return m_clients.removeOne(client);
if (!m_clients.removeOne(client)) {
return false;
}
}
}
return false;
return true;
}
/*!
@ -549,14 +552,14 @@ bool ScreenPlayManager::removeWallpaperByAppID(const QString& appID)
*/
void ScreenPlayManager::loadProfiles()
{
auto configObj = Util::openJsonFileToObject(m_globalVariables->localSettingsPath().toString() + "/profiles.json");
auto configObj = ScreenPlayUtil::openJsonFileToObject(m_globalVariables->localSettingsPath().toString() + "/profiles.json");
if (!configObj) {
qWarning() << "Could not load active profiles at path: " << m_globalVariables->localSettingsPath().toString() + "/profiles.json";
return;
}
std::optional<QVersionNumber> version = Util::getVersionNumberFromString(configObj->value("version").toString());
std::optional<QVersionNumber> version = ScreenPlayUtil::getVersionNumberFromString(configObj->value("version").toString());
if (version && *version != m_globalVariables->version()) {
qWarning() << "Version missmatch fileVersion: " << version->toString() << "m_version: " << m_globalVariables->version().toString();

View File

@ -45,7 +45,7 @@
#include "installedlistmodel.h"
#include "monitorlistmodel.h"
#include "profilelistmodel.h"
#include "projectfile.h"
#include "ScreenPlayUtil/projectfile.h"
#include "projectsettingslistmodel.h"
#include "screenplaywallpaper.h"
#include "screenplaywidget.h"

View File

@ -47,7 +47,7 @@ ScreenPlayWallpaper::ScreenPlayWallpaper(const QVector<int>& screenNumber,
projectSettingsListModelProperties.insert("playbackRate", m_playbackRate);
} else {
if (properties.isEmpty()) {
auto obj = Util::openJsonFileToObject(absolutePath + "/project.json");
auto obj = ScreenPlayUtil::openJsonFileToObject(absolutePath + "/project.json");
if (!obj)
return;

View File

@ -34,7 +34,7 @@ ScreenPlayWidget::ScreenPlayWidget(
QJsonObject projectSettingsListModelProperties;
if (properties.isEmpty()) {
auto obj = Util::openJsonFileToObject(absolutePath + "/project.json");
auto obj = ScreenPlayUtil::openJsonFileToObject(absolutePath + "/project.json");
if (!obj)
return;

View File

@ -42,12 +42,13 @@
#include <QPoint>
#include <QProcess>
#include <memory>
#include "ScreenPlayUtil/util.h"
#include "globalvariables.h"
#include "projectsettingslistmodel.h"
#include "sdkconnection.h"
#include <memory>
namespace ScreenPlay {
class ScreenPlayWidget : public QObject {

View File

@ -48,7 +48,7 @@ void ScreenPlay::SDKConnection::readyRead()
m_appID = appID.remove("appID=");
bool typeFound = false;
for (const QString& type : GlobalVariables::getAvailableTypes()) {
for (const QString& type : ScreenPlayUtil::getAvailableTypes()) {
if (msg.contains(type, Qt::CaseInsensitive)) {
m_type = type;
typeFound = true;
@ -57,9 +57,11 @@ void ScreenPlay::SDKConnection::readyRead()
}
if (!typeFound) {
qCritical() << "Wallpaper type not found. Expected: " << GlobalVariables::getAvailableTypes() << " got: " << msg;
qCritical() << "Wallpaper type not found. Expected: " << ScreenPlayUtil::getAvailableTypes() << " got: " << msg;
}
qInfo() << "New connection" << m_appID << msg;
emit appConnected(this);
} else if (msg.startsWith("command=")) {
@ -99,7 +101,7 @@ void ScreenPlay::SDKConnection::sendMessage(const QByteArray& message)
void ScreenPlay::SDKConnection::close()
{
qInfo() << "Close " << m_type;
qInfo() << "Close " << m_type << m_appID;
QJsonObject obj;
obj.insert("command", QJsonValue("quit"));

View File

@ -46,11 +46,12 @@
#include <QVector>
#include <QWebSocketServer>
#include <memory>
#include "ScreenPlayUtil/util.h"
#include "globalvariables.h"
#include "util.h"
#include <memory>
namespace ScreenPlay {
/*!

View File

@ -1,5 +1,7 @@
#include "settings.h"
#include "ScreenPlayUtil/util.h"
namespace ScreenPlay {
/*!
@ -173,8 +175,8 @@ void Settings::setupWidgetAndWindowPaths()
QDir workingDir(QGuiApplication::applicationDirPath());
#if defined(Q_OS_WIN) || defined(Q_OS_LINUX)
m_globalVariables->setWidgetExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWidget" + Util::executableEnding()));
m_globalVariables->setWallpaperExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWallpaper" + Util::executableEnding()));
m_globalVariables->setWidgetExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWidget" + ScreenPlayUtil::executableEnding()));
m_globalVariables->setWallpaperExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWallpaper" + ScreenPlayUtil::executableEnding()));
#endif
#if defined(Q_OS_OSX)

View File

@ -60,12 +60,12 @@
#include <QtConcurrent/QtConcurrent>
#include <QtGlobal>
#include <memory>
#include <optional>
#include "globalvariables.h"
#include "util.h"
#include <memory>
#include <optional>
#ifdef Q_OS_WIN
#include <qt_windows.h>
#endif

View File

@ -1,5 +1,7 @@
#include "util.h"
#include <sentry.h>
namespace ScreenPlay {
/*!
@ -40,107 +42,6 @@ void Util::copyToClipboard(const QString& text) const
clipboard->setText(text);
}
/*!
\brief Opens a json file (absolute path) and tries to convert it to a QJsonObject.
Returns std::nullopt when not successful.
*/
std::optional<QJsonObject> Util::openJsonFileToObject(const QString& path)
{
auto jsonString = openJsonFileToString(path);
if (!jsonString.has_value()) {
return std::nullopt;
}
QJsonDocument jsonDocument;
QJsonParseError parseError {};
jsonDocument = QJsonDocument::fromJson(jsonString->toUtf8(), &parseError);
if (!(parseError.error == QJsonParseError::NoError)) {
qWarning() << "Settings Json Parse Error: " << parseError.errorString();
return std::nullopt;
}
return jsonDocument.object();
}
/*!
\brief Opens a json file (absolute path) and tries to convert it to a QString.
Returns std::nullopt when not successful.
*/
std::optional<QString> Util::openJsonFileToString(const QString& path)
{
QFile file;
file.setFileName(path);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return std::nullopt;
}
QString fileContent = file.readAll();
file.flush();
file.close();
return { fileContent };
}
/*!
\brief Generates a (non secure) random string with the default length of 32. Can contain:
\list
\li A-Z
\li a-z
\li 0-9
\endlist
*/
QString Util::generateRandomString(quint32 length)
{
const QString possibleCharacters {
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
};
const auto radomGen = QRandomGenerator::system();
QString randomString;
for (quint32 i = 0; i < length; ++i) {
const int index = radomGen->bounded(possibleCharacters.length());
const QChar nextChar = possibleCharacters.at(index);
randomString.append(nextChar);
}
return randomString;
}
/*!
\brief Return .exe in windows otherwise empty string.
*/
QString Util::executableEnding()
{
#ifdef Q_OS_WIN
return ".exe";
#else
return "";
#endif
}
/*!
\brief Parses a version from a given QString. The QString must be looke like this:
1.0.0 - Major.Minor.Patch. A fixed position is used for parsing (at 0,2,4).
Return std::nullopt when not successful.
*/
std::optional<QVersionNumber> Util::getVersionNumberFromString(const QString& str)
{
// Must be: Major.Minor.Patch
bool okMajor { false };
bool okMinor { false };
bool okPatch { false };
int major = QString(str.at(0)).toInt(&okMajor);
int minor = QString(str.at(2)).toInt(&okMinor);
int patch = QString(str.at(4)).toInt(&okPatch);
if (okMajor && okMinor && okPatch) {
return std::nullopt;
}
return QVersionNumber(major, minor, patch);
}
/*!
\brief Writes a given QJsonObject to a file. The path must be absolute. When truncate is set to
true the exsisting json file will be overriten.
@ -168,18 +69,6 @@ bool Util::writeJsonObjectToFile(const QString& absoluteFilePath, const QJsonObj
return true;
}
/*!
\brief Helper function to append a QStringList into a QString with a space between the items.
*/
QString Util::toString(const QStringList& list)
{
QString out;
for (const auto& string : list) {
out += " " + string;
}
return out;
}
void Util::appendToMetricsFile(const QString& key, const QVariant& value)
{
if (!QGuiApplication::arguments().contains("--benchmark"))
@ -201,23 +90,6 @@ void Util::appendToMetricsFile(const QString& key, const QVariant& value)
metricsFile.close();
}
/*!
\brief Parses a QByteArray to a QJsonObject. If returns and std::nullopt on failure.
*/
std::optional<QJsonObject> Util::parseQByteArrayToQJsonObject(const QByteArray& byteArray)
{
QJsonObject obj;
QJsonParseError err {};
QJsonDocument doc = QJsonDocument::fromJson(byteArray, &err);
if (err.error == QJsonParseError::NoError) {
obj = doc.object();
return { obj };
}
return std::nullopt;
}
/*!
\brief Opens a native folder window on the given path. Windows and Mac only for now!
*/
@ -309,85 +181,25 @@ void Util::Util::requestDataProtection()
});
}
/*!
\brief Util function that converts a QVector of Strings into a QJsonArray.
*/
QJsonArray Util::fillArray(const QVector<QString>& items)
static const char*
logLevelForMessageType(QtMsgType msgType)
{
QJsonArray array;
for (const QString& item : items) {
array.append(item);
}
return array;
}
/*!
\brief Maps the Search type to an installed type. Used for filtering the installed
content.
*/
SearchType::SearchType Util::getSearchTypeFromInstalledType(const InstalledType::InstalledType type)
{
using InstalledType::InstalledType;
using SearchType::SearchType;
switch (type) {
case InstalledType::GodotWallpaper:
case InstalledType::HTMLWallpaper:
case InstalledType::QMLWallpaper:
case InstalledType::GifWallpaper:
case InstalledType::WebsiteWallpaper:
return SearchType::Scene;
case InstalledType::VideoWallpaper:
return SearchType::Wallpaper;
case InstalledType::HTMLWidget:
case InstalledType::QMLWidget:
return SearchType::Widget;
case InstalledType::Unknown:
switch (msgType) {
case QtDebugMsg:
return "debug";
case QtWarningMsg:
return "warning";
case QtCriticalMsg:
return "error";
case QtFatalMsg:
return "fatal";
case QtInfoMsg:
Q_FALLTHROUGH();
default:
return SearchType::All;
return "info";
}
}
/*!
\brief Maps the installed type from a QString to an enum. Used for parsing the project.json.
*/
std::optional<InstalledType::InstalledType> Util::getInstalledTypeFromString(const QString& type)
{
if (type.endsWith("Wallpaper")) {
if (type.startsWith("video", Qt::CaseInsensitive)) {
return InstalledType::InstalledType::VideoWallpaper;
}
if (type.startsWith("qml", Qt::CaseInsensitive)) {
return InstalledType::InstalledType::QMLWallpaper;
}
if (type.startsWith("html", Qt::CaseInsensitive)) {
return InstalledType::InstalledType::HTMLWallpaper;
}
if (type.startsWith("godot", Qt::CaseInsensitive)) {
return InstalledType::InstalledType::GodotWallpaper;
}
if (type.startsWith("website", Qt::CaseInsensitive)) {
return InstalledType::InstalledType::WebsiteWallpaper;
}
if (type.startsWith("gif", Qt::CaseInsensitive)) {
return InstalledType::InstalledType::GifWallpaper;
}
}
if (type.endsWith("Widget")) {
if (type.startsWith("qml", Qt::CaseInsensitive)) {
return InstalledType::InstalledType::QMLWidget;
}
if (type.startsWith("html", Qt::CaseInsensitive)) {
return InstalledType::InstalledType::HTMLWidget;
}
}
return std::nullopt;
}
/*!
\brief Basic logging to the GUI. No logging is done to a log file for now. This string can be copied
in the settings tab in the UI.
@ -423,6 +235,24 @@ void Util::logToGui(QtMsgType type, const QMessageLogContext& context, const QSt
if (utilPointer != nullptr)
utilPointer->appendDebugMessages(log);
sentry_value_t crumb
= sentry_value_new_breadcrumb("default", qUtf8Printable(msg));
sentry_value_set_by_key(
crumb, "category", sentry_value_new_string(context.category));
sentry_value_set_by_key(
crumb, "level", sentry_value_new_string(logLevelForMessageType(type)));
sentry_value_t location = sentry_value_new_object();
sentry_value_set_by_key(
location, "file", sentry_value_new_string(context.file));
sentry_value_set_by_key(
location, "line", sentry_value_new_int32(context.line));
sentry_value_set_by_key(crumb, "data", location);
sentry_add_breadcrumb(crumb);
}
/*!
@ -514,12 +344,4 @@ bool Util::copyPreviewThumbnail(QJsonObject& obj, const QString& previewThumbnai
return true;
}
/*!
\brief Converts the given \a url string to a local file path.
*/
QString Util::toLocal(const QString& url)
{
return QUrl(url).toLocalFile();
}
}

View File

@ -53,12 +53,12 @@
#include <QtConcurrent/QtConcurrent>
#include <qqml.h>
#include "globalvariables.h"
#include <fstream>
#include <iostream>
#include <optional>
#include "globalvariables.h"
namespace ScreenPlay {
template <typename T>
@ -105,13 +105,6 @@ public slots:
void requestAllLicenses();
void requestDataProtection();
static QJsonArray fillArray(const QVector<QString>& items);
static SearchType::SearchType getSearchTypeFromInstalledType(const InstalledType::InstalledType type);
static std::optional<InstalledType::InstalledType> getInstalledTypeFromString(const QString& type);
static std::optional<QJsonObject> parseQByteArrayToQJsonObject(const QByteArray& byteArray);
static std::optional<QJsonObject> openJsonFileToObject(const QString& path);
static std::optional<QString> openJsonFileToString(const QString& path);
static std::optional<QVersionNumber> getVersionNumberFromString(const QString& str);
static void appendToMetricsFile(const QString& key, const QVariant& value);
static void logToGui(QtMsgType type, const QMessageLogContext& context, const QString& msg);
static bool writeJsonObjectToFile(const QString& absoluteFilePath, const QJsonObject& object, bool truncate = true);
@ -119,10 +112,6 @@ public slots:
static bool writeFile(const QString& text, const QString& absolutePath);
static bool writeFileFromQrc(const QString& qrcPath, const QString& absolutePath);
static bool copyPreviewThumbnail(QJsonObject& obj, const QString& previewThumbnail, const QString& destination);
static QString toString(const QStringList& list);
static QString toLocal(const QString& url);
static QString generateRandomString(quint32 length = 32);
static QString executableEnding();
void setNavigation(QString nav)
{

View File

@ -1,5 +1,7 @@
#include "wizards.h"
#include "ScreenPlayUtil/util.h"
namespace ScreenPlay {
/*!
\class ScreenPlay::Wizards
@ -37,12 +39,12 @@ void Wizards::createQMLWidget(const QString& title,
return;
}
const QString workingPath = Util::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value());
const QString workingPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value());
QJsonObject obj;
obj.insert("license", licenseName);
obj.insert("title", title);
obj.insert("tags", Util::fillArray(tags));
obj.insert("tags", ScreenPlayUtil::fillArray(tags));
obj.insert("createdBy", createdBy);
obj.insert("type", "qmlWidget");
obj.insert("file", "main.qml");
@ -98,13 +100,13 @@ void Wizards::createHTMLWidget(const QString& title,
return;
}
const QString workingPath = Util::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value());
const QString workingPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value());
QJsonObject obj;
obj.insert("license", licenseName);
obj.insert("createdBy", createdBy);
obj.insert("title", title);
obj.insert("tags", Util::fillArray(tags));
obj.insert("tags", ScreenPlayUtil::fillArray(tags));
obj.insert("type", "htmlWidget");
obj.insert("file", "index.html");
@ -161,13 +163,13 @@ void Wizards::createHTMLWallpaper(
return;
}
const QString workingPath = Util::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value());
const QString workingPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value());
QJsonObject obj;
obj.insert("license", licenseName);
obj.insert("createdBy", createdBy);
obj.insert("title", title);
obj.insert("tags", Util::fillArray(tags));
obj.insert("tags", ScreenPlayUtil::fillArray(tags));
obj.insert("type", "htmlWallpaper");
obj.insert("file", "index.html");
@ -223,13 +225,13 @@ void Wizards::createQMLWallpaper(
return;
}
const QString workingPath = Util::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value());
const QString workingPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value());
QJsonObject obj;
obj.insert("license", licenseName);
obj.insert("title", title);
obj.insert("createdBy", createdBy);
obj.insert("tags", Util::fillArray(tags));
obj.insert("tags", ScreenPlayUtil::fillArray(tags));
obj.insert("type", "qmlWallpaper");
obj.insert("file", "main.qml");
@ -276,8 +278,8 @@ void Wizards::createGifWallpaper(
return;
}
const QString workingPath = Util::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value());
const QString gifFileName = QFileInfo(Util::toLocal(file)).fileName();
const QString workingPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value());
const QString gifFileName = QFileInfo(ScreenPlayUtil::toLocal(file)).fileName();
QJsonObject obj;
obj.insert("license", licenseName);
@ -285,7 +287,7 @@ void Wizards::createGifWallpaper(
obj.insert("title", title);
obj.insert("file", gifFileName);
obj.insert("previewGIF", gifFileName);
obj.insert("tags", Util::fillArray(tags));
obj.insert("tags", ScreenPlayUtil::fillArray(tags));
obj.insert("type", "gifWallpaper");
if (!Util::writeFileFromQrc(":/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) {
@ -299,7 +301,7 @@ void Wizards::createGifWallpaper(
return;
}
if (!QFile::copy(Util::toLocal(file), workingPath + "/" + gifFileName)) {
if (!QFile::copy(ScreenPlayUtil::toLocal(file), workingPath + "/" + gifFileName)) {
qWarning() << "Could not copy gif " << file << " to: " << workingPath + "/" + gifFileName;
emit widgetCreationFinished(WizardResult::CopyFileError);
return;
@ -326,11 +328,11 @@ void Wizards::createWebsiteWallpaper(
return;
}
const QString workingPath = Util::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value());
const QString workingPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value());
QJsonObject obj;
obj.insert("title", title);
obj.insert("tags", Util::fillArray(tags));
obj.insert("tags", ScreenPlayUtil::fillArray(tags));
obj.insert("type", "websiteWallpaper");
obj.insert("url", url.toString());

View File

@ -54,14 +54,12 @@
#include <QUrl>
#include <QtMath>
#include <memory>
#include <optional>
#include "createimportvideo.h"
#include "globalvariables.h"
#include "util.h"
#include <QObject>
#include <memory>
#include <optional>
namespace ScreenPlay {

View File

@ -1,5 +1,6 @@
project(ScreenPlaySDK LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)

View File

@ -1,5 +1,6 @@
project(ScreenPlayShader LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)

View File

@ -1,5 +1,6 @@
project(ScreenPlaySysInfo LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)

View File

@ -0,0 +1,27 @@
project(ScreenPlayUtil LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)
find_package(
Qt5
COMPONENTS Core
REQUIRED)
set(SOURCES
src/util.cpp
src/contenttypes.cpp
)
set(HEADER
inc/public/ScreenPlayUtil/util.h
inc/public/ScreenPlayUtil/contenttypes.h
inc/public/ScreenPlayUtil/projectfile.h
)
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADER})
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core )
target_include_directories(${PROJECT_NAME} PUBLIC inc/public/ PRIVATE src/)

View File

@ -0,0 +1,100 @@
/****************************************************************************
**
** 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 <qobjectdefs.h>
namespace ScreenPlay {
/*!
\class ScreenPlay::GlobalVariables
\inmodule ScreenPlay
\brief GlobalVariables.
A header only class used only for storing some global variables like localStoragePath.
*/
namespace SearchType {
Q_NAMESPACE
enum class SearchType {
All,
Text,
Scene, //QML, HTML, Godot, Gif, Website wallpaper
Wallpaper,
Widget,
};
Q_ENUM_NS(SearchType)
}
namespace FillMode {
Q_NAMESPACE
enum class FillMode {
Stretch,
Fill,
Contain,
Cover,
Scale_Down
};
Q_ENUM_NS(FillMode)
}
namespace InstalledType {
Q_NAMESPACE
// When changing the enum, one also needs to change:
// GlobalVariables::getAvailableWallpaper
// GlobalVariables::getAvailableWidgets
// Common/Util.js isWallpaper() and isWidget()
// ScreenPlayWallpaper: BaseWindow::parseWallpaperType()
enum class InstalledType {
Unknown,
//Wallpaper
VideoWallpaper,
QMLWallpaper,
HTMLWallpaper,
GodotWallpaper,
GifWallpaper,
WebsiteWallpaper,
//Widgets
QMLWidget,
HTMLWidget,
};
Q_ENUM_NS(InstalledType)
}
}

View File

@ -43,8 +43,7 @@
#include <QVariant>
#include <QVariantList>
#include "globalvariables.h"
#include "util.h"
#include "ScreenPlayUtil/util.h"
/*!
\class ProjectFile
@ -103,7 +102,7 @@ struct ProjectFile {
if (!obj.contains("type"))
return;
auto type = Util::getInstalledTypeFromString(obj.value("type").toString());
auto type = ScreenPlayUtil::getInstalledTypeFromString(obj.value("type").toString());
if (!type) {
qWarning() << "Type could not parsed from: " << *type << folderName;
return;
@ -113,7 +112,7 @@ struct ProjectFile {
if (m_type == InstalledType::InstalledType::GifWallpaper) {
m_preview = m_previewGIF;
}
m_searchType = Util::getSearchTypeFromInstalledType(m_type);
m_searchType = ScreenPlayUtil::getSearchTypeFromInstalledType(m_type);
}
ProjectFile() { }

View File

@ -0,0 +1,65 @@
/****************************************************************************
**
** 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 "ScreenPlayUtil/contenttypes.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QString>
#include <QVersionNumber>
#include <optional>
namespace ScreenPlayUtil {
QJsonArray fillArray(const QVector<QString>& items);
ScreenPlay::SearchType::SearchType getSearchTypeFromInstalledType(const ScreenPlay::InstalledType::InstalledType type);
std::optional<ScreenPlay::InstalledType::InstalledType> getInstalledTypeFromString(const QString& type);
std::optional<QJsonObject> parseQByteArrayToQJsonObject(const QByteArray& byteArray);
std::optional<QJsonObject> openJsonFileToObject(const QString& path);
std::optional<QString> openJsonFileToString(const QString& path);
std::optional<QVersionNumber> getVersionNumberFromString(const QString& str);
bool writeJsonObjectToFile(const QString& absoluteFilePath, const QJsonObject& object, bool truncate = true);
bool writeSettings(const QJsonObject& obj, const QString& absolutePath);
bool writeFile(const QString& text, const QString& absolutePath);
bool writeFileFromQrc(const QString& qrcPath, const QString& absolutePath);
bool copyPreviewThumbnail(QJsonObject& obj, const QString& previewThumbnail, const QString& destination);
QString toString(const QStringList& list);
QString toLocal(const QString& url);
QString generateRandomString(quint32 length = 32);
QString executableEnding();
QStringList getAvailableWallpaper();
QStringList getAvailableWidgets();
QStringList getAvailableTypes();
bool isWallpaper(const ScreenPlay::InstalledType::InstalledType type);
bool isWidget(const ScreenPlay::InstalledType::InstalledType type);
}

View File

@ -0,0 +1,5 @@
#include "ScreenPlayUtil/contenttypes.h"
namespace ScreenPlayUtil {
}

273
ScreenPlayUtil/src/util.cpp Normal file
View File

@ -0,0 +1,273 @@
#include "ScreenPlayUtil/util.h"
#include <QFile>
#include <QJsonParseError>
#include <QRandomGenerator>
namespace ScreenPlayUtil {
/*!
\brief Opens a json file (absolute path) and tries to convert it to a QJsonObject.
Returns std::nullopt when not successful.
*/
std::optional<QJsonObject> openJsonFileToObject(const QString& path)
{
auto jsonString = openJsonFileToString(path);
if (!jsonString.has_value()) {
return std::nullopt;
}
QJsonDocument jsonDocument;
QJsonParseError parseError {};
jsonDocument = QJsonDocument::fromJson(jsonString->toUtf8(), &parseError);
if (!(parseError.error == QJsonParseError::NoError)) {
qWarning() << "Settings Json Parse Error: " << parseError.errorString();
return std::nullopt;
}
return jsonDocument.object();
}
/*!
\brief Opens a json file (absolute path) and tries to convert it to a QString.
Returns std::nullopt when not successful.
*/
std::optional<QString> openJsonFileToString(const QString& path)
{
QFile file;
file.setFileName(path);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return std::nullopt;
}
QString fileContent = file.readAll();
file.flush();
file.close();
return { fileContent };
}
/*!
\brief Generates a (non secure) random string with the default length of 32. Can contain:
\list
\li A-Z
\li a-z
\li 0-9
\endlist
*/
QString generateRandomString(quint32 length)
{
const QString possibleCharacters {
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
};
const auto radomGen = QRandomGenerator::system();
QString randomString;
for (quint32 i = 0; i < length; ++i) {
const int index = radomGen->bounded(possibleCharacters.length());
const QChar nextChar = possibleCharacters.at(index);
randomString.append(nextChar);
}
return randomString;
}
/*!
\brief Return .exe in windows otherwise empty string.
*/
QString executableEnding()
{
#ifdef Q_OS_WIN
return ".exe";
#else
return "";
#endif
}
/*!
\brief Parses a version from a given QString. The QString must be looke like this:
1.0.0 - Major.Minor.Patch. A fixed position is used for parsing (at 0,2,4).
Return std::nullopt when not successful.
*/
std::optional<QVersionNumber> getVersionNumberFromString(const QString& str)
{
// Must be: Major.Minor.Patch
bool okMajor { false };
bool okMinor { false };
bool okPatch { false };
int major = QString(str.at(0)).toInt(&okMajor);
int minor = QString(str.at(2)).toInt(&okMinor);
int patch = QString(str.at(4)).toInt(&okPatch);
if (okMajor && okMinor && okPatch) {
return std::nullopt;
}
return QVersionNumber(major, minor, patch);
}
/*!
\brief Parses a QByteArray to a QJsonObject. If returns and std::nullopt on failure.
*/
std::optional<QJsonObject> parseQByteArrayToQJsonObject(const QByteArray& byteArray)
{
QJsonObject obj;
QJsonParseError err {};
QJsonDocument doc = QJsonDocument::fromJson(byteArray, &err);
if (err.error == QJsonParseError::NoError) {
obj = doc.object();
return { obj };
}
return std::nullopt;
}
/*!
\brief Helper function to append a QStringList into a QString with a space between the items.
*/
QString toString(const QStringList& list)
{
QString out;
for (const auto& string : list) {
out += " " + string;
}
return out;
}
/*!
\brief Util function that converts a QVector of Strings into a QJsonArray.
*/
QJsonArray fillArray(const QVector<QString>& items)
{
QJsonArray array;
for (const QString& item : items) {
array.append(item);
}
return array;
}
/*!
\brief Maps the Search type to an installed type. Used for filtering the installed
content.
*/
ScreenPlay::SearchType::SearchType getSearchTypeFromInstalledType(const ScreenPlay::InstalledType::InstalledType type)
{
using ScreenPlay::InstalledType::InstalledType;
using ScreenPlay::SearchType::SearchType;
switch (type) {
case InstalledType::GodotWallpaper:
case InstalledType::HTMLWallpaper:
case InstalledType::QMLWallpaper:
case InstalledType::GifWallpaper:
case InstalledType::WebsiteWallpaper:
return SearchType::Scene;
case InstalledType::VideoWallpaper:
return SearchType::Wallpaper;
case InstalledType::HTMLWidget:
case InstalledType::QMLWidget:
return SearchType::Widget;
case InstalledType::Unknown:
default:
return SearchType::All;
}
}
/*!
\brief Maps the installed type from a QString to an enum. Used for parsing the project.json.
*/
std::optional<ScreenPlay::InstalledType::InstalledType> getInstalledTypeFromString(const QString& type)
{
using ScreenPlay::InstalledType::InstalledType;
if (type.endsWith("Wallpaper")) {
if (type.startsWith("video", Qt::CaseInsensitive)) {
return InstalledType::VideoWallpaper;
}
if (type.startsWith("qml", Qt::CaseInsensitive)) {
return InstalledType::QMLWallpaper;
}
if (type.startsWith("html", Qt::CaseInsensitive)) {
return InstalledType::HTMLWallpaper;
}
if (type.startsWith("godot", Qt::CaseInsensitive)) {
return InstalledType::GodotWallpaper;
}
if (type.startsWith("website", Qt::CaseInsensitive)) {
return InstalledType::WebsiteWallpaper;
}
if (type.startsWith("gif", Qt::CaseInsensitive)) {
return InstalledType::GifWallpaper;
}
}
if (type.endsWith("Widget")) {
if (type.startsWith("qml", Qt::CaseInsensitive)) {
return InstalledType::QMLWidget;
}
if (type.startsWith("html", Qt::CaseInsensitive)) {
return InstalledType::HTMLWidget;
}
}
return std::nullopt;
}
/*!
\brief Converts the given \a url string to a local file path.
*/
QString toLocal(const QString& url)
{
return QUrl(url).toLocalFile();
}
QStringList getAvailableWallpaper()
{
return {
"qmlWallpaper",
"htmlWallpaper",
"videoWallpaper",
"godotWallpaper",
"gifWallpaper",
"websiteWallpaper"
};
}
QStringList getAvailableWidgets()
{
return {
"qmlWidget",
"htmlWidget",
};
}
QStringList getAvailableTypes()
{
return { getAvailableWallpaper() + getAvailableWidgets() };
}
bool isWallpaper(const ScreenPlay::InstalledType::InstalledType type)
{
using ScreenPlay::InstalledType::InstalledType;
return (type == InstalledType::VideoWallpaper
|| type == InstalledType::QMLWallpaper
|| type == InstalledType::HTMLWallpaper
|| type == InstalledType::GifWallpaper
|| type == InstalledType::WebsiteWallpaper
|| type == InstalledType::GodotWallpaper);
}
bool isWidget(const ScreenPlay::InstalledType::InstalledType type)
{
using ScreenPlay::InstalledType::InstalledType;
return (type == InstalledType::QMLWidget || type == InstalledType::HTMLWidget);
}
}

6
ScreenPlayUtil/util.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "util.h"
Util::Util()
{
}

11
ScreenPlayUtil/util.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef UTIL_H
#define UTIL_H
class Util
{
public:
Util();
};
#endif // UTIL_H

View File

@ -1,5 +1,6 @@
project(ScreenPlayWallpaper LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)
@ -40,7 +41,7 @@ if(APPLE)
set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE true)
endif()
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Quick Qt5::Gui Qt5::Widgets Qt5::Core Qt5::WebEngine ScreenPlaySDK)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Quick Qt5::Gui Qt5::Widgets Qt5::Core Qt5::WebEngine ScreenPlaySDK ScreenPlayUtil)
if(APPLE)
target_link_libraries(${PROJECT_NAME} PRIVATE "-framework Cocoa")

View File

@ -1,6 +1,7 @@
import QtQuick 2.14
import QtQml 2.14
import ScreenPlayWallpaper 1.0
import ScreenPlay.Enums.InstalledType 1.0
import ScreenPlay.Shader 1.0
import "ShaderWrapper" as ShaderWrapper
@ -56,7 +57,7 @@ Rectangle {
function onReloadVideo(oldType) {
// We need to check if the old type
// was also Video not get called twice
if (oldType === Wallpaper.WallpaperType.Video)
if (oldType === InstalledType.VideoWallpaper)
return
imgCover.state = "in"
@ -66,33 +67,33 @@ Rectangle {
function init() {
switch (Wallpaper.type) {
case Wallpaper.WallpaperType.Video:
case InstalledType.VideoWallpaper:
loader.source = "qrc:/WebView.qml"
break
case Wallpaper.WallpaperType.Html:
loader.webViewUrl = Qt.resolvedUrl(Wallpaper.fullContentPath)
loader.source = "qrc:/WebView.qml"
fadeIn()
case InstalledType.HTMLWallpaper:
loader.setSource("qrc:/WebView.qml", {
"url": Qt.resolvedUrl(
Wallpaper.fullContentPath)
})
break
case Wallpaper.WallpaperType.Qml:
case InstalledType.QMLWallpaper:
loader.source = Qt.resolvedUrl(Wallpaper.fullContentPath)
imgCover.state = "out"
fadeIn()
print(loader.source)
break
case Wallpaper.WallpaperType.Website:
case InstalledType.WebsiteWallpaper:
loader.setSource("qrc:/WebsiteWallpaper.qml", {
"url": Wallpaper.fullContentPath
})
fadeIn()
break
case Wallpaper.WallpaperType.Gif:
case InstalledType.GifWallpaper:
loader.setSource("qrc:/GifWallpaper.qml", {
"source": Qt.resolvedUrl(
Wallpaper.fullContentPath)
})
fadeIn()
break
}
fadeIn()
}
function fadeIn() {
@ -107,16 +108,7 @@ Rectangle {
Loader {
id: loader
anchors.fill: parent
property string webViewUrl
onStatusChanged: {
if (loader.status === Loader.Ready) {
if (Wallpaper.type === Wallpaper.WallpaperType.Html) {
loader.item.url = loader.webViewUrl
print(loader.item.url, " --- ", loader.webViewUrl)
}
}
}
onStatusChanged: print(status)
Connections {
ignoreUnknownSignals: true
target: loader.item
@ -135,6 +127,7 @@ Rectangle {
right: parent.right
}
state: "in"
onStateChanged: print(state)
sourceSize.width: Wallpaper.width
sourceSize.height: Wallpaper.height

View File

@ -1,6 +1,6 @@
import QtQuick 2.0
import QtWebEngine 1.8
import ScreenPlay.Enums.InstalledType 1.0
import ScreenPlayWallpaper 1.0
Item {
@ -42,9 +42,7 @@ Item {
onJavaScriptConsoleMessage: print(lineNumber, message)
onLoadProgressChanged: {
if ((loadProgress === 100)) {
if (Wallpaper.type === Wallpaper.WallpaperType.Video) {
if (Wallpaper.type === InstalledType.VideoWallpaper) {
webView.runJavaScript(root.getSetVideoCommand(),
function (result) {
fadeInTimer.start()
@ -89,7 +87,6 @@ Item {
target: Wallpaper
function onReloadVideo(oldType) {
webView.runJavaScript(root.getSetVideoCommand())
}

View File

@ -15,14 +15,19 @@ BaseWindow::BaseWindow(
{
QApplication::instance()->installEventFilter(this);
qRegisterMetaType<BaseWindow::WallpaperType>();
qRegisterMetaType<ScreenPlay::InstalledType::InstalledType>();
qmlRegisterUncreatableMetaObject(ScreenPlay::InstalledType::staticMetaObject,
"ScreenPlay.Enums.InstalledType",
1, 0,
"InstalledType",
"Error: only enums");
qmlRegisterType<BaseWindow>("ScreenPlay.Wallpaper", 1, 0, "Wallpaper");
setOSVersion(QSysInfo::productVersion());
if (projectFilePath == "test") {
setType(BaseWindow::WallpaperType::Qml);
setType(ScreenPlay::InstalledType::InstalledType::QMLWallpaper);
setFullContentPath("qrc:/Test.qml");
setupLiveReloading();
return;
@ -70,10 +75,15 @@ BaseWindow::BaseWindow(
QApplication::exit(-4);
}
setType(parseWallpaperType(project.value("type").toString().toLower()));
if (auto typeOpt = ScreenPlayUtil::getInstalledTypeFromString(project.value("type").toString())) {
setType(typeOpt.value());
} else {
qCritical() << "Cannot parse Wallpaper type from value" << project.value("type");
}
setBasePath(QUrl::fromUserInput(projectFilePath).toLocalFile());
if (m_type == WallpaperType::Website) {
if (m_type == ScreenPlay::InstalledType::InstalledType::WebsiteWallpaper) {
if (!project.contains("url")) {
qFatal("No url was specified for a websiteWallpaper!");
QApplication::exit(-5);
@ -154,22 +164,24 @@ void BaseWindow::replaceWallpaper(
const QString type,
const bool checkWallpaperVisible)
{
const WallpaperType oldType = this->type();
const ScreenPlay::InstalledType::InstalledType oldType = this->type();
setCheckWallpaperVisible(checkWallpaperVisible);
setVolume(volume);
setFillMode(fillMode);
setType(parseWallpaperType(type));
if (auto typeOpt = ScreenPlayUtil::getInstalledTypeFromString(type)) {
setType(typeOpt.value());
}
if (type.contains("websiteWallpaper", Qt::CaseInsensitive)) {
setFullContentPath(file);
} else {
setFullContentPath("file:///" + absolutePath + "/" + file);
}
qInfo() << file;
if (m_type == WallpaperType::Qml || m_type == WallpaperType::Html)
if (m_type == ScreenPlay::InstalledType::InstalledType::QMLWallpaper || m_type == ScreenPlay::InstalledType::InstalledType::HTMLWallpaper)
emit reloadQML(oldType);
if (m_type == WallpaperType::Video)
if (m_type == ScreenPlay::InstalledType::InstalledType::VideoWallpaper)
emit reloadVideo(oldType);
}
@ -177,49 +189,15 @@ void BaseWindow::replaceWallpaper(
// Loading shader relative to the qml file will be available in Qt 6
QString BaseWindow::loadFromFile(const QString& filename)
{
QFile file;
file.setFileName(basePath() + "/" + filename);
qWarning() << " loadFromFile: " << file.fileName() << file.readAll();
if (file.open(QIODevice::ReadOnly)) {
const QString content = file.readAll();
QFile file(basePath() + "/" + filename);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Could not loadFromFile: " << file.fileName();
file.close();
return content;
return "";
}
const QString content = file.readAll();
file.close();
qWarning() << "Could not loadFromFile: " << file.fileName();
return "";
}
BaseWindow::WallpaperType BaseWindow::parseWallpaperType(const QString& type)
{
if (type.contains("videoWallpaper", Qt::CaseInsensitive)) {
return (BaseWindow::WallpaperType::Video);
}
if (type.contains("qmlWallpaper", Qt::CaseInsensitive)) {
return (BaseWindow::WallpaperType::Qml);
}
if (type.contains("htmlWallpaper", Qt::CaseInsensitive)) {
return (BaseWindow::WallpaperType::Html);
}
if (type.contains("godotWallpaper", Qt::CaseInsensitive)) {
return (BaseWindow::WallpaperType::Godot);
}
if (type.contains("gifWallpaper", Qt::CaseInsensitive)) {
return (BaseWindow::WallpaperType::Gif);
}
if (type.contains("websiteWallpaper", Qt::CaseInsensitive)) {
return (BaseWindow::WallpaperType::Website);
}
qWarning() << "Could not parse Wallpaper type from value: " << type;
return BaseWindow::WallpaperType::Video;
return content;
}
void BaseWindow::setupLiveReloading()

View File

@ -46,6 +46,8 @@
#include <QSysInfo>
#include <QtQml>
#include "ScreenPlayUtil/util.h"
class BaseWindow : public QObject {
Q_OBJECT
@ -75,19 +77,9 @@ public:
Q_PROPERTY(float playbackRate READ playbackRate WRITE setPlaybackRate NOTIFY playbackRateChanged)
Q_PROPERTY(float currentTime READ currentTime WRITE setCurrentTime NOTIFY currentTimeChanged)
Q_PROPERTY(WallpaperType type READ type WRITE setType NOTIFY typeChanged)
Q_PROPERTY(ScreenPlay::InstalledType::InstalledType type READ type WRITE setType NOTIFY typeChanged)
Q_PROPERTY(QString OSVersion READ OSVersion WRITE setOSVersion NOTIFY OSVersionChanged)
enum class WallpaperType {
Video,
Html,
Godot,
Qml,
Gif,
Website
};
Q_ENUM(WallpaperType)
bool loops() const
{
return m_loops;
@ -108,7 +100,7 @@ public:
return m_playbackRate;
}
BaseWindow::WallpaperType type() const
ScreenPlay::InstalledType::InstalledType type() const
{
return m_type;
}
@ -180,14 +172,14 @@ public:
signals:
void qmlExit();
void reloadQML(const BaseWindow::WallpaperType oldType);
void reloadVideo(const BaseWindow::WallpaperType oldType);
void reloadQML(const ScreenPlay::InstalledType::InstalledType oldType);
void reloadVideo(const ScreenPlay::InstalledType::InstalledType oldType);
void loopsChanged(bool loops);
void volumeChanged(float volume);
void isPlayingChanged(bool isPlaying);
void playbackRateChanged(float playbackRate);
void typeChanged(BaseWindow::WallpaperType type);
void typeChanged(ScreenPlay::InstalledType::InstalledType type);
void fullContentPathChanged(QString fullContentPath);
void appIDChanged(QString appID);
void qmlSceneValueReceived(QString key, QString value);
@ -261,7 +253,7 @@ public slots:
emit playbackRateChanged(m_playbackRate);
}
void setType(BaseWindow::WallpaperType type)
void setType(ScreenPlay::InstalledType::InstalledType type)
{
if (m_type == type)
return;
@ -406,8 +398,6 @@ public slots:
}
private:
BaseWindow::WallpaperType parseWallpaperType(const QString& type);
void setupLiveReloading();
private:
@ -426,7 +416,7 @@ private:
QString m_fullContentPath;
QString m_appID;
WallpaperType m_type = BaseWindow::WallpaperType::Qml;
ScreenPlay::InstalledType::InstalledType m_type = ScreenPlay::InstalledType::InstalledType::Unknown;
QString m_OSVersion;
QString m_fillMode;
int m_width { 0 };

View File

@ -75,7 +75,7 @@ LRESULT __stdcall MouseHookCallback(int nCode, WPARAM wParam, LPARAM lParam)
void WinWindow::setupWindowMouseHook()
{
// MUST be called before setting hook for events!
if (type() != BaseWindow::WallpaperType::Video) {
if (type() != ScreenPlay::InstalledType::InstalledType::VideoWallpaper) {
qInfo() << "Enable mousehook";
g_winGlobalHook = &m_window;

View File

@ -1,5 +1,6 @@
project(ScreenPlayWidget LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)

View File

@ -5,8 +5,8 @@ cd ..
git clone https://github.com/microsoft/vcpkg.git ScreenPlay-vcpkg
cd ScreenPlay-vcpkg
git pull
# master 10.09.2020 - 18ab4b72a26284f0df28295ce7bf9b21c96f20f4
git checkout 18ab4b72a26284f0df28295ce7bf9b21c96f20f4
# master 25.01.2021 - fc0d6b28006e0607a6b9871641ec48925274e079
git checkout fc0d6b28006e0607a6b9871641ec48925274e079
chmod +x bootstrap-vcpkg.sh
./bootstrap-vcpkg.sh
chmod +x vcpkg
@ -15,4 +15,6 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
./vcpkg install openssl-unix sentry-native doctest benchmark --triplet x64-osx --recurse
else
./vcpkg install openssl-unix sentry-native doctest benchmark --triplet x64-linux --recurse
fi
fi
./vcpkg upgrade --no-dry-run

View File

@ -5,12 +5,13 @@ cd ..
git clone https://github.com/microsoft/vcpkg.git ScreenPlay-vcpkg
cd ScreenPlay-vcpkg
git pull
rem master 26.12.2020 - a8ac047e6c40b806ac89ac4d7281d45d7c0aaf29
git checkout a8ac047e6c40b806ac89ac4d7281d45d7c0aaf29
rem master 25.01.2021 - fc0d6b28006e0607a6b9871641ec48925274e079
git checkout fc0d6b28006e0607a6b9871641ec48925274e079
call bootstrap-vcpkg.bat
rem Install vcpkg dependencies
vcpkg.exe install openssl sentry-native doctest benchmark --triplet x64-windows --recurse
vcpkg.exe upgrade --no-dry-run
cd ..
cd ScreenPlay