1
0
mirror of https://gitlab.com/kelteseth/ScreenPlay.git synced 2024-11-22 02:32:29 +01:00

Merge branch 'master' into qt6-support

# Conflicts:
#	CMakeLists.txt
#	ScreenPlay/app.h
#	ScreenPlay/main.cpp
#	ScreenPlay/main.qml
#	ScreenPlay/qml/Navigation/Navigation.qml
#	ScreenPlay/src/settings.h
#	ScreenPlay/translations/ScreenPlay_zh_cn.qm
#	ScreenPlayWallpaper/CMakeLists.txt
#	ScreenPlayWallpaper/SPWResources.qrc
#	ScreenPlayWallpaper/qml/Wallpaper.qml
This commit is contained in:
Elias Steurer 2021-09-10 11:09:38 +02:00
commit 4504f06eb1
198 changed files with 39583 additions and 7941 deletions

3
.gitattributes vendored
View File

@ -1,3 +0,0 @@
*.dll filter=lfs diff=lfs merge=lfs -text
*.exe filter=lfs diff=lfs merge=lfs -text
*.dylib filter=lfs diff=lfs merge=lfs -text

1
.gitignore vendored
View File

@ -91,3 +91,4 @@ _deps
.cmake/**
/Common/ffmpeg/*
/Docs/html/screenplay.index
/ContentBuilder/**

View File

@ -13,8 +13,8 @@ check:
script:
- cd Tools
- pip install cmakelang
- python format_cmake.py
- python format_cpp.py
- python clang_format.py
- python cmake_format.py
build:windows_debug:
stage: build
@ -84,23 +84,24 @@ build:linux_debug:
stage: build
allow_failure: true
image:
name: darkmattercoder/qt-build:5.15.2
entrypoint: [""]
name: ubuntu:20.04
tags:
- gitlab-org-docker
needs:
- check
script:
- sudo apt-get update -y
- sudo apt-get install apt-transport-https ca-certificates gnupg software-properties-common wget software-properties-common -y
- sudo snap install cqtdeployer
- wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null
- sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic-rc main' -y
- sudo apt-get update -y
- sudo apt install build-essential libgl1-mesa-dev lld ninja-build cmake -y
- apt update -y
# Otherwise libglib2 needs interaction
- export DEBIAN_FRONTEND=noninteractive
- apt install mesa-common-dev curl zip unzip tar git pkg-config apt-transport-https ca-certificates gnupg software-properties-common wget software-properties-common wget python3-pip build-essential libgl1-mesa-dev lld ninja-build cmake -y
- pip3 install aqtinstall
- mkdir Qt
- aqt install --outputdir Qt/ 5.15.2 linux desktop
- cd Tools
- python setup.py
- python build.py -t debug
- wget -q https://github.com/QuasarApp/CQtDeployer/releases/download/1.5.2/CQtDeployer_1.5.2_OfflineInstaller_Linux64.run
- python3 setup.py
- python3 build.py -t debug
artifacts:
expire_in: "4 weeks"
paths:
@ -110,24 +111,23 @@ build:linux_release:
stage: build
allow_failure: true
image:
name: darkmattercoder/qt-build:5.15.1
entrypoint: [""]
name: ubuntu:20.04
tags:
- gitlab-org-docker
needs:
- check
script:
- sudo apt-get update -y
- sudo apt-get install apt-transport-https ca-certificates gnupg software-properties-common wget software-properties-common snapd -y
- sudo /etc/init.d/snapd start
- sudo snap install cqtdeployer
- wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null
- sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic-rc main' -y
- sudo apt-get update -y
- sudo apt install build-essential libgl1-mesa-dev lld ninja-build cmake -y
- apt update -y
# Otherwise libglib2 needs interaction
- export DEBIAN_FRONTEND=noninteractive
- apt install mesa-common-dev curl zip unzip tar git pkg-config apt-transport-https ca-certificates gnupg software-properties-common wget software-properties-common wget python3-pip build-essential libgl1-mesa-dev lld ninja-build cmake -y
- pip3 install aqtinstall
- mkdir Qt
- aqt install --outputdir Qt/ 5.15.2 linux desktop
- cd Tools
- python setup.py
- python build.py -t release
- wget -q https://github.com/QuasarApp/CQtDeployer/releases/download/1.5.2/CQtDeployer_1.5.2_OfflineInstaller_Linux64.run
- python3 setup.py
- python3 build.py -t release
artifacts:
expire_in: "4 weeks"
paths:

Binary file not shown.

BIN
.gitlab/media/preview.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 MiB

9
CMake/CMakeLists.txt Normal file
View File

@ -0,0 +1,9 @@
project(CMake)
set(FILES # cmake-format: sortable
QtUpdateTranslations.cmake)
add_custom_target(
${PROJECT_NAME}
SOURCES ${FILES}
COMMENT "Dummy target to list these files in the IDE")

View File

@ -0,0 +1,16 @@
find_program(LUPDATE_EXECUTABLE lupdate)
find_program(LRELEASE_EXECUTABLE lrelease)
# Updates all ts files and generates .qm
# Absolute paths are needed!
# qt_update_translations("${CMAKE_CURRENT_SOURCE_DIR}/qml" "${L10N_LIST}")
# The second argument (list) __must__ be passed as string!
function(qt_update_translations SOURCE_PATH TS_FILES)
foreach(_ts_file ${TS_FILES})
message(STATUS "Update Translation: ${_ts_file}")
execute_process(COMMAND ${LUPDATE_EXECUTABLE} -noobsolete -recursive ${SOURCE_PATH} -ts ${_ts_file} OUTPUT_QUIET)
execute_process(COMMAND ${LRELEASE_EXECUTABLE} ${_ts_file} OUTPUT_QUIET)
endforeach()
endfunction()

View File

@ -6,7 +6,15 @@ project(ScreenPlay LANGUAGES CXX)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
option(SCREENPLAY_FOSS "" true)
option(SCREENPLAY_STEAM_DEPLOY OFF "Steam build settings. Disables steam_app.txt copy step, that is only needed for development.")
option(SCREENPLAY_STEAM ON "For FOSS distribution so we do not bundle proprietary code.")
option(TESTS_ENABLED OFF)
# Add our *.cmake diretory to the CMAKE_MODULE_PATH, so that our includes are found
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
file(MAKE_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY})
set(CMAKE_CXX_STANDARD 20)
@ -18,31 +26,20 @@ elseif(APPLE)
set(VCPKG_ARCH "x64-osx")
endif()
# Assume built-in pthreads on MacOS https://stackoverflow.com/questions/54587052/cmake-on-mac-could-not-find-threads-missing-threads-found
if(APPLE)
set(CMAKE_THREAD_LIBS_INIT "-lpthread")
set(CMAKE_HAVE_THREADS_LIBRARY 1)
set(CMAKE_USE_WIN32_THREADS_INIT 0)
set(CMAKE_USE_PTHREADS_INIT 1)
set(THREADS_PREFER_PTHREAD_FLAG ON)
endif()
if(${SCREENPLAY_FOSS})
set(VCPKG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../ScreenPlay-vcpkg")
else()
set(VCPKG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../ScreenPlay-vcpkg")
if(${TESTS_ENABLED})
enable_testing()
endif()
set(VCPKG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../ScreenPlay-vcpkg")
set(VCPKG_INSTALLED_PATH "${VCPKG_PATH}/installed/${VCPKG_ARCH}")
find_package(Git REQUIRED)
if(WIN32)
set(date_command "CMD")
set(date_arg "/c date /t")
elseif(APPLE)
set(date_command "date")
set(date_arg " +%y.%m.%d")
set(date_arg "")
elseif(UNIX)
set(date_command "date")
set(date_arg "")
@ -52,15 +49,16 @@ execute_process(
COMMAND ${date_command} ${date_arg}
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE BUILD_DATE
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --always
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_COMMIT_HASH
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
OUTPUT_STRIP_TRAILING_WHITESPACE)
add_compile_definitions(COMPILE_INFO="${BUILD_DATE} + ${GIT_COMMIT_HASH}")
add_compile_definitions(SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
if(UNIX AND NOT APPLE)
# Fixes QWebEngine linker errors on Ubuntu 20.04
@ -74,13 +72,24 @@ add_subdirectory(ScreenPlayShader)
add_subdirectory(ScreenPlayWallpaper)
add_subdirectory(ScreenPlayWidget)
add_subdirectory(ScreenPlayUtil)
add_subdirectory(CMake)
if(${SCREENPLAY_STEAM})
add_subdirectory(ScreenPlayWorkshop)
endif()
if(WIN32)
add_subdirectory(ScreenPlaySysInfo)
endif()
message(STATUS "[PROJECT] VCPKG_TARGET_TRIPLET = ${VCPKG_TARGET_TRIPLET}")
message(STATUS "[PROJECT] CMAKE_TOOLCHAIN_FILE = ${CMAKE_TOOLCHAIN_FILE}")
message(STATUS "[PROJECT] CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}")
message(STATUS "[PROJECT] QT_VERSION_MAJOR = ${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH} ")
message(STATUS "[PROJECT] Qt6_FOUND = ${Qt6_FOUND}")
message(STATUS "[DEFINE] SOURCE_DIR = ${SOURCE_DIR}")
message(STATUS "[DEFINE] BUILD_DATE = ${BUILD_DATE}")
message(STATUS "[DEFINE] GIT_COMMIT_HASH = ${GIT_COMMIT_HASH}")
message(STATUS "[PROJECT] CMAKE_TOOLCHAIN_FILE = ${CMAKE_TOOLCHAIN_FILE}")
message(STATUS "[PROJECT] VCPKG_PATH = ${VCPKG_PATH}")
message(STATUS "[PROJECT] VCPKG_ARCH = ${VCPKG_ARCH}")
message(STATUS "[PROJECT] CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}")
message(STATUS "[PROJECT] VCPKG_TARGET_TRIPLET = ${VCPKG_TARGET_TRIPLET}")
message(STATUS "[OPTION] SCREENPLAY_STEAM_DEPLOY = ${SCREENPLAY_STEAM_DEPLOY}")
message(STATUS "[OPTION] SCREENPLAY_STEAM = ${SCREENPLAY_STEAM}")
message(STATUS "[OPTION] TESTS_ENABLED = ${TESTS_ENABLED}")

29
Docs/macOSSigning.md Normal file
View File

@ -0,0 +1,29 @@
# ScreenPlay macOS signing full guide
## Create a developer account and certs
1. Pay the 99$ Apple tax
2. Create a app password for distribution outside of the app store
- Go to https://appleid.apple.com/account/manage
- Call it ScreenPlay and save the password!
3. Next we need a developer certificate:
- Go to https://developer.apple.com/account/resources/certificates/list
- Click the blue plus sign
- Select `Developer ID Application`
- _This certificate is used to code sign your app for distribution outside of the Mac App Store._
## Sign the app locally with codesign
We need to sign every single file in the .app file. For this we use the name from the installed cert. This can be copied from the `Keychain Access.app`.
`codesign --deep -f -s "Developer ID Application: Elias Steurer (AAABCXYZAA)" --options "runtime" "ScreenPlay.app/"`
## Upload to apple for notization
We use [xcnotary](https://github.com/akeru-inc/xcnotary) tools for fast automatic upload. Install it via brew:
`brew install akeru-inc/tap/xcnotary`
Then run it with the
- `*.app` name
- `-d` the developer account email and
- `-k` command is here the keychain name that contains your password from the app password step above!
`xcnotary notarize ScreenPlay.app -d yourDeveloperAccountEmail@example.com -k ScreenPlay`

View File

@ -16,9 +16,6 @@ Dev. Docs [![pipeline status](https://gitlab.com/kelteseth/ScreenPlayDeveloper
<br><br>
User Chat (Discord)
<a href="https://discord.com/invite/JBMmZbgc?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)
<br>
ScreenPlay is an open source cross platform app for displaying Video Wallpaper, Widgets and AppDrawer. It is written in modern C++20/Qt5/QML. Binaries with workshop support are available for Windows and soon Linux & MacOSX via <a href="https://store.steampowered.com/app/672870/ScreenPlay/">Steam</a>. Join our community: <a href="https://screen-play.app/">Homepage</a> - <a href="https://forum.screen-play.app/">Forum</a>
@ -29,14 +26,16 @@ Windows only, Linux and MacOS next.
<br>
<br>
<a href="https://www.youtube.com/watch?v=q-J2fTWDxw8">
<!-- This works only on gitlab -->
![](https://gitlab.com/kelteseth/ScreenPlay/-/raw/master/.gitlab/media/preview.webp)
<!-- This works only on github -->
![](/.gitlab/media/preview.webp)
![Preview](.gitlab/media/preview.gif)
</a>
<p>Click gif to see the Steam Early Access Trailer (YouTube)</p>
<a href="https://www.youtube.com/watch?v=q-J2fTWDxw8"><p>Watch the Steam Early Access Trailer (YouTube)</p></a>
</div>
# Important Issues
* [Implement KDE Support](https://gitlab.com/kelteseth/ScreenPlay/-/issues/111)
* [Implement MacOS Support](https://gitlab.com/kelteseth/ScreenPlay/-/issues/130)
@ -97,7 +96,7 @@ Here are some ways you can contribute:
| Feature | Windows | Linux | MacOS |
|------------------------ |--------- |------- |------- |
| __ScreenPlay Main App__ | ✔ | ✔ | ✔ |
| __Steam Binaries__ | ✔ | ❌ | |
| __Steam Binaries__ | ✔ | ❌ | |
| __Wallpaper__ | ✔ | ❓ Help Needed for Gnome/KDE/etc! | ✔ |
| __Widgets__ | ✔ | ✔ | ✔ |
| __Multilanguage (EN,DE,RU,FR,ES,KO,VI,CH_ZN,PT_BR🆕)__ | ✔ | ✔ | ✔ |

View File

@ -11,10 +11,8 @@ ScreenPlay [![pipeline status](https://gitlab.com/kelteseth/ScreenPlay/badges/ma
<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>
用户交流 (Discord英语)
用户聊天群 (Discord英语)
<a href="https://discord.com/invite/JBMmZbgc?utm_source=Discord%20Widget&utm_medium=Connect">![Discord](https://img.shields.io/discord/516635043435773970?style=for-the-badge)</a>
开发者交流(英语) [![Gitter](https://badges.gitter.im/ScreenPlayApp/community.svg)](https://gitter.im/ScreenPlayApp/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
<br>
@ -22,21 +20,21 @@ ScreenPlay 是一款开源、跨平台,显示视频壁纸,部件,应用抽
带有创意工坊支持的二进制(在 Windows ,以及不久的 Linux 及 MacOSX 可用)可以通过<a href="https://store.steampowered.com/app/672870/ScreenPlay/">Steam</a>获取。加入我们(英语):<a href="https://screen-play.app/">首页</a> - <a href="https://forum.screen-play.app/">论坛</a>
<br>
<h3><a href="https://store.steampowered.com/app/672870/ScreenPlay/">✨通过Steam下载ScreenPlay</a> - <a href="https://steamcommunity.com/app/672870/workshop/">Steam 创意工坊,获取壁纸与部件✨</a></h3>
仅支持WindowsLinux 和 MacOS 在做了
<h3><a href="https://store.steampowered.com/app/672870/ScreenPlay/">✨通过Steam下载ScreenPlay</a> <br><br> <a href="https://www.patreon.com/ScreenPlayApp">🚀于 Patreon 支持 ScreenPlay 🚀</a></h3>
支持Windows 与 MacOS。Linux支持敬请期待
<br>
<br>
<!-- This works only on gitlab -->
![](https://gitlab.com/kelteseth/ScreenPlay/-/raw/master/.gitlab/media/preview.webp)
<!-- This works only on github -->
![](/.gitlab/media/preview.webp)
<a href="https://www.youtube.com/watch?v=q-J2fTWDxw8">
![预览](.gitlab/media/preview.gif)
</a>
<p>点击gif查看尽早访问预告片 (YouTube)</p>
<p>查看提前访问预告片 (YouTube)</p>
</div>
# 重要议题
* [对Windows显示器缩放的支持目前有问题。所有显示器必须被设为100%](https://gitlab.com/kelteseth/ScreenPlay/-/issues/125)
# 重要问题
* [KDE 支持](https://gitlab.com/kelteseth/ScreenPlay/-/issues/111)
* [MacOS 支持](https://gitlab.com/kelteseth/ScreenPlay/-/issues/130)
@ -58,16 +56,16 @@ ScreenPlay 是一款开源、跨平台,显示视频壁纸,部件,应用抽
* [部件引导](https://kelteseth.gitlab.io/ScreenPlayDocs/widgets/widgets/) - 通用引导,如何创建部件。
ScreenPlay使用易于学习的 QML 语言。无需任何编程知识!
* [Storage Widget](https://kelteseth.gitlab.io/ScreenPlayDocs/widgets/example_Storage/). Display your drives and usage.
* [存储部件](https://kelteseth.gitlab.io/ScreenPlayDocs/widgets/example_Storage/) 显示您的设备及使用情况
* [CPU 占用部件](https://kelteseth.gitlab.io/ScreenPlayDocs/widgets/example_CPU/) 显示您当前的CPU使用情况
* [RSS订阅部件](https://kelteseth.gitlab.io/ScreenPlayDocs/widgets/example_RSS/) 以RSS部件显示新闻
* [RSS订阅部件](https://kelteseth.gitlab.io/ScreenPlayDocs/widgets/example_RSS/) 用RSS部件显示新闻
# 一般贡献
每个人都可以贡献代码,设计,文档以及翻译。更多信息见[贡献引导](https://kelteseth.gitlab.io/ScreenPlayDocs/contribute/contribute)。也请查阅 [Collaboration Guidelines](Docs/CodeOfConduct.md).
这里是一些贡献的方式:
这里是一些贡献的方式:
* 通过使用预发布版本/ master分支或者Steam每夜构建。
* 通过 [添加/修复翻译](https://kelteseth.gitlab.io/ScreenPlayDocs/contribute/translations/)
* by [设计 UI/UX](https://kelteseth.gitlab.io/ScreenPlayDocs/contribute/contribute/#design)
@ -88,17 +86,17 @@ ScreenPlay使用易于学习的 QML 语言。无需任何编程知识!
* [ScreenPlay project overview](Docs/ProjectOverview.md)
* [Developer C++ Classes Documentation](https://kelteseth.gitlab.io/ScreenPlayDeveloperDocs/)
# Platform support
# 平台支持
* ❌ Not working/Not implemented
* ❓ Only partially implemented/Not tested, help needed
* ❌ 不工作 / 尚未实现
* ❓ 部分实现 / 尚未测试,需要帮助
<div align="center">
| 功能 | Windows | Linux | MacOS |
|------------------------ |--------- |------- |------- |
| __ScreenPlay 主程序__ | ✔ | ✔ | ✔ |
| __Steam 二进制__ | ✔ | ❌ | |
| __Steam 二进制__ | ✔ | ❌ | |
| __壁纸__ | ✔ | ❓ 需要帮助 Gnome/KDE 等! | ✔ |
| __部件__ | ✔ | ✔ | ✔ |
| __多语言 (EN,DE,RU,FR,ES,KO,VI,ZH_CN,PT_BR🆕)__ | ✔ | ✔ | ✔ |
@ -106,9 +104,9 @@ ScreenPlay使用易于学习的 QML 语言。无需任何编程知识!
</div>
因为每个操作系统有它自己的桌面环境,我们需要分别适配 ScreenPlayWindow 到各个平台。
目前功能最完好的是Windows 10。Windows 7下也可用但有[错误的coordinates](https://gitlab.com/kelteseth/ScreenPlay/issues/34). MacOS has some basic wallpaper functionality but no maintainer. For Linux we sadly have no support for any desktop environments at the moment, except basic KDE support.
目前功能最完好的是Windows 10。Windows 7下也可用但有[错误的coordinates](https://gitlab.com/kelteseth/ScreenPlay/issues/34)。MacOS 有了一定的基本壁纸功能但是没有人维护。对于linux很抱歉我们尚未支持任何桌面环境除了 KDE 的基本支持。
__If you want to help and add new desktop environments look at ScreenPlayWallpaper/src folder__
__如果您想要帮助我们,添加新的桌面环境,请于 ScreenPlayWallpaper/src 文件夹查看__
* [BaseWindow](https://gitlab.com/kelteseth/ScreenPlay/blob/dev/ScreenPlayWallpaper/src/basewindow.h) baseclass for:
* [LinuxWindow](https://gitlab.com/kelteseth/ScreenPlay/blob/dev/ScreenPlayWallpaper/src/linuxwindow.h)
@ -119,7 +117,7 @@ __If you want to help and add new desktop environments look at ScreenPlayWallpap
| 平台 | Windows 10 | Gnome | KDE | MacOS |
|------------------------ |------- |--------- |------- | ------- |
| __壁纸__ | ✔ |❌ Help Needed! | ❓ [基本实现](https://gitlab.com/kelteseth/ScreenPlay/-/tree/master/ScreenPlayWallpaper/kde/ScreenPlay) | ❓ [基本实现](https://gitlab.com/kelteseth/ScreenPlay/-/blob/master/ScreenPlayWallpaper/src/MacBridge.mm) |
| __壁纸__ | ✔ |❌ 需要帮助! | ❓ [基本实现](https://gitlab.com/kelteseth/ScreenPlay/-/tree/master/ScreenPlayWallpaper/kde/ScreenPlay) | ❓ [基本实现](https://gitlab.com/kelteseth/ScreenPlay/-/blob/master/ScreenPlayWallpaper/src/MacBridge.mm) |
</div>

View File

@ -14,7 +14,6 @@ find_package(CURL CONFIG REQUIRED)
find_package(sentry CONFIG REQUIRED)
set(src
main.cpp
app.cpp
src/globalvariables.cpp
src/createimportvideo.cpp
@ -36,6 +35,7 @@ set(headers
app.h
src/globalvariables.h
src/createimportvideo.h
src/createimportstates.h
src/installedlistmodel.h
src/monitorlistmodel.h
src/screenplaywallpaper.h
@ -51,97 +51,75 @@ set(headers
src/create.h
src/wizards.h)
set(l10n
translations/ScreenPlay_de.ts
translations/ScreenPlay_zh_cn.ts
translations/ScreenPlay_pt_br.ts
translations/ScreenPlay_en.ts
translations/ScreenPlay_es.ts
translations/ScreenPlay_fr.ts
translations/ScreenPlay_ko.ts
translations/ScreenPlay_ru.ts
translations/ScreenPlay_vi.ts)
list(
APPEND
L10N_LIST
# cmake-format: sortable
${CMAKE_CURRENT_SOURCE_DIR}/translations/ScreenPlay_de.ts
${CMAKE_CURRENT_SOURCE_DIR}/translations/ScreenPlay_zh_cn.ts
${CMAKE_CURRENT_SOURCE_DIR}/translations/ScreenPlay_pt_br.ts
${CMAKE_CURRENT_SOURCE_DIR}/translations/ScreenPlay_en.ts
${CMAKE_CURRENT_SOURCE_DIR}/translations/ScreenPlay_es.ts
${CMAKE_CURRENT_SOURCE_DIR}/translations/ScreenPlay_fr.ts
${CMAKE_CURRENT_SOURCE_DIR}/translations/ScreenPlay_ko.ts
${CMAKE_CURRENT_SOURCE_DIR}/translations/ScreenPlay_ru.ts
${CMAKE_CURRENT_SOURCE_DIR}/translations/ScreenPlay_vi.ts)
set_source_files_properties(${l10n} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/translations")
include(QtUpdateTranslations)
qt_update_translations("${CMAKE_CURRENT_SOURCE_DIR}/qml" "${L10N_LIST}")
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
find_package(
Qt${QT_VERSION_MAJOR}
COMPONENTS Core
Quick
Gui
Widgets
WebSockets
Svg
WebEngineCore
WebEngineQuick
WebChannel
Positioning
LinguistTools)
# Needed on macos
find_package(Threads REQUIRED)
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
qt_add_resources(qml qml.qrc assets.qrc)
else()
qtquick_compiler_add_resources(qml qml.qrc assets.qrc)
endif()
find_package(
Qt6
COMPONENTS Core
Quick
Gui
Widgets
WebSockets
Svg
LinguistTools
WebEngineQuick
WebEngineCore
Test)
add_executable(${PROJECT_NAME} ${src} ${headers} ${resources} ${qml} ${fonts})
target_link_libraries(
${PROJECT_NAME}
PRIVATE ScreenPlaySDK
ScreenPlayUtil
benchmark::benchmark
benchmark::benchmark_main
doctest::doctest
sentry::sentry
Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::WebSockets
Qt${QT_VERSION_MAJOR}::Svg
Qt6::WebEngineCore
Qt6::WebEngineQuick)
qt_add_translation(qmFiles ${l10n})
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
qt_add_resources(resources ScreenPlayAssets.qrc ScreenPlayQML.qrc)
else()
find_package(
Qt${QT_VERSION_MAJOR}
COMPONENTS Core
Quick
Gui
Widgets
WebSockets
Svg
LinguistTools
WebEngine)
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
qt_add_resources(qml qml.qrc assets.qrc)
else()
qtquick_compiler_add_resources(qml qml.qrc assets.qrc)
endif()
add_executable(${PROJECT_NAME} ${src} ${headers} ${resources} ${qml} ${fonts})
target_link_libraries(
${PROJECT_NAME}
PRIVATE ScreenPlaySDK
ScreenPlayUtil
benchmark::benchmark
benchmark::benchmark_main
doctest::doctest
sentry::sentry
Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::WebSockets
Qt${QT_VERSION_MAJOR}::Svg
Qt5::WebEngine)
qt5_add_translation(qmFiles ${l10n})
qtquick_compiler_add_resources(resources ScreenPlayAssets.qrc ScreenPlayQML.qrc)
endif()
add_library(ScreenPlayLib ${src} ${headers} ${resources} ${resources} ${fonts})
target_include_directories(ScreenPlayLib PUBLIC ./ src/)
target_link_libraries(
ScreenPlayLib
PUBLIC ScreenPlaySDK
ScreenPlayUtil
benchmark::benchmark
benchmark::benchmark_main
doctest::doctest
sentry::sentry
Threads::Threads
Qt6::Quick
Qt6::Gui
Qt6::Widgets
Qt6::Core
Qt6::WebSockets
Qt6::Svg
Qt6::WebEngineQuick
Qt6::WebEngineCore)
add_executable(tst_ScreenPlay tests/tst_main.cpp)
target_link_libraries(tst_ScreenPlay PRIVATE ScreenPlayLib Qt6::Test)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlayLib)
qt_add_translation(qmFiles ${l10n})
qt_add_big_resources(fonts fonts.qrc)
target_compile_definitions(${PROJECT_NAME} PRIVATE "GIT_VERSION=${GIT_VERSION}")
@ -193,6 +171,19 @@ if(APPLE)
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/../Common/ffmpeg/ffprobe
${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/)
# tst_ScreenPlay needs ffmpeg in the base path
if(${TESTS_ENABLED})
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/../Common/ffmpeg/ffmpeg ${CMAKE_BINARY_DIR}/bin/)
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/../Common/ffmpeg/ffprobe ${CMAKE_BINARY_DIR}/bin/)
endif()
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD

View File

@ -13,11 +13,13 @@
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<string>ScreenPlay</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<string>0.14</string>
<key>CFBundleShortVersionString</key>
<string>0.14</string>
<key>CFBundleDisplayName</key>
<string>ScreenPlay</string>
</dict>

View File

@ -130,5 +130,6 @@
<file>assets/icons/brand_reddit.svg</file>
<file>assets/icons/steam_default_avatar.png</file>
<file>assets/macos/app.screenplay.plist</file>
<file>assets/icons/item_banner_new.svg</file>
</qresource>
</RCC>

View File

@ -58,7 +58,7 @@ App::App()
QGuiApplication::setOrganizationName("ScreenPlay");
QGuiApplication::setOrganizationDomain("screen-play.app");
QGuiApplication::setApplicationName("ScreenPlay");
QGuiApplication::setApplicationVersion("0.13.3");
QGuiApplication::setApplicationVersion("0.14.0");
QGuiApplication::setQuitOnLastWindowClosed(false);
QFontDatabase::addApplicationFont(":/assets/fonts/LibreBaskerville-Italic.ttf");
@ -173,6 +173,8 @@ void App::init()
}
m_create = make_unique<Create>(m_globalVariables);
QObject::connect(m_create.get(), &Create::finished, m_installedListModel.get(), &InstalledListModel::reset);
m_wizards = make_unique<Wizards>(m_globalVariables);
// When the installed storage path changed
@ -195,6 +197,11 @@ void App::init()
}
qmlRegisterSingletonInstance("ScreenPlay", 1, 0, "ScreenPlay", this);
#ifdef Q_OS_MACOS
// Needed for macos .app files
m_mainWindowEngine->addPluginPath(QGuiApplication::instance()->applicationDirPath());
#endif
m_mainWindowEngine->load(QUrl(QStringLiteral("qrc:/main.qml")));
// Must be called last to display a error message on startup by the qml engine

View File

@ -47,12 +47,7 @@
#include <QUrl>
#include <QtGlobal>
#include <QtQml>
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <QtWebEngine>
#else
#include <QtWebEngineCore>
#endif
#include <QtSvg>
#include "src/create.h"

View File

@ -1 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 22 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><path id="display" d="M0,0l0,13.701l21.922,0l0,-13.701l-21.922,0Zm20.552,12.331l-19.182,0l0,-10.961l19.182,0l0,10.961Zm-6.166,2.74l-6.85,0l-0.685,2.741l-1.371,1.37l10.961,0l-1.37,-1.37l-0.685,-2.741Z" style="fill:#626262;fill-rule:nonzero;"/></svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 28 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g id="Artboard1" transform="matrix(1.27726,0,0,1.25117,0,0)">
<rect x="0" y="0" width="21.922" height="19.182" style="fill:none;"/>
<g id="display" transform="matrix(0.914274,0,0,1,0,0)">
<path d="M0,0L0,15.099L23.977,15.099L23.977,0L0,0ZM22.607,13.729L1.37,13.729L1.37,1.37L22.607,1.37L22.607,13.729ZM14.103,15.005L9.875,15.005L9.453,17.812L8.607,19.182L15.371,19.182L14.525,17.812L14.103,15.005Z" style="fill:rgb(98,98,98);fill-rule:nonzero;"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 658 B

After

Width:  |  Height:  |  Size: 952 B

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 320 180" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(0.319516,0.319516,-0.498372,0.498372,302.434,-166.795)">
<path d="M350.406,189.405L226.597,189.405L189.603,213.123L387.4,213.123L350.406,189.405Z" style="fill:rgb(255,152,0);"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 18 MiB

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>

View File

@ -51,10 +51,9 @@
int main(int argc, char* argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QtWebEngine::initialize();
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
Q_INIT_RESOURCE(ScreenPlayQML);
Q_INIT_RESOURCE(ScreenPlayAssets);
QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QApplication qtGuiApp(argc, argv);

View File

@ -34,11 +34,17 @@ ApplicationWindow {
function switchPage(name) {
if (nav.currentNavigationName === name) {
if (name === "Installed")
ScreenPlay.installedListModel.reset();
ScreenPlay.installedListModel.reset()
}
if (name === "Installed") {
stackView.replace("qrc:/qml/" + name + "/" + name + ".qml", {
"sidebar": sidebar
})
return
}
stackView.replace("qrc:/qml/" + name + "/" + name + ".qml");
sidebar.state = "inactive";
stackView.replace("qrc:/qml/" + name + "/" + name + ".qml")
sidebar.state = "inactive"
}
color: Material.theme === Material.Dark ? Qt.darker(Material.background) : Material.background
@ -105,7 +111,7 @@ ApplicationWindow {
StackView {
id: stackView
objectName: "stackView"
property int duration: 300
anchors {
@ -172,6 +178,7 @@ ApplicationWindow {
Installed.Sidebar {
id: sidebar
objectName: "installedSidebar"
navHeight: nav.height

View File

@ -141,8 +141,8 @@ Item {
title: qsTr("Please choose a file")
onAccepted: {
root.file = fileDialog.file;
txtName.text = fileDialog.file.toString();
root.file = fileDialog.fileUrl;
txtName.text = fileDialog.fileUrl.toString();
}
}

View File

@ -1,7 +1,7 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.Material 2.12
import Qt.labs.platform 1.1
import QtQuick.Dialogs 1.2
import ScreenPlay 1.0
/*!
@ -193,11 +193,10 @@ Item {
id: fileDialog
title: "Please choose a file"
fileMode: FileDialog.OpenFile
nameFilters: ["Images (*.png *.jpg)"]
onAccepted: {
imageSource = fileDialog.file;
txtName.text = fileDialog.file.toString().replace(/^.*[\\\/]/, '');
imageSource = fileDialog.fileUrl;
txtName.text = fileDialog.fileUrl.toString().replace(/^.*[\\\/]/, '');
}
}

View File

@ -11,6 +11,7 @@ import ScreenPlay.QMLUtilities 1.0
Rectangle {
id: root
objectName: "createSidebar"
property bool expanded: false
property alias listView: listView
@ -24,6 +25,8 @@ Rectangle {
color: Material.background
ListView {
/*
ListElement {
headline: qsTr("QML Particle Wallpaper")
@ -85,8 +88,8 @@ Rectangle {
category: "Example Widget"
}
*/
id: listView
objectName: "wizardsListView"
anchors.fill: parent
anchors.margins: 20
@ -97,15 +100,15 @@ Rectangle {
id: loaderConnections
function onWizardStarted() {
root.expanded = false;
root.expanded = false
}
function onWizardExited() {
root.expanded = true;
stackView.clear(StackView.PushTransition);
stackView.push("qrc:/qml/Create/StartInfo.qml");
listView.currentIndex = 0;
ScreenPlay.util.setNavigationActive(true);
root.expanded = true
stackView.clear(StackView.PushTransition)
stackView.push("qrc:/qml/Create/StartInfo.qml")
listView.currentIndex = 0
ScreenPlay.util.setNavigationActive(true)
}
ignoreUnknownSignals: true
@ -116,56 +119,64 @@ Rectangle {
headline: qsTr("Tools Overview")
source: "qrc:/qml/Create/StartInfo.qml"
category: "Home"
objectName: ""
}
ListElement {
headline: "Video import and convert (all types)"
headline: qsTr("Video import and convert (all types)")
source: "qrc:/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml"
category: "Video Wallpaper"
objectName: "videoImportConvert"
}
ListElement {
headline: qsTr("Video Import (.webm)")
source: "qrc:/qml/Create/Wizards/ImportWebm/ImportWebm.qml"
category: "Video Wallpaper"
objectName: ""
}
ListElement {
headline: qsTr("GIF Wallpaper")
source: "qrc:/qml/Create/Wizards/GifWallpaper.qml"
category: "Video Wallpaper"
objectName: ""
}
ListElement {
headline: qsTr("QML Wallpaper")
source: "qrc:/qml/Create/Wizards/QMLWallpaper.qml"
category: "Code Wallpaper"
objectName: ""
}
ListElement {
headline: qsTr("HTML5 Wallpaper")
source: "qrc:/qml/Create/Wizards/HTMLWallpaper.qml"
category: "Code Wallpaper"
objectName: ""
}
ListElement {
headline: qsTr("Website Wallpaper")
source: "qrc:/qml/Create/Wizards/WebsiteWallpaper.qml"
category: "Code Wallpaper"
objectName: ""
}
ListElement {
headline: qsTr("QML Widget")
source: "qrc:/qml/Create/Wizards/QMLWidget.qml"
category: "Code Widgets"
objectName: ""
}
ListElement {
headline: qsTr("HTML Widget")
source: "qrc:/qml/Create/Wizards/HTMLWidget.qml"
category: "Code Widgets"
objectName: ""
}
}
ScrollBar.vertical: ScrollBar {
@ -186,25 +197,22 @@ Rectangle {
left: parent.left
bottomMargin: 10
}
}
}
delegate: Button {
id: listItem
objectName: model.objectName
width: listView.width - 40
height: 45
highlighted: ListView.isCurrentItem
text: headline
onClicked: {
listView.currentIndex = index;
const item = stackView.push(source);
loaderConnections.target = item;
listView.currentIndex = index
const item = stackView.push(source)
loaderConnections.target = item
}
}
}
layer.effect: ElevationEffect {
@ -220,7 +228,6 @@ Rectangle {
anchors.leftMargin: 0
opacity: 1
}
},
State {
name: "inactive"
@ -230,7 +237,6 @@ Rectangle {
opacity: 0
anchors.leftMargin: -root.width
}
}
]
transitions: [
@ -249,9 +255,7 @@ Rectangle {
duration: 300
easing.type: Easing.OutCubic
}
}
}
]
}

View File

@ -21,12 +21,14 @@ Item {
clip: true
CreateWallpaperInit {
onNext: {
onNext: startConvert(filePath,codec);
function startConvert(filePath,codec){
root.wizardStarted();
swipeView.currentIndex = 1;
createWallpaperVideoImportConvert.codec = codec;
createWallpaperVideoImportConvert.filePath = filePath;
ScreenPlay.create.createWallpaperStart(filePath, codec, quality);
}
}

View File

@ -10,6 +10,7 @@ import "../../../Common" as Common
Item {
id: root
objectName: "createWallpaperInit"
property int quality: sliderQuality.slider.value
@ -127,6 +128,7 @@ Item {
}
Button {
objectName: "createWallpaperInitFileSelectButton"
text: qsTr("Select file")
highlighted: true
font.family: ScreenPlay.settings.font

View File

@ -5,6 +5,7 @@ import QtQuick.Controls.Material 2.3
import QtQuick.Layouts 1.12
import ScreenPlay 1.0
import ScreenPlay.Create 1.0
import ScreenPlay.Enums.ImportVideoState 1.0
import "../../../Common" as Common
Item {
@ -15,86 +16,88 @@ Item {
property var codec: Create.VP8
property string filePath
signal abort()
signal save()
signal abort
signal save
function cleanup() {
ScreenPlay.create.abortAndCleanup();
ScreenPlay.create.cancel()
}
function basename(str) {
let filenameWithExtentions = (str.slice(str.lastIndexOf("/") + 1));
let filename = filenameWithExtentions.split('.').slice(0, -1).join('.');
return filename;
let filenameWithExtentions = (str.slice(str.lastIndexOf("/") + 1))
let filename = filenameWithExtentions.split('.').slice(0, -1).join('.')
return filename
}
function checkCanSave() {
if (canSave && conversionFinishedSuccessful)
btnSave.enabled = true;
btnSave.enabled = true
else
btnSave.enabled = false;
btnSave.enabled = false
}
onCanSaveChanged: root.checkCanSave()
onFilePathChanged: {
textFieldName.text = basename(filePath);
textFieldName.text = basename(filePath)
}
Connections {
function onCreateWallpaperStateChanged(state) {
switch (state) {
case CreateImportVideo.ConvertingPreviewImage:
txtConvert.text = qsTr("Generating preview image...");
break;
case CreateImportVideo.ConvertingPreviewThumbnailImage:
txtConvert.text = qsTr("Generating preview thumbnail image...");
break;
case CreateImportVideo.ConvertingPreviewImageFinished:
imgPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.jpg";
imgPreview.visible = true;
break;
case CreateImportVideo.ConvertingPreviewVideo:
txtConvert.text = qsTr("Generating 5 second preview video...");
break;
case CreateImportVideo.ConvertingPreviewGif:
txtConvert.text = qsTr("Generating preview gif...");
break;
case CreateImportVideo.ConvertingPreviewGifFinished:
gifPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.gif";
imgPreview.visible = false;
gifPreview.visible = true;
gifPreview.playing = true;
break;
case CreateImportVideo.ConvertingAudio:
txtConvert.text = qsTr("Converting Audio...");
break;
case CreateImportVideo.ConvertingVideo:
txtConvert.text = qsTr("Converting Video... This can take some time!");
break;
case CreateImportVideo.ConvertingVideoError:
txtConvert.text = qsTr("Converting Video ERROR!");
break;
case CreateImportVideo.AnalyseVideoError:
txtConvert.text = qsTr("Analyse Video ERROR!");
break;
case CreateImportVideo.Finished:
txtConvert.text = "";
conversionFinishedSuccessful = true;
busyIndicator.running = false;
root.checkCanSave();
break;
case ImportVideoState.ConvertingPreviewImage:
txtConvert.text = qsTr("Generating preview image...")
break
case ImportVideoState.ConvertingPreviewThumbnailImage:
txtConvert.text = qsTr("Generating preview thumbnail image...")
break
case ImportVideoState.ConvertingPreviewImageFinished:
imgPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.jpg"
imgPreview.visible = true
break
case ImportVideoState.ConvertingPreviewVideo:
txtConvert.text = qsTr("Generating 5 second preview video...")
break
case ImportVideoState.ConvertingPreviewGif:
txtConvert.text = qsTr("Generating preview gif...")
break
case ImportVideoState.ConvertingPreviewGifFinished:
gifPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.gif"
imgPreview.visible = false
gifPreview.visible = true
gifPreview.playing = true
break
case ImportVideoState.ConvertingAudio:
txtConvert.text = qsTr("Converting Audio...")
break
case ImportVideoState.ConvertingVideo:
txtConvert.text = qsTr(
"Converting Video... This can take some time!")
break
case ImportVideoState.ConvertingVideoError:
txtConvert.text = qsTr("Converting Video ERROR!")
break
case ImportVideoState.AnalyseVideoError:
txtConvert.text = qsTr("Analyse Video ERROR!")
break
case ImportVideoState.Finished:
txtConvert.text = ""
conversionFinishedSuccessful = true
busyIndicator.running = false
btnExit.enabled = false;
root.checkCanSave()
break
}
}
function onProgressChanged(progress) {
var percentage = Math.floor(progress * 100);
var percentage = Math.floor(progress * 100)
if (percentage > 100 || progress > 0.95)
percentage = 100;
percentage = 100
if (percentage === NaN)
print(progress, percentage);
print(progress, percentage)
txtConvertNumber.text = percentage + "%";
txtConvertNumber.text = percentage + "%"
}
target: ScreenPlay.create
@ -116,7 +119,6 @@ Item {
margins: 40
bottomMargin: 0
}
}
Item {
@ -186,9 +188,7 @@ Item {
position: 1
color: "#00000000"
}
}
}
BusyIndicator {
@ -211,7 +211,6 @@ Item {
bottom: parent.bottom
bottomMargin: 40
}
}
Text {
@ -227,9 +226,7 @@ Item {
bottom: parent.bottom
bottomMargin: 20
}
}
}
Common.ImageSelector {
@ -243,9 +240,7 @@ Item {
left: parent.left
bottom: parent.bottom
}
}
}
Item {
@ -283,9 +278,9 @@ Item {
Layout.fillWidth: true
onTextChanged: {
if (textFieldName.text.length >= 3)
canSave = true;
canSave = true
else
canSave = false;
canSave = false
}
}
@ -311,7 +306,6 @@ Item {
width: parent.width
Layout.fillWidth: true
}
}
Row {
@ -336,14 +330,14 @@ Item {
Material.foreground: "white"
font.family: ScreenPlay.settings.font
onClicked: {
root.abort();
ScreenPlay.create.abortAndCleanup();
root.abort()
ScreenPlay.create.cancel()
}
}
Button {
id: btnSave
objectName: "btnSave"
text: qsTr("Save")
enabled: false
Material.background: Material.accent
@ -351,16 +345,18 @@ Item {
font.family: ScreenPlay.settings.font
onClicked: {
if (conversionFinishedSuccessful) {
btnSave.enabled = false;
ScreenPlay.create.saveWallpaper(textFieldName.text, textFieldDescription.text, root.filePath, previewSelector.imageSource, textFieldYoutubeURL.text, codec, textFieldTags.getTags());
savePopup.open();
ScreenPlay.installedListModel.reset();
btnSave.enabled = false
ScreenPlay.create.saveWallpaper(
textFieldName.text,
textFieldDescription.text, root.filePath,
previewSelector.imageSource,
textFieldYoutubeURL.text, codec,
textFieldTags.getTags())
savePopup.open()
}
}
}
}
}
Popup {
@ -392,12 +388,10 @@ Item {
interval: 1000 + Math.random() * 1000
onTriggered: {
savePopup.close();
ScreenPlay.util.setNavigationActive(true);
ScreenPlay.util.setNavigation("Installed");
savePopup.close()
ScreenPlay.util.setNavigationActive(true)
ScreenPlay.util.setNavigation("Installed")
}
}
}
}

View File

@ -26,7 +26,7 @@ Item {
swipeView.currentIndex = 1;
createWallpaperVideoImportConvert.filePath = filePath;
ScreenPlay.util.setNavigationActive(false);
ScreenPlay.create.createWallpaperStart(filePath, Create.VP9);
ScreenPlay.create.createWallpaperStart(filePath);
}
}

View File

@ -5,6 +5,7 @@ import QtQuick.Controls.Material 2.3
import QtQuick.Layouts 1.12
import ScreenPlay 1.0
import ScreenPlay.Create 1.0
import ScreenPlay.Enums.ImportVideoState 1.0
import "../../../Common" as Common
Item {
@ -38,47 +39,48 @@ Item {
Connections {
function onCreateWallpaperStateChanged(state) {
switch (state) {
case CreateImportVideo.AnalyseVideo:
case ImportVideoState.AnalyseVideo:
txtConvert.text = qsTr("AnalyseVideo...");
break;
case CreateImportVideo.ConvertingPreviewImage:
case ImportVideoState.ConvertingPreviewImage:
txtConvert.text = qsTr("Generating preview image...");
break;
case CreateImportVideo.ConvertingPreviewThumbnailImage:
case ImportVideoState.ConvertingPreviewThumbnailImage:
txtConvert.text = qsTr("Generating preview thumbnail image...");
break;
case CreateImportVideo.ConvertingPreviewImageFinished:
case ImportVideoState.ConvertingPreviewImageFinished:
imgPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.jpg";
imgPreview.visible = true;
break;
case CreateImportVideo.ConvertingPreviewVideo:
case ImportVideoState.ConvertingPreviewVideo:
txtConvert.text = qsTr("Generating 5 second preview video...");
break;
case CreateImportVideo.ConvertingPreviewGif:
case ImportVideoState.ConvertingPreviewGif:
txtConvert.text = qsTr("Generating preview gif...");
break;
case CreateImportVideo.ConvertingPreviewGifFinished:
case ImportVideoState.ConvertingPreviewGifFinished:
gifPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.gif";
imgPreview.visible = false;
gifPreview.visible = true;
gifPreview.playing = true;
break;
case CreateImportVideo.ConvertingAudio:
case ImportVideoState.ConvertingAudio:
txtConvert.text = qsTr("Converting Audio...");
break;
case CreateImportVideo.ConvertingVideo:
case ImportVideoState.ConvertingVideo:
txtConvert.text = qsTr("Converting Video... This can take some time!");
break;
case CreateImportVideo.ConvertingVideoError:
case ImportVideoState.ConvertingVideoError:
txtConvert.text = qsTr("Converting Video ERROR!");
break;
case CreateImportVideo.AnalyseVideoError:
case ImportVideoState.AnalyseVideoError:
txtConvert.text = qsTr("Analyse Video ERROR!");
break;
case CreateImportVideo.Finished:
case ImportVideoState.Finished:
txtConvert.text = "";
conversionFinishedSuccessful = true;
busyIndicator.running = false;
btnExit.enabled = false;
root.checkCanSave();
break;
}
@ -330,13 +332,13 @@ Item {
font.family: ScreenPlay.settings.font
onClicked: {
root.exit();
ScreenPlay.create.abortAndCleanup();
ScreenPlay.create.cancel();
}
}
Button {
id: btnSave
objectName: "btnSave"
text: qsTr("Save")
enabled: false
Material.background: Material.accent
@ -347,7 +349,6 @@ Item {
btnSave.enabled = false;
ScreenPlay.create.saveWallpaper(textFieldName.text, textFieldDescription.text, root.filePath, previewSelector.imageSource, textFieldYoutubeURL.text, Create.VP9, textFieldTags.getTags());
savePopup.open();
ScreenPlay.installedListModel.reset();
}
}
}

View File

@ -65,7 +65,7 @@ FocusScope {
Button {
id: btnSave
objectName: "btnSave"
text: qsTr("Save")
enabled: root.ready
Material.background: Material.accent

View File

@ -13,6 +13,7 @@ Item {
property bool refresh: false
property bool enabled: true
property Sidebar sidebar
signal setNavigationItem(var pos)
signal setSidebarActive(var active)
@ -85,6 +86,7 @@ Item {
GridView {
id: gridView
objectName: "gridView"
property bool isDragging: false
property bool isScrolling: gridView.verticalVelocity != 0
@ -101,6 +103,36 @@ Item {
onDragStarted: isDragging = true
onDragEnded: isDragging = false
model: ScreenPlay.installedListFilter
removeDisplaced: Transition {
SequentialAnimation {
PauseAnimation {
duration: 150
}
NumberAnimation {
properties: "x,y"
duration: 250
easing.type: Easing.InOutQuart
}
}
}
remove: Transition {
SequentialAnimation {
NumberAnimation {
property: "opacity"
to: 0
duration: 200
easing.type: Easing.InOutQuart
}
NumberAnimation {
properties: "y"
to: 100
duration: 200
easing.type: Easing.InOutQuart
}
}
}
onContentYChanged: {
if (contentY <= -180)
gridView.headerItem.isVisible = true;
@ -202,10 +234,11 @@ Item {
delegate: ScreenPlayItem {
id: delegate
objectName: "installedItem" + index
focus: true
customTitle: m_title
type: m_type
isNew: m_isNew
screenId: m_folderId
absoluteStoragePath: m_absoluteStoragePath
publishedFileID: m_publishedFileID
@ -215,7 +248,6 @@ Item {
// Set the menu to the current item informations
contextMenu.publishedFileID = delegate.publishedFileID;
contextMenu.absoluteStoragePath = delegate.absoluteStoragePath;
deleteDialog.currentItemIndex = itemIndex;
const pos = delegate.mapToItem(root, position.x, position.y);
// Disable duplicate opening. The can happen if we
// call popup when we are in the closing animtion.
@ -234,51 +266,54 @@ Item {
Menu {
id: contextMenu
objectName: "installedItemContextMenu"
property var publishedFileID: 0
property url absoluteStoragePath
MenuItem {
text: qsTr("Open containing folder")
objectName: "openFolder"
icon.source: "qrc:/assets/icons/icon_folder_open.svg"
onClicked: {
ScreenPlay.util.openFolderInExplorer(contextMenu.absoluteStoragePath);
ScreenPlay.util.openFolderInExplorer(
contextMenu.absoluteStoragePath)
}
}
MenuItem {
text: qsTr("Deinstall Item")
text: enabled ? qsTr("Remove Item") : qsTr("Remove via Workshop")
objectName: enabled ? "removeItem" : "removeWorkshopItem"
icon.source: "qrc:/assets/icons/icon_delete.svg"
enabled: contextMenu.publishedFileID === 0
onClicked: {
deleteDialog.open();
deleteDialog.open()
}
}
MenuItem {
id: miWorkshop
text: qsTr("Open workshop Page")
text: qsTr("Open Workshop Page")
enabled: contextMenu.publishedFileID !== 0
icon.source: "qrc:/assets/icons/icon_steam.svg"
onClicked: {
Qt.openUrlExternally("steam://url/CommunityFilePage/" + publishedFileID);
Qt.openUrlExternally(
"steam://url/CommunityFilePage/" + contextMenu.publishedFileID)
}
}
}
Dialog {
id: deleteDialog
property int currentItemIndex: 0
title: qsTr("Are you sure you want to delete this item?")
standardButtons: Dialog.Ok | Dialog.Cancel
modal: true
dim: true
anchors.centerIn: Overlay.overlay
onAccepted: ScreenPlay.installedListModel.deinstallItemAt(currentItemIndex)
onAccepted: {
root.sidebar.clear()
ScreenPlay.installedListModel.deinstallItemAt(
contextMenu.absoluteStoragePath)
}
}
Navigation {
@ -289,7 +324,5 @@ Item {
right: parent.right
left: parent.left
}
}
}

View File

@ -17,6 +17,7 @@ Item {
property var publishedFileID: 0
property int itemIndex
property bool isScrolling: false
property bool isNew: false
signal openContextMenu(point position)
@ -24,16 +25,16 @@ Item {
height: 180
onTypeChanged: {
if (JSUtil.isWidget(type)) {
icnType.source = "qrc:/assets/icons/icon_widgets.svg";
return ;
icnType.source = "qrc:/assets/icons/icon_widgets.svg"
return
}
if (JSUtil.isScene(type)) {
icnType.source = "qrc:/assets/icons/icon_code.svg";
return ;
icnType.source = "qrc:/assets/icons/icon_code.svg"
return
}
if (JSUtil.isVideo(type)) {
icnType.source = "qrc:/assets/icons/icon_movie.svg";
return ;
icnType.source = "qrc:/assets/icons/icon_movie.svg"
return
}
}
@ -41,11 +42,11 @@ Item {
running: true
onTriggered: showAnim.start()
interval: {
var itemIndexMax = itemIndex;
var itemIndexMax = itemIndex
if (itemIndex > 30)
itemIndexMax = 3;
itemIndexMax = 3
5 * itemIndexMax * Math.random();
5 * itemIndexMax * Math.random()
}
}
@ -78,7 +79,6 @@ Item {
duration: 200
easing.type: Easing.OutCirc
}
}
OpacityAnimator {
@ -88,7 +88,6 @@ Item {
duration: 800
easing.type: Easing.OutCirc
}
}
RectangularGlow {
@ -107,7 +106,6 @@ Item {
top: parent.top
topMargin: 3
}
}
Item {
@ -174,22 +172,37 @@ Item {
left: parent.left
margins: 10
}
}
Rectangle {
color: "#AAffffff"
height: 30
visible: false
anchors {
right: parent.right
left: parent.left
bottom: parent.bottom
width: 120
height: 20
anchors{
top:parent.top
right:parent.right
rightMargin: -60
topMargin: -20
}
color: Material.color(Material.Orange)
transform: Rotation {
angle: 45
}
visible: root.isNew
Text {
font.family: ScreenPlay.settings.font
font.pointSize: 9
renderType: Text.QtRendering
color: "white"
text: qsTr("NEW")
smooth: true
antialiasing: true
visible: root.isNew
anchors.centerIn: parent
}
}
}
OpacityMask {
@ -203,25 +216,23 @@ Item {
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onEntered: {
root.state = "hover";
screenPlayItemImage.state = "hover";
screenPlayItemImage.enter();
root.state = "hover"
screenPlayItemImage.state = "hover"
screenPlayItemImage.enter()
}
onExited: {
root.state = "";
screenPlayItemImage.state = "loaded";
screenPlayItemImage.exit();
root.state = ""
screenPlayItemImage.state = "loaded"
screenPlayItemImage.exit()
}
onClicked: (mouse)=> {
if (mouse.button === Qt.LeftButton)
ScreenPlay.util.setSidebarItem(root.screenId, root.type);
ScreenPlay.util.setSidebarItem(root.screenId, root.type)
else if (mouse.button === Qt.RightButton)
root.openContextMenu(Qt.point(mouseX, mouseY));
root.openContextMenu(Qt.point(mouseX, mouseY))
}
}
}
}
transitions: [
@ -256,7 +267,6 @@ Item {
from: 0.6
to: 1
}
},
Transition {
from: "hover"
@ -289,7 +299,6 @@ Item {
from: 1
to: 0.5
}
}
]
}

View File

@ -28,6 +28,14 @@ Item {
return -1;
}
// This is used for removing wallpaper. We need to clear
// the preview image/gif so we can release the file for deletion.
function clear(){
image.source = ""
txtHeadline.text = ""
root.state = "inactive"
}
width: 400
state: "inactive"
onContentFolderNameChanged: {
@ -47,8 +55,10 @@ Item {
btnSetWallpaper.enabled = false;
}
Connections {
function onSetSidebarItem(folderName, type) {
// Toggle sidebar if clicked on the same content twice
if (root.contentFolderName === folderName && root.state !== "inactive") {
root.state = "inactive";
@ -151,10 +161,12 @@ Item {
AnimatedImage {
id: image
// Do NOT enable async image loading!
// Otherwhise it will still hold the file
// when calling InstalledListModel::deinstallItemAt
asynchronous: false
playing: true
fillMode: Image.PreserveAspectCrop
asynchronous: true
anchors.fill: parent
onStatusChanged: {
if (image.status === Image.Error)
@ -262,6 +274,7 @@ Item {
MonitorSelection {
id: monitorSelection
objectName: "monitorSelection"
height: 180
Layout.fillWidth: true
@ -346,6 +359,7 @@ Item {
Button {
id: btnSetWallpaper
objectName: "btnSetWallpaper"
Material.background: Material.accent
Material.foreground: "white"

View File

@ -80,6 +80,7 @@ Rectangle {
name: "Create"
iconSource: "qrc:/assets/icons/icon_plus.svg"
onPageClicked: (name)=> {root.onPageChanged(name)}
objectName: "createTab"
}
NavigationItem {
@ -89,6 +90,7 @@ Rectangle {
name: "Workshop"
iconSource: "qrc:/assets/icons/icon_steam.svg"
onPageClicked: (name)=> {root.onPageChanged(name)}
objectName: "workshopTab"
}
NavigationItem {
@ -99,6 +101,7 @@ Rectangle {
amount: ScreenPlay.installedListModel.count
iconSource: "qrc:/assets/icons/icon_installed.svg"
onPageClicked: (name)=> {root.onPageChanged(name)}
objectName: "installedTab"
}
NavigationItem {
@ -108,6 +111,7 @@ Rectangle {
name: "Community"
iconSource: "qrc:/assets/icons/icon_community.svg"
onPageClicked: (name)=> {root.onPageChanged(name)}
objectName: "communityTab"
}
NavigationItem {
@ -117,6 +121,7 @@ Rectangle {
name: "Settings"
iconSource: "qrc:/assets/icons/icon_settings.svg"
onPageClicked: (name)=> {root.onPageChanged(name)}
objectName: "settingsTab"
}
}

View File

@ -6,96 +6,122 @@ import ScreenPlay 1.0
import "../Common"
Item {
id: navigationWallpaperConfiguration
id: root
width: 450
states: []
transitions: []
width: 390
property bool active: ScreenPlay.screenPlayManager.activeWallpaperCounter > 0
anchors {
top: parent.top
right: parent.right
rightMargin: 20
bottom: parent.bottom
}
RippleEffect {
id: rippleEffect
target: navigationWallpaperConfiguration
}
Connections {
function onActiveWallpaperCounterChanged() {
rippleEffect.trigger();
rippleEffect.trigger()
}
target: ScreenPlay.screenPlayManager
}
Image {
id: image
Pane {
anchors.centerIn: parent
contentWidth: activeMonitorName.contentWidth + image.width + 80
contentHeight: parent.height - 10
background: Item {
Rectangle {
id: bg
clip: true
anchors {
fill: parent
margins: 16
}
color: "transparent"
border.color: root.active ? Material.accentColor : Material.iconDisabledColor
border.width: 1
radius: 3
}
width: 24
height: 24
source: "qrc:/assets/icons/icon_monitor.svg"
RippleEffect {
id: rippleEffect
anchors {
rightMargin: 30
right: parent.right
verticalCenter: parent.verticalCenter
target: bg
}
}
Behavior on contentWidth {
PropertyAnimation {
duration: 250
easing.type: Easing.InOutQuart
}
}
Text {
id: txtAmountActiveWallpapers
id: activeMonitorName
text: ScreenPlay.screenPlayManager.activeWallpaperCounter + ScreenPlay.screenPlayManager.activeWidgetsCounter
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: Material.accent
font.pointSize: 10
font.bold: true
horizontalAlignment: Text.AlignRight
color: root.active ? Material.primaryTextColor : Material.iconDisabledColor
font.pointSize: 12
font.family: ScreenPlay.settings.font
text: root.active ? qsTr("Configurate active Wallpaper or Widgets") : qsTr(
"No active Wallpaper or Widgets")
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: 1
right: image.right
rightMargin: 50
verticalCenter: parent.verticalCenter
}
}
Image {
id: image
width: 28
height: 24
source: "qrc:/assets/icons/icon_monitor.svg"
layer {
effect: ColorOverlay {
color: root.active ? Material.color(
Material.Orange) : Material.iconDisabledColor
}
}
anchors {
rightMargin: 30
right: parent.right
verticalCenter: parent.verticalCenter
}
Text {
id: txtAmountActiveWallpapers
text: ScreenPlay.screenPlayManager.activeWallpaperCounter
+ ScreenPlay.screenPlayManager.activeWidgetsCounter
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: root.active ? Material.color(
Material.Orange) : Material.iconDisabledColor
font.pointSize: 10
font.bold: true
font.family: ScreenPlay.settings.font
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
bottomMargin: 7
}
}
}
}
MouseArea {
id: ma
Text {
id: activeMonitorName
horizontalAlignment: Text.AlignRight
color: Material.foreground
font.pointSize: 12
font.family: ScreenPlay.settings.font
text: {
if (ScreenPlay.screenPlayManager.activeWallpaperCounter > 0)
return qsTr("Configurate active Wallpaper or Widgets");
else
return qsTr("No active Wallpaper or Widgets");
}
anchors {
right: image.right
rightMargin: 30
verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: ma
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
ScreenPlay.util.setToggleWallpaperConfiguration();
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
ScreenPlay.util.setToggleWallpaperConfiguration()
}
}
}
}

View File

@ -15,6 +15,9 @@ Popup {
anchors.centerIn: Overlay.overlay
dim: true
property ScreenPlayWorkshop workshop
property SteamWorkshop steam
Text {
id: txtOffline
@ -22,7 +25,7 @@ Popup {
font.family: ScreenPlay.settings.font
font.pointSize: 21
color: Material.foreground
text: qsTr("You need to run Steam for this :)")
text: qsTr("You need to run Steam for this. steamErrorRestart: %1 - steamErrorAPIInit: %2").arg(steam.steamErrorRestart).arg(steam.steamErrorAPIInit)
}
Button {

View File

@ -10,12 +10,14 @@ Item {
id: root
ScreenPlayWorkshop {
id: workshop
id: ws
Component.onCompleted: {
if (online) {
const success = ws.init();
if(success){
stackView.push("qrc:/qml/Workshop/SteamWorkshop.qml", {
"workshop": workshop,
"steam": workshop.steamWorkshop
"workshop": ws,
"steam": ws.steamWorkshop
})
} else {
popupOffline.open()
@ -25,6 +27,8 @@ Item {
PopupOffline {
id: popupOffline
workshop: ws
steam: ws.steamWorkshop
}
StackView {
@ -37,8 +41,8 @@ Item {
ignoreUnknownSignals: true
function onOpenSteamProfile(){
stackView.push("qrc:/qml/Workshop/SteamProfile.qml", {
"workshop": workshop,
"steam": workshop.steamWorkshop
"workshop": ws,
"steam": ws.steamWorkshop
})
}
function onRequestWorkshopMainPage(){

View File

@ -10,23 +10,16 @@ namespace ScreenPlay {
As for this writing (April 2019) it is solely used to import webm wallpaper
and create the gif/web 5 second previews.
*/
/*!
Constructor.
*/
Create::Create(const std::shared_ptr<GlobalVariables>& globalVariables, QObject* parent)
: QObject(parent)
Create::Create(const std::shared_ptr<GlobalVariables>& globalVariables)
: QObject(nullptr)
, m_globalVariables(globalVariables)
{
qRegisterMetaType<CreateImportVideo::ImportVideoState>("CreateImportVideo::ImportVideoState");
qRegisterMetaType<Create::VideoCodec>("Create::VideoCodec");
qmlRegisterUncreatableType<CreateImportVideo>("ScreenPlay.Create", 1, 0, "CreateImportVideo", "Error only for enums");
qmlRegisterUncreatableType<Create>("ScreenPlay.Create", 1, 0, "VideoCodec", "Error only for enums");
qmlRegisterType<Create>("ScreenPlay.Create", 1, 0, "Create");
init();
}
/*!
@ -35,11 +28,29 @@ Create::Create(const std::shared_ptr<GlobalVariables>& globalVariables, QObject*
Create::Create()
: QObject(nullptr)
{
qRegisterMetaType<CreateImportVideo::ImportVideoState>("CreateImportVideo::ImportVideoState");
init();
}
void Create::init()
{
qRegisterMetaType<Create::VideoCodec>("Create::VideoCodec");
qmlRegisterUncreatableType<ScreenPlay::CreateImportVideo>("ScreenPlay.Create", 1, 0, "CreateImportVideo", "Error only for enums");
qmlRegisterUncreatableType<Create>("ScreenPlay.Create", 1, 0, "VideoCodec", "Error only for enums");
qmlRegisterType<Create>("ScreenPlay.Create", 1, 0, "Create");
qRegisterMetaType<ImportVideoState::ImportVideoState>("ImportVideoState::ImportVideoState");
qmlRegisterUncreatableMetaObject(ScreenPlay::ImportVideoState::staticMetaObject,
"ScreenPlay.Enums.ImportVideoState",
1, 0,
"ImportVideoState",
"Error: only enums");
}
void Create::reset()
{
clearFfmpegOutput();
m_interrupt = false;
setProgress(0.);
setWorkingDir({});
}
/*!
@ -47,20 +58,22 @@ Create::Create()
*/
void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, const int quality)
{
clearFfmpegOutput();
reset();
videoPath = ScreenPlayUtil::toLocal(videoPath);
const QDir dir(m_globalVariables->localStoragePath().toLocalFile());
const QDir installedDir = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString());
// Create a temp dir so we can later alter it to the workshop id
const auto folderName = QString("_tmp_" + QTime::currentTime().toString()).replace(":", "");
const QDateTime date = QDateTime::currentDateTime();
const auto folderName = date.toString("ddMMyyyyhhmmss");
setWorkingDir(installedDir.path() + "/" + folderName);
if (!dir.mkdir(folderName)) {
emit createWallpaperStateChanged(CreateImportVideo::ImportVideoState::CreateTmpFolderError);
if (!installedDir.mkdir(folderName)) {
qInfo() << "Unable to create folder with name: " << folderName << " at: " << installedDir;
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CreateTmpFolderError);
emit abortCreateWallpaper();
return;
}
setWorkingDir(dir.path() + "/" + folderName);
QString target_codec;
switch (codec) {
@ -75,34 +88,103 @@ void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, c
break;
}
m_createImportVideoThread = new QThread(this);
m_createImportVideo = new CreateImportVideo(videoPath, workingDir(), target_codec, quality);
connect(m_createImportVideo, &CreateImportVideo::processOutput, this, [this](QString text) {
appendFfmpegOutput(text + "\n");
m_createImportFuture = QtConcurrent::run(QThreadPool::globalInstance(), [videoPath, target_codec, quality, this]() {
CreateImportVideo import(videoPath, workingDir(), target_codec, quality, m_interrupt);
QObject::connect(&import, &CreateImportVideo::createWallpaperStateChanged, this, &Create::createWallpaperStateChanged, Qt::ConnectionType::QueuedConnection);
QObject::connect(&import, &CreateImportVideo::abortAndCleanup, this, &Create::abortAndCleanup, Qt::ConnectionType::QueuedConnection);
QObject::connect(
&import, &CreateImportVideo::processOutput, this, [this](const QString text) {
appendFfmpegOutput(text + "\n");
},
Qt::ConnectionType::QueuedConnection);
if (!import.createWallpaperInfo() || m_interrupt) {
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed);
emit import.abortAndCleanup();
return;
}
qInfo() << "createWallpaperImageThumbnailPreview()";
if (!import.createWallpaperImageThumbnailPreview() || m_interrupt) {
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed);
emit import.abortAndCleanup();
return;
}
qInfo() << "createWallpaperImagePreview()";
if (!import.createWallpaperImagePreview() || m_interrupt) {
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed);
emit import.abortAndCleanup();
return;
}
// Skip preview convert for webm
if (!import.m_isWebm) {
qInfo() << "createWallpaperVideoPreview()";
if (!import.createWallpaperVideoPreview() || m_interrupt) {
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed);
emit import.abortAndCleanup();
return;
}
}
qInfo() << "createWallpaperGifPreview()";
if (!import.createWallpaperGifPreview() || m_interrupt) {
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed);
emit import.abortAndCleanup();
return;
}
// If the video has no audio we can skip the extraction
if (!import.m_skipAudio) {
qInfo() << "extractWallpaperAudio()";
if (!import.extractWallpaperAudio() || m_interrupt) {
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed);
emit import.abortAndCleanup();
return;
}
}
// Skip convert for webm
if (import.m_isWebm) {
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Finished);
return;
}
qInfo() << "createWallpaperVideo()";
if (!import.createWallpaperVideo() || m_interrupt) {
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed);
emit import.abortAndCleanup();
return;
}
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Finished);
});
connect(m_createImportVideo, &CreateImportVideo::createWallpaperStateChanged, this, &Create::createWallpaperStateChanged);
connect(m_createImportVideo, &CreateImportVideo::progressChanged, this, &Create::setProgress);
connect(m_createImportVideoThread, &QThread::started, m_createImportVideo, &CreateImportVideo::process);
connect(m_createImportVideo, &CreateImportVideo::abortAndCleanup, this, &Create::abortAndCleanup);
QObject::connect(&m_createImportFutureWatcher, &QFutureWatcherBase::finished, this, [this]() {
if (m_interrupt)
abortAndCleanup();
});
connect(m_createImportVideo, &CreateImportVideo::finished, m_createImportVideoThread, &QThread::quit);
connect(m_createImportVideo, &CreateImportVideo::finished, m_createImportVideo, &QObject::deleteLater);
connect(m_createImportVideoThread, &QThread::finished, m_createImportVideoThread, &QObject::deleteLater);
m_createImportVideo->moveToThread(m_createImportVideoThread);
m_createImportVideoThread->start();
m_createImportFutureWatcher.setFuture(m_createImportFuture);
}
/*!
\brief When converting of the wallpaper steps where successful.
*/
void Create::saveWallpaper(QString title, QString description, QString filePath, QString previewImagePath, QString youtube, Create::VideoCodec codec, QVector<QString> tags)
void Create::saveWallpaper(
const QString title,
const QString description,
QString filePath,
QString previewImagePath,
const QString youtube,
const Create::VideoCodec codec,
const QVector<QString> tags)
{
filePath = ScreenPlayUtil::toLocal(filePath);
previewImagePath = ScreenPlayUtil::toLocal(previewImagePath);
emit createWallpaperStateChanged(CreateImportVideo::ImportVideoState::CopyFiles);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CopyFiles);
// Case when the selected users preview image has the same name as
// our default "preview.jpg" name. QFile::copy does no override exsisting files
@ -111,7 +193,7 @@ void Create::saveWallpaper(QString title, QString description, QString filePath,
if (userSelectedPreviewImage.fileName() == "preview.jpg") {
if (!userSelectedPreviewImage.remove()) {
qDebug() << "Could remove" << previewImagePath;
emit createWallpaperStateChanged(CreateImportVideo::ImportVideoState::CopyFilesError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CopyFilesError);
}
}
@ -119,7 +201,7 @@ void Create::saveWallpaper(QString title, QString description, QString filePath,
if (previewImageFile.exists()) {
if (!QFile::copy(previewImagePath, m_workingDir + "/" + previewImageFile.fileName())) {
qDebug() << "Could not copy" << previewImagePath << " to " << m_workingDir + "/" + previewImageFile.fileName();
emit createWallpaperStateChanged(CreateImportVideo::ImportVideoState::CopyFilesError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CopyFilesError);
return;
}
}
@ -128,19 +210,19 @@ void Create::saveWallpaper(QString title, QString description, QString filePath,
if (filePath.endsWith(".webm")) {
if (!QFile::copy(filePath, m_workingDir + "/" + filePathFile.fileName())) {
qDebug() << "Could not copy" << filePath << " to " << m_workingDir + "/" + filePathFile.fileName();
emit createWallpaperStateChanged(CreateImportVideo::ImportVideoState::CopyFilesError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CopyFilesError);
return;
}
}
emit createWallpaperStateChanged(CreateImportVideo::ImportVideoState::CopyFilesFinished);
emit createWallpaperStateChanged(CreateImportVideo::ImportVideoState::CreateProjectFile);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CopyFilesFinished);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CreateProjectFile);
QJsonObject obj;
obj.insert("description", description);
obj.insert("title", title);
obj.insert("youtube", youtube);
obj.insert("videoCodec", codec == Create::VideoCodec::VP8 ? "vp8" : "vp9");
obj.insert("file", filePathFile.fileName());
obj.insert("file", filePathFile.completeBaseName() + ".webm");
obj.insert("previewGIF", "preview.gif");
obj.insert("previewWEBM", "preview.webm");
obj.insert("preview", previewImageFile.exists() ? previewImageFile.fileName() : "preview.jpg");
@ -155,11 +237,21 @@ void Create::saveWallpaper(QString title, QString description, QString filePath,
}
if (!Util::writeSettings(std::move(obj), m_workingDir + "/project.json")) {
emit createWallpaperStateChanged(CreateImportVideo::ImportVideoState::CreateProjectFileError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CreateProjectFileError);
return;
}
emit createWallpaperStateChanged(CreateImportVideo::ImportVideoState::CreateProjectFileFinished);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CreateProjectFileFinished);
emit finished();
}
/*!
\brief This method is called from qml.
*/
void Create::cancel()
{
qInfo() << "cancel()";
m_interrupt = true;
}
/*!
@ -167,36 +259,15 @@ void Create::saveWallpaper(QString title, QString description, QString filePath,
*/
void Create::abortAndCleanup()
{
qWarning() << "Abort and Cleanup!";
if (m_createImportVideo == nullptr || m_createImportVideoThread == nullptr) {
qDebug() << m_createImportVideo << m_createImportVideoThread;
return;
}
// disconnect(m_createImportVideo);
// disconnect(m_createImportVideoThread);
// Save to export path before aborting to be able to cleanup the tmp folder
QString tmpExportPath = m_createImportVideo->m_exportPath;
connect(m_createImportVideoThread, &QThread::finished, this, [=]() {
QDir exportPath(tmpExportPath);
qWarning() << "Abort and Cleanup!" << exportPath;
if (exportPath.exists()) {
if (!exportPath.removeRecursively()) {
emit createWallpaperStateChanged(CreateImportVideo::ImportVideoState::AbortCleanupError);
qWarning() << "Could not delete temp exportPath: " << exportPath;
} else {
qDebug() << "cleanup " << tmpExportPath;
}
} else {
qDebug() << "Could not cleanup and delete: " << exportPath;
QDir exportPath(m_workingDir);
if (exportPath.exists()) {
if (!exportPath.removeRecursively()) {
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AbortCleanupError);
qWarning() << "Could not delete temp exportPath: " << exportPath;
}
m_createImportVideo = nullptr;
m_createImportVideoThread = nullptr;
});
m_createImportVideoThread->requestInterruption();
} else {
qWarning() << "Could not cleanup video import. Export path does not exist: " << exportPath;
}
}
}

View File

@ -71,9 +71,7 @@ class Create : public QObject {
Q_PROPERTY(QString ffmpegOutput READ ffmpegOutput WRITE appendFfmpegOutput NOTIFY ffmpegOutputChanged)
public:
explicit Create(
const std::shared_ptr<GlobalVariables>& globalVariables,
QObject* parent = nullptr);
explicit Create(const std::shared_ptr<GlobalVariables>& globalVariables);
Create();
@ -85,32 +83,31 @@ public:
Q_ENUM(VideoCodec)
float progress() const { return m_progress; }
QString workingDir() const { return m_workingDir; }
QString ffmpegOutput() const { return m_ffmpegOutput; }
signals:
void createWallpaperStateChanged(CreateImportVideo::ImportVideoState state);
void createWallpaperStateChanged(ImportVideoState::ImportVideoState state);
void progressChanged(float progress);
void abortCreateWallpaper();
void workingDirChanged(QString workingDir);
void ffmpegOutputChanged(QString ffmpegOutput);
void widgetCreatedSuccessful(QString path);
void htmlWallpaperCreatedSuccessful(QString path);
void finished();
public slots:
void cancel();
void createWallpaperStart(QString videoPath, Create::VideoCodec codec, const int quality = 50);
void createWallpaperStart(QString videoPath, Create::VideoCodec codec = Create::VideoCodec::VP9, const int quality = 50);
void saveWallpaper(
QString title,
QString description,
void saveWallpaper(const QString title,
const QString description,
QString filePath,
QString previewImagePath,
QString youtube,
ScreenPlay::Create::VideoCodec codec,
QVector<QString> tags);
const QString youtube,
const ScreenPlay::Create::VideoCodec codec,
const QVector<QString> tags);
void abortAndCleanup();
@ -145,13 +142,18 @@ public slots:
}
private:
CreateImportVideo* m_createImportVideo { nullptr };
QThread* m_createImportVideoThread { nullptr };
void init();
void reset();
private:
const std::shared_ptr<GlobalVariables> m_globalVariables;
float m_progress { 0.0F };
QString m_workingDir;
QString m_ffmpegOutput;
std::atomic<bool> m_interrupt;
QFuture<void> m_createImportFuture;
QFutureWatcher<void> m_createImportFutureWatcher;
};
}

View File

@ -0,0 +1,52 @@
#pragma once
#include <QObject>
namespace ScreenPlay {
/*!
\namespace ScreenPlay::ImportVideoState
\inmodule ScreenPlay
\brief Global enum for ImportVideoState.
*/
namespace ImportVideoState {
Q_NAMESPACE
enum class ImportVideoState {
Idle,
Started,
AnalyseVideo,
AnalyseVideoFinished,
AnalyseVideoError,
AnalyseVideoHasNoVideoStreamError,
ConvertingPreviewVideo,
ConvertingPreviewVideoFinished,
ConvertingPreviewVideoError,
ConvertingPreviewGif,
ConvertingPreviewGifFinished, //10
ConvertingPreviewGifError,
ConvertingPreviewImage,
ConvertingPreviewImageFinished,
ConvertingPreviewImageError,
ConvertingPreviewImageThumbnail,
ConvertingPreviewImageThumbnailFinished,
ConvertingPreviewImageThumbnailError,
ConvertingAudio,
ConvertingAudioFinished,
ConvertingAudioError, //20
ConvertingVideo,
ConvertingVideoFinished,
ConvertingVideoError,
CopyFiles,
CopyFilesFinished,
CopyFilesError,
CreateProjectFile,
CreateProjectFileFinished,
CreateProjectFileError,
AbortCleanupError, //30
CreateTmpFolderError,
Finished,
Failed,
};
Q_ENUM_NS(ImportVideoState)
}
}

View File

@ -17,21 +17,23 @@ namespace ScreenPlay {
/*!
\brief This constructor is only needed for calling qRegisterMetaType on CreateImportVideo to register the enums.
\code
qRegisterMetaType<CreateImportVideo::ImportVideoState>("CreateImportVideo::ImportVideoState");
qRegisterMetaType<ImportVideoState::ImportVideoState>("ImportVideoState::ImportVideoState");
\endcode
*/
CreateImportVideo::CreateImportVideo(QObject* parent)
: QObject(parent)
{
}
/*!
\brief Creates a CreateImportVideo object to be used in a different thread. A \a videoPath and a \a exportPath are
needed for convertion.
*/
CreateImportVideo::CreateImportVideo(const QString& videoPath, const QString& exportPath, const QString& codec, const int quality, QObject* parent)
: QObject(parent)
CreateImportVideo::CreateImportVideo(
const QString& videoPath,
const QString& exportPath,
const QString& codec,
const int quality,
std::atomic<bool>& interrupt)
: QObject(nullptr)
, m_quality(quality)
, m_interrupt(interrupt)
{
m_videoPath = videoPath;
m_exportPath = exportPath;
@ -48,90 +50,6 @@ CreateImportVideo::CreateImportVideo(const QString& videoPath, const QString& ex
}
}
/*!
\brief Processes the multiple steps of creating a wallpaper.
\list 1
\li createWallpaperInfo()
\li createWallpaperImagePreview()
\li createWallpaperVideoPreview()
\li createWallpaperGifPreview()
\li createWallpaperVideo() - skiped if already a webm
\li extractWallpaperAudio() - skiped if no audio
\li emit createWallpaperStateChanged(ImportVideoState::Finished);
\endlist
*/
void CreateImportVideo::process()
{
qInfo() << "createWallpaperInfo()" << m_videoPath << m_exportPath << m_codec << m_ffmpegExecutable << m_ffprobeExecutable;
if (!createWallpaperInfo() || QThread::currentThread()->isInterruptionRequested()) {
emit abortAndCleanup();
return;
}
qInfo() << "createWallpaperImageThumbnailPreview()";
if (!createWallpaperImageThumbnailPreview() || QThread::currentThread()->isInterruptionRequested()) {
emit abortAndCleanup();
return;
}
qInfo() << "createWallpaperImagePreview()";
if (!createWallpaperImagePreview() || QThread::currentThread()->isInterruptionRequested()) {
emit abortAndCleanup();
return;
}
qInfo() << "createWallpaperVideoPreview()";
if (!createWallpaperVideoPreview() || QThread::currentThread()->isInterruptionRequested()) {
emit abortAndCleanup();
return;
}
qInfo() << "createWallpaperGifPreview()";
if (!createWallpaperGifPreview() || QThread::currentThread()->isInterruptionRequested()) {
emit abortAndCleanup();
return;
}
// If the video has no audio we can skip the extraction
if (!m_skipAudio) {
qInfo() << "extractWallpaperAudio()";
if (!extractWallpaperAudio() || QThread::currentThread()->isInterruptionRequested()) {
emit abortAndCleanup();
return;
}
}
if (m_isWebm) {
emit createWallpaperStateChanged(ImportVideoState::Finished);
return;
}
qInfo() << "createWallpaperVideo()";
if (!createWallpaperVideo() || QThread::currentThread()->isInterruptionRequested()) {
emit abortAndCleanup();
return;
}
emit createWallpaperStateChanged(ImportVideoState::Finished);
}
void CreateImportVideo::processGif()
{
qInfo() << "createWallpaperImageThumbnailPreview()";
if (!createWallpaperImageThumbnailPreview() || QThread::currentThread()->isInterruptionRequested()) {
emit abortAndCleanup();
return;
}
qInfo() << "createWallpaperImagePreview()";
if (!createWallpaperImagePreview() || QThread::currentThread()->isInterruptionRequested()) {
emit abortAndCleanup();
return;
}
emit createWallpaperStateChanged(ImportVideoState::Finished);
}
/*!
\brief Starts ffprobe and tries to parse the resulting json. If the video
is a container that not contains the video length like webm or mkv
@ -173,12 +91,12 @@ bool CreateImportVideo::createWallpaperInfo()
emit processOutput("ffprobe " + ScreenPlayUtil::toString(args));
emit createWallpaperStateChanged(ImportVideoState::AnalyseVideo);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideo);
const QString ffmpegOut = waitForFinished(args, QProcess::SeparateChannels, Executable::FFPROBE);
qInfo() << ffmpegOut;
emit createWallpaperStateChanged(ImportVideoState::AnalyseVideoFinished);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoFinished);
auto obj = ScreenPlayUtil::parseQByteArrayToQJsonObject(QByteArray::fromStdString(ffmpegOut.toStdString()));
@ -188,14 +106,14 @@ bool CreateImportVideo::createWallpaperInfo()
emit processOutput(ffmpegOut);
emit processOutput("Error parsing FFPROBE json output");
emit createWallpaperStateChanged(ImportVideoState::AnalyseVideoError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoError);
return false;
}
if (obj->empty()) {
qWarning() << "Error! File could not be parsed.";
emit processOutput("Error! File could not be parsed.");
emit createWallpaperStateChanged(ImportVideoState::AnalyseVideoError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoError);
return false;
}
@ -214,7 +132,7 @@ bool CreateImportVideo::createWallpaperInfo()
bool CreateImportVideo::analyzeWebmReadFrames(const QJsonObject& obj)
{
emit createWallpaperStateChanged(ImportVideoState::AnalyseVideo);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideo);
// Number of frames is a string for some reason...
if (!obj.value("streams").isArray()) {
@ -283,7 +201,7 @@ bool CreateImportVideo::analyzeVideo(const QJsonObject& obj)
if (!hasVideoStream) {
qDebug() << "Error! File has no video Stream!";
emit processOutput("Error! File has no video Stream!");
emit createWallpaperStateChanged(ImportVideoState::AnalyseVideoHasNoVideoStreamError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoHasNoVideoStreamError);
return false;
}
@ -299,7 +217,7 @@ bool CreateImportVideo::analyzeVideo(const QJsonObject& obj)
emit processOutput("Error parsing number of frames. Is this really a valid video File?");
QJsonDocument tmpVideoStreamDoc(videoStream);
emit processOutput(tmpVideoStreamDoc.toJson());
emit createWallpaperStateChanged(ImportVideoState::AnalyseVideoError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoError);
return false;
}
@ -312,7 +230,7 @@ bool CreateImportVideo::analyzeVideo(const QJsonObject& obj)
if (!okParseDuration) {
qDebug() << "Error parsing video length. Is this really a valid video File?";
emit processOutput("Error parsing video length. Is this really a valid video File?");
emit createWallpaperStateChanged(ImportVideoState::AnalyseVideoError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoError);
return false;
}
@ -373,7 +291,7 @@ bool CreateImportVideo::analyzeVideo(const QJsonObject& obj)
bool CreateImportVideo::createWallpaperVideoPreview()
{
emit createWallpaperStateChanged(ImportVideoState::ConvertingPreviewVideo);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewVideo);
QStringList args;
args.append("-y");
@ -397,13 +315,13 @@ bool CreateImportVideo::createWallpaperVideoPreview()
const QString ffmpegOut = waitForFinished(args);
const QFile previewVideo(m_exportPath + "/preview.webm");
if (!previewVideo.exists() || !(previewVideo.size() > 0)) {
emit createWallpaperStateChanged(ImportVideoState::ConvertingPreviewVideoError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewVideoError);
return false;
}
emit processOutput(ffmpegOut);
emit createWallpaperStateChanged(ImportVideoState::ConvertingPreviewVideoFinished);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewVideoFinished);
return true;
}
@ -425,13 +343,17 @@ bool CreateImportVideo::createWallpaperVideoPreview()
bool CreateImportVideo::createWallpaperGifPreview()
{
emit createWallpaperStateChanged(ImportVideoState::ConvertingPreviewGif);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewGif);
QStringList args;
args.append("-y");
args.append("-stats");
args.append("-i");
args.append(m_exportPath + "/preview.webm");
if (m_isWebm) {
args.append(m_videoPath);
} else {
args.append(m_exportPath + "/preview.webm");
}
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");
@ -442,13 +364,13 @@ bool CreateImportVideo::createWallpaperGifPreview()
if (!ffmpegOut.isEmpty()) {
const QFile previewGif(m_exportPath + "/preview.gif");
if (!previewGif.exists() || !(previewGif.size() > 0)) {
emit createWallpaperStateChanged(ImportVideoState::ConvertingPreviewGifError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewGifError);
return false;
}
}
emit processOutput(ffmpegOut);
emit createWallpaperStateChanged(ImportVideoState::ConvertingPreviewGifFinished);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewGifFinished);
return true;
}
@ -464,7 +386,7 @@ bool CreateImportVideo::createWallpaperGifPreview()
bool CreateImportVideo::createWallpaperImageThumbnailPreview()
{
emit createWallpaperStateChanged(ImportVideoState::ConvertingPreviewImageThumbnail);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewImageThumbnail);
QStringList args;
args.clear();
@ -500,13 +422,13 @@ bool CreateImportVideo::createWallpaperImageThumbnailPreview()
if (!ffmpegOut.isEmpty()) {
const QFile previewImg(m_exportPath + "/previewThumbnail.jpg");
if (!previewImg.exists() || !(previewImg.size() > 0)) {
emit createWallpaperStateChanged(ImportVideoState::ConvertingPreviewImageThumbnailError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewImageThumbnailError);
return false;
}
}
emit processOutput(ffmpegOut);
emit createWallpaperStateChanged(ImportVideoState::ConvertingPreviewImageThumbnailFinished);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewImageThumbnailFinished);
return true;
}
@ -517,7 +439,7 @@ bool CreateImportVideo::createWallpaperImageThumbnailPreview()
bool CreateImportVideo::createWallpaperImagePreview()
{
emit createWallpaperStateChanged(ImportVideoState::ConvertingPreviewImage);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewImage);
QStringList args;
args.clear();
@ -544,13 +466,13 @@ bool CreateImportVideo::createWallpaperImagePreview()
if (!ffmpegOut.isEmpty()) {
const QFile previewImg(m_exportPath + "/preview.jpg");
if (!previewImg.exists() || !(previewImg.size() > 0)) {
emit createWallpaperStateChanged(ImportVideoState::ConvertingPreviewImageError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewImageError);
return false;
}
}
emit processOutput(ffmpegOut);
emit createWallpaperStateChanged(ImportVideoState::ConvertingPreviewImageFinished);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewImageFinished);
return true;
}
@ -576,13 +498,13 @@ bool CreateImportVideo::createWallpaperImagePreview()
*/
bool CreateImportVideo::createWallpaperVideo()
{
emit createWallpaperStateChanged(ImportVideoState::ConvertingVideo);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingVideo);
connect(m_process.get(), &QProcess::readyReadStandardOutput, this, [&]() {
QString tmpOut = m_process->readAllStandardOutput();
qInfo() << tmpOut;
if (tmpOut.contains("Conversion failed!")) {
emit createWallpaperStateChanged(ImportVideoState::ConvertingVideoError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingVideoError);
}
const auto tmpList = tmpOut.split(QRegularExpression("\\s+"), Qt::SplitBehaviorFlags::SkipEmptyParts);
@ -614,7 +536,7 @@ bool CreateImportVideo::createWallpaperVideo()
if (m_codec == "av1")
args.append("libaom-av1");
args.append("-b:v");
args.append("3000k");
args.append("13000k");
args.append("-threads");
args.append(QString::number(QThread::idealThreadCount()));
qInfo() << "threads" << QThread::idealThreadCount() << "m_quality" << m_quality;
@ -657,7 +579,7 @@ bool CreateImportVideo::createWallpaperVideo()
if (m_codec == "av1")
args.append("libaom-av1");
args.append("-b:v");
args.append("3000k");
args.append("13000k");
args.append("-threads");
args.append(QString::number(QThread::idealThreadCount()));
args.append("-speed");
@ -675,7 +597,7 @@ bool CreateImportVideo::createWallpaperVideo()
args.append("-pass");
args.append("2");
const QFileInfo file(m_videoPath);
const QString convertedFileAbsolutePath { m_exportPath + "/" + file.baseName() + ".webm" };
const QString convertedFileAbsolutePath { m_exportPath + "/" + file.completeBaseName() + ".webm" };
args.append(convertedFileAbsolutePath);
const QString ffmpegOutput = waitForFinished(args);
@ -683,11 +605,11 @@ bool CreateImportVideo::createWallpaperVideo()
QFile video(convertedFileAbsolutePath);
if (!video.exists() || !(video.size() > 0)) {
qDebug() << convertedFileAbsolutePath << ffmpegOutput << video.exists() << video.size();
emit createWallpaperStateChanged(ImportVideoState::ConvertingVideoError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingVideoError);
return false;
}
emit createWallpaperStateChanged(ImportVideoState::ConvertingVideoFinished);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingVideoFinished);
return true;
}
@ -710,7 +632,7 @@ bool CreateImportVideo::createWallpaperVideo()
bool CreateImportVideo::extractWallpaperAudio()
{
emit createWallpaperStateChanged(ImportVideoState::ConvertingAudio);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingAudio);
QStringList args;
args.append("-y");
@ -731,13 +653,13 @@ bool CreateImportVideo::extractWallpaperAudio()
if (!previewImg.exists() || !(previewImg.size() > 0)) {
qDebug() << args;
qDebug() << tmpErrImg;
emit createWallpaperStateChanged(ImportVideoState::ConvertingAudioError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingAudioError);
return false;
}
}
emit processOutput(tmpErrImg);
emit createWallpaperStateChanged(ImportVideoState::ConvertingAudioFinished);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingAudioFinished);
return true;
}
@ -755,12 +677,20 @@ QString CreateImportVideo::waitForFinished(
m_process = std::make_unique<QProcess>();
QObject::connect(m_process.get(), &QProcess::errorOccurred, [=](QProcess::ProcessError error) {
qDebug() << "error enum val = " << error << m_process->errorString();
emit createWallpaperStateChanged(ImportVideoState::AnalyseVideoError);
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoError);
m_process->terminate();
if (!m_process->waitForFinished(1000)) {
m_process->kill();
}
});
QObject::connect(m_process.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[=](int exitCode, QProcess::ExitStatus exitStatus) {
qInfo() << "Process finished with exit code: " << exitCode;
if (exitCode != 0)
qWarning() << "Process finished with exit code: " << exitCode << " exitStatus:" << exitStatus;
});
if (executable == Executable::FFMPEG) {
m_process->setProgram(m_ffmpegExecutable);
} else {
@ -786,7 +716,7 @@ QString CreateImportVideo::waitForFinished(
while (!m_process->waitForFinished(10)) //Wake up every 10ms and check if we must exit
{
if (QThread::currentThread()->isInterruptionRequested()) {
if (m_interrupt) {
qInfo() << "Interrupt thread";
m_process->terminate();
if (!m_process->waitForFinished(1000)) {
@ -802,7 +732,10 @@ QString CreateImportVideo::waitForFinished(
} else {
processOutput = m_process->readAll();
}
qInfo() << "ProcessOutput:" << processOutput;
if (!processOutput.isEmpty())
qInfo() << "ProcessOutput:" << processOutput;
m_process->close();
return processOutput;

View File

@ -47,9 +47,9 @@
#include <QProcess>
#include <QScopeGuard>
#include <QString>
#include <QThread>
#include <QtMath>
#include "createimportstates.h"
#include "util.h"
namespace ScreenPlay {
@ -59,46 +59,7 @@ class CreateImportVideo : public QObject {
Q_PROPERTY(float progress READ progress WRITE setProgress NOTIFY progressChanged)
public:
CreateImportVideo() { }
CreateImportVideo(QObject* parent = nullptr);
explicit CreateImportVideo(const QString& videoPath, const QString& exportPath, const QString& codec, const int quality, QObject* parent = nullptr);
enum class ImportVideoState {
Idle,
Started,
AnalyseVideo,
AnalyseVideoFinished,
AnalyseVideoError,
AnalyseVideoHasNoVideoStreamError,
ConvertingPreviewVideo,
ConvertingPreviewVideoFinished,
ConvertingPreviewVideoError,
ConvertingPreviewGif,
ConvertingPreviewGifFinished, //10
ConvertingPreviewGifError,
ConvertingPreviewImage,
ConvertingPreviewImageFinished,
ConvertingPreviewImageError,
ConvertingPreviewImageThumbnail,
ConvertingPreviewImageThumbnailFinished,
ConvertingPreviewImageThumbnailError,
ConvertingAudio,
ConvertingAudioFinished,
ConvertingAudioError, //20
ConvertingVideo,
ConvertingVideoFinished,
ConvertingVideoError,
CopyFiles,
CopyFilesFinished,
CopyFilesError,
CreateProjectFile,
CreateProjectFileFinished,
CreateProjectFileError,
AbortCleanupError, //30
CreateTmpFolderError,
Finished,
};
Q_ENUM(ImportVideoState)
explicit CreateImportVideo(const QString& videoPath, const QString& exportPath, const QString& codec, const int quality, std::atomic<bool>& interrupt);
float progress() const { return m_progress; }
@ -128,16 +89,13 @@ public:
};
signals:
void createWallpaperStateChanged(CreateImportVideo::ImportVideoState state);
void createWallpaperStateChanged(ImportVideoState::ImportVideoState state);
void processOutput(QString text);
void finished();
void abortAndCleanup();
void progressChanged(float progress);
public slots:
void process();
void processGif();
bool createWallpaperInfo();
bool createWallpaperVideoPreview();
bool createWallpaperGifPreview();
@ -170,6 +128,7 @@ private:
QString m_ffprobeExecutable;
QString m_ffmpegExecutable;
std::unique_ptr<QProcess> m_process;
std::atomic<bool>& m_interrupt;
};
}
Q_DECLARE_METATYPE(ScreenPlay::CreateImportVideo::ImportVideoState)
Q_DECLARE_METATYPE(ScreenPlay::ImportVideoState::ImportVideoState)

View File

@ -1,4 +1,5 @@
#include "installedlistmodel.h"
#include <QDebug>
namespace ScreenPlay {
@ -44,27 +45,65 @@ void InstalledListModel::init()
/*!
\brief Deleted the item from the local storage and removes it from the
installed list.
installed list. We wait for the qml engine to free all resources before
we proceed. This like the preview.gif will be in use when clicking on an item
*/
bool InstalledListModel::deinstallItemAt(const int index)
void InstalledListModel::deinstallItemAt(const QString& absoluteStoragePath)
{
if (index < 0 || index >= m_screenPlayFiles.count()) {
qWarning() << "remove folder error, invalid index " << index;
return false;
}
QTimer::singleShot(1000, this, [this, absoluteStoragePath]() {
int index = -1;
for (int i = 0; i < m_screenPlayFiles.size(); ++i) {
if (m_screenPlayFiles.at(i).m_absoluteStoragePath.toString() == absoluteStoragePath) {
index = i;
break;
}
}
beginRemoveRows(QModelIndex(), index, index);
const QString path = QUrl::fromUserInput(m_screenPlayFiles.at(index).m_absoluteStoragePath.toString()).toLocalFile();
if (index < 0 || index >= m_screenPlayFiles.count()) {
qWarning() << "Remove folder error, invalid index " << index;
return;
}
QDir dir(path);
const bool success = dir.removeRecursively();
beginRemoveRows(QModelIndex(), index, index);
m_screenPlayFiles.removeAt(index);
endRemoveRows();
if (!success)
qWarning() << "Could not remove folder: " << m_screenPlayFiles.at(index).m_absoluteStoragePath.toString();
const QString path = ScreenPlayUtil::toLocal(absoluteStoragePath);
m_screenPlayFiles.removeAt(index);
endRemoveRows();
return success;
QDir dir(path);
bool success = true;
if (!dir.exists()) {
qWarning() << "Directory does not exist!" << dir;
return;
}
// We must pause the QFileSystemWatcher to not trigger
// a reload for every removed file
m_fileSystemWatcher.blockSignals(true);
for (auto& item : dir.entryInfoList(QDir::Files)) {
if (!QFile::remove(item.absoluteFilePath())) {
qWarning() << "Unable to remove file:" << item;
success = false;
break;
}
}
if (!success) {
qWarning() << "Could not remove folder content at: " << path;
loadInstalledContent();
}
if (!dir.rmdir(path)) {
qWarning() << "Could not remove folder at: " << path;
return;
}
// Add delay to the watcher, because it was trigger by
// something when enabling after the removal.
QTimer::singleShot(3000, this, [this]() {
m_fileSystemWatcher.blockSignals(false);
});
});
}
/*!
@ -111,13 +150,15 @@ QVariant InstalledListModel::data(const QModelIndex& index, int role) const
return m_screenPlayFiles.at(row).m_publishedFileID;
case static_cast<int>(ScreenPlayItem::Tags):
return m_screenPlayFiles.at(row).m_tags;
case static_cast<int>(ScreenPlayItem::IsNew):
return m_screenPlayFiles.at(row).m_isNew;
case static_cast<int>(ScreenPlayItem::LastModified):
return m_screenPlayFiles.at(row).m_lastModified;
case static_cast<int>(ScreenPlayItem::SearchType):
return QVariant::fromValue(m_screenPlayFiles.at(row).m_searchType);
default:
return QVariant();
}
qWarning() << "Unable to fetch value for row type:" << role;
return QVariant();
}
@ -137,26 +178,34 @@ QHash<int, QByteArray> InstalledListModel::roleNames() const
{ static_cast<int>(ScreenPlayItem::PublishedFileID), "m_publishedFileID" },
{ static_cast<int>(ScreenPlayItem::Tags), "m_tags" },
{ static_cast<int>(ScreenPlayItem::SearchType), "m_searchType" },
{ static_cast<int>(ScreenPlayItem::LastModified), "m_lastModified" },
{ static_cast<int>(ScreenPlayItem::IsNew), "m_isNew" },
{ static_cast<int>(ScreenPlayItem::LastModified), "m_lastModified" }
};
}
/*!
\brief Append an ProjectFile to the list.
*/
void InstalledListModel::append(const QJsonObject& obj, const QString& folderName, const QDateTime& lastModified)
void InstalledListModel::append(const QJsonObject& obj, const QString& folderName, const bool isNew, const QDateTime& lastModified)
{
beginInsertRows(QModelIndex(), m_screenPlayFiles.size(), m_screenPlayFiles.size());
m_screenPlayFiles.append(ProjectFile(obj, folderName, m_globalVariables->localStoragePath(), lastModified));
m_screenPlayFiles.append(ProjectFile(obj, folderName, m_globalVariables->localStoragePath(), isNew, lastModified));
endInsertRows();
}
/*!
\brief Loads all installed content. Skips projects.json without a "type" field.
\brief Loads all installed content.
- Skips if the loadContentFuture is already running.
- Skips projects.json without a "type" field.
*/
void InstalledListModel::loadInstalledContent()
{
QtConcurrent::run([this]() {
if (m_loadContentFuture.isRunning()) {
qInfo() << "loadInstalledContent is already running. Skip.";
return;
}
m_loadContentFuture = QtConcurrent::run([this]() {
QFileInfoList list = QDir(m_globalVariables->localStoragePath().toLocalFile()).entryInfoList(QDir::NoDotAndDotDot | QDir::AllDirs);
int counter = 0;
@ -166,6 +215,11 @@ void InstalledListModel::loadInstalledContent()
if (!QFile::exists(absoluteFilePath))
continue;
bool isNew = false;
if (item.birthTime().date() == QDateTime::currentDateTime().date())
isNew = true;
if (auto obj = ScreenPlayUtil::openJsonFileToObject(absoluteFilePath)) {
if (obj->isEmpty())
@ -176,7 +230,7 @@ void InstalledListModel::loadInstalledContent()
if (ScreenPlayUtil::getAvailableTypes().contains(obj->value("type").toString())) {
if (ScreenPlayUtil::getAvailableTypes().contains(obj->value("type").toString(), Qt::CaseInsensitive)) {
append(*obj, item.baseName(), item.lastModified());
append(*obj, item.baseName(), isNew, item.lastModified());
}
counter += 1;
@ -189,26 +243,33 @@ void InstalledListModel::loadInstalledContent()
}
/*!
\brief .
\brief Used for receiving values from qml. One must add all new fields
when adding new roles to this model.
*/
QVariantMap InstalledListModel::get(const QString& folderId) const
QVariantMap InstalledListModel::get(const QString& folderName) const
{
if (m_screenPlayFiles.count() == 0)
return {};
QVariantMap map;
for (int i = 0; i < m_screenPlayFiles.count(); i++) {
const QString localInstalledPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString());
if (m_screenPlayFiles[i].m_folderId == folderId) {
map.insert("m_title", m_screenPlayFiles[i].m_title);
map.insert("m_preview", m_screenPlayFiles[i].m_preview);
map.insert("m_previewGIF", m_screenPlayFiles[i].m_previewGIF);
map.insert("m_file", m_screenPlayFiles[i].m_file);
map.insert("m_type", QVariant::fromValue(m_screenPlayFiles[i].m_type));
map.insert("m_absoluteStoragePath", m_screenPlayFiles[i].m_absoluteStoragePath);
map.insert("m_publishedFileID", m_screenPlayFiles[i].m_publishedFileID);
map.insert("m_lastModified", m_screenPlayFiles[i].m_lastModified);
if (!QDir(localInstalledPath + "/" + folderName).exists()) {
return {};
}
for (const auto& item : m_screenPlayFiles) {
if (item.m_folderId == folderName) {
QVariantMap map;
map.insert("m_title", item.m_title);
map.insert("m_preview", item.m_preview);
map.insert("m_previewGIF", item.m_previewGIF);
map.insert("m_file", item.m_file);
map.insert("m_type", QVariant::fromValue(item.m_type));
map.insert("m_absoluteStoragePath", item.m_absoluteStoragePath);
map.insert("m_publishedFileID", item.m_publishedFileID);
map.insert("m_isNew", item.m_isNew);
map.insert("m_lastModified", item.m_lastModified);
return map;
}
}
@ -217,7 +278,7 @@ QVariantMap InstalledListModel::get(const QString& folderId) const
}
/*!
\brief .
\brief Removes all entires and loads it again.
*/
void InstalledListModel::reset()
{

View File

@ -89,6 +89,7 @@ public:
Tags,
SearchType,
LastModified,
IsNew,
};
Q_ENUM(ScreenPlayItem)
@ -98,13 +99,13 @@ public:
}
public slots:
QVariantMap get(const QString& folderId) const;
QVariantMap get(const QString& folderName) const;
void loadInstalledContent();
void append(const QJsonObject&, const QString&, const QDateTime& lastModified);
void append(const QJsonObject&, const QString&, const bool isNew, const QDateTime& lastModified);
void reset();
void init();
bool deinstallItemAt(const int index);
void deinstallItemAt(const QString& absoluteStoragePath);
void setCount(int count)
{
@ -123,6 +124,7 @@ private:
QFileSystemWatcher m_fileSystemWatcher;
QVector<ProjectFile> m_screenPlayFiles;
int m_count { 0 };
QFuture<void> m_loadContentFuture;
const std::shared_ptr<GlobalVariables>& m_globalVariables;
};

View File

@ -90,7 +90,12 @@ void ScreenPlayManager::init(
});
}
loadProfiles();
// Reset to default settings if we are unable to load
// the existing one
if (!loadProfiles()) {
qInfo() << "Reset default profiles.json at:" << m_globalVariables->localSettingsPath();
m_settings->writeJsonFileFromResource("profiles");
}
}
/*!
@ -418,10 +423,11 @@ bool ScreenPlayManager::removeWallpaper(const QString& appID)
std::remove_if(
m_screenPlayWallpapers.begin(),
m_screenPlayWallpapers.end(),
[this, appID](auto& wallpaper) {
[this, appID](std::shared_ptr<ScreenPlayWallpaper>& wallpaper) {
if (wallpaper->appID() != appID) {
return false;
}
wallpaper->messageQuit();
qInfo() << "Remove wallpaper " << wallpaper->file() << "at monitor " << wallpaper->screenNumber();
@ -452,12 +458,14 @@ bool ScreenPlayManager::removeWidget(const QString& appID)
std::remove_if(
m_screenPlayWidgets.begin(),
m_screenPlayWidgets.end(),
[this, appID](auto& widget) {
[this, appID](std::shared_ptr<ScreenPlayWidget>& widget) {
if (widget->appID() != appID) {
qInfo() << "No match " << widget->appID();
return false;
}
widget->messageQuit();
qInfo() << "Remove widget " << appID;
decreaseActiveWidgetsCounter();
@ -559,6 +567,21 @@ bool ScreenPlayManager::loadProfiles()
if (wallpaper.toObject().value("name").toString() != "default")
continue;
// Dry run to check if the config is outdated. This is when a wallpaper is configured
// but no longer available.
for (QJsonValueRef wallpaper : wallpaper.toObject().value("wallpaper").toArray()) {
QJsonObject wallpaperObj = wallpaper.toObject();
if (wallpaperObj.empty())
continue;
const QString absolutePath = wallpaperObj.value("absolutePath").toString();
if (!QFile(absolutePath).exists()) {
qWarning() << "Specified file does not exist! This means the profiles.json is no longer valid.";
return false;
}
}
for (QJsonValueRef wallpaper : wallpaper.toObject().value("wallpaper").toArray()) {
QJsonObject wallpaperObj = wallpaper.toObject();

View File

@ -10,16 +10,6 @@ namespace ScreenPlay {
This class is only for managing the QProcess to an extern ScreenPlayWallpaper!
*/
/*!
\brief Destructor for ScreenPlayWallpaper.
*/
ScreenPlayWallpaper::~ScreenPlayWallpaper()
{
m_connection->close();
qInfo() << "Remove wallpaper " << m_appID;
}
/*!
\brief Constructor for ScreenPlayWallpaper.
*/
@ -144,6 +134,15 @@ QJsonObject ScreenPlayWallpaper::getActiveSettingsJson()
return obj;
}
/*!
\brief Sends command quit to the wallpaper.
*/
void ScreenPlayWallpaper::messageQuit()
{
QJsonObject obj;
obj.insert("command", "quit");
m_connection->sendMessage(QJsonDocument(obj).toJson(QJsonDocument::Compact));
}
/*!
\brief Prints the exit code if != 0.
*/

View File

@ -66,8 +66,8 @@ class ScreenPlayWallpaper : public QObject {
Q_PROPERTY(InstalledType::InstalledType type READ type WRITE setType NOTIFY typeChanged)
public:
// Default constructor needed for qml engine
ScreenPlayWallpaper() { }
~ScreenPlayWallpaper();
explicit ScreenPlayWallpaper(
const QVector<int>& screenNumber,
@ -127,6 +127,7 @@ signals:
void error(const QString& msg);
public slots:
void messageQuit();
void processExit(int exitCode, QProcess::ExitStatus exitStatus);
void processError(QProcess::ProcessError error);
bool setWallpaperValue(const QString& key, const QString& value, const bool save = false);

View File

@ -50,10 +50,9 @@ ScreenPlayWidget::ScreenPlayWidget(
QVariant::fromValue(m_type).toString(),
QString::number(m_position.x()),
QString::number(m_position.y()),
};
};
}
bool ScreenPlayWidget::start()
{
m_process.setArguments(m_appArgumentsList);
@ -71,10 +70,14 @@ bool ScreenPlayWidget::start()
return success;
}
ScreenPlayWidget::~ScreenPlayWidget()
/*!
\brief Sends command quit to the widget.
*/
void ScreenPlayWidget::messageQuit()
{
qInfo() << "Remove widget " << m_appID;
m_connection->close();
QJsonObject obj;
obj.insert("command", "quit");
m_connection->sendMessage(QJsonDocument(obj).toJson(QJsonDocument::Compact));
}
/*!

View File

@ -69,7 +69,6 @@ public:
const QString& absolutePath,
const QString& previewImage, const QJsonObject& properties,
const InstalledType::InstalledType type);
~ScreenPlayWidget();
bool start();
@ -86,6 +85,7 @@ public:
ProjectSettingsListModel* getProjectSettingsListModel() { return &m_projectSettingsListModel; }
public slots:
void messageQuit();
QJsonObject getActiveSettingsJson();
void setPreviewImage(QString previewImage)

View File

@ -18,7 +18,7 @@ ScreenPlay::SDKConnection::SDKConnection(QLocalSocket* socket, QObject* parent)
{
m_socket = socket;
connect(m_socket, &QLocalSocket::readyRead, this, &SDKConnection::readyRead);
connect(m_socket, &QLocalSocket::errorOccurred, this, [](QLocalSocket::LocalSocketError socketError){
connect(m_socket, &QLocalSocket::errorOccurred, this, [](QLocalSocket::LocalSocketError socketError) {
qInfo() << "Localsocket error:" << socketError;
});
}

View File

@ -140,16 +140,26 @@ void Settings::writeJsonFileFromResource(const QString& filename)
void Settings::setupWidgetAndWindowPaths()
{
QDir workingDir(QGuiApplication::applicationDirPath());
#ifdef Q_OS_WIN
m_globalVariables->setWidgetExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWidget" + ScreenPlayUtil::executableBinEnding()));
m_globalVariables->setWallpaperExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWallpaper" + ScreenPlayUtil::executableBinEnding()));
#endif
#ifdef Q_OS_LINUX
m_globalVariables->setWidgetExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWidget"));
m_globalVariables->setWallpaperExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWallpaper"));
#endif
#ifdef Q_OS_OSX
workingDir.cdUp();
workingDir.cdUp();
workingDir.cdUp();
// ScreenPlayTest is not bundled in an .app so the working directory
// the the same as the executable.
if (QFileInfo(QCoreApplication::applicationFilePath()).fileName() != "tst_ScreenPlay") {
workingDir.cdUp();
workingDir.cdUp();
workingDir.cdUp();
}
m_globalVariables->setWidgetExecutablePath(QUrl::fromUserInput(workingDir.path() + "/ScreenPlayWidget.app/Contents/MacOS/ScreenPlayWidget").toLocalFile());
m_globalVariables->setWallpaperExecutablePath(QUrl::fromUserInput(workingDir.path() + "/ScreenPlayWallpaper.app/Contents/MacOS/ScreenPlayWallpaper").toLocalFile());
@ -157,10 +167,12 @@ void Settings::setupWidgetAndWindowPaths()
#endif
if (!QFileInfo::exists(m_globalVariables->widgetExecutablePath().toString())) {
qFatal("widget executable not found!");
qInfo() << "widgetExecutablePath:" << m_globalVariables->widgetExecutablePath().toString();
qCritical("widget executable not found!");
}
if (!QFileInfo::exists(m_globalVariables->wallpaperExecutablePath().toString())) {
qFatal("wallpaper executable not found!");
qInfo() << "wallpaperExecutablePath:" << m_globalVariables->wallpaperExecutablePath().toString();
qCritical("wallpaper executable not found!");
}
}

View File

@ -201,7 +201,7 @@ public slots:
QFile defaultPListFile(":/assets/macos/" + plistFileName);
defaultPListFile.open(QIODevice::ReadOnly);
QString settingsPlistContent = defaultPListFile.readAll();
if(!settingsPlistContent.contains("{{SCREENPLAY_PATH}}")){
if (!settingsPlistContent.contains("{{SCREENPLAY_PATH}}")) {
qCritical() << "Unable to load plist settings template from qrc to set autostart!";
}
@ -211,7 +211,7 @@ public slots:
workingDir.cdUp();
const QString screenPlayPath = QUrl::fromUserInput(workingDir.path() + "/ScreenPlay.app/Contents/MacOS/ScreenPlay").toLocalFile();
settingsPlistContent.replace("{{SCREENPLAY_PATH}}", screenPlayPath);
settingsPlistContent.replace("{{SCREENPLAY_AUTOSTART}}", autostart ? "true":"false");
settingsPlistContent.replace("{{SCREENPLAY_AUTOSTART}}", autostart ? "true" : "false");
const QString homePath = QDir::homePath();
QFile settingsPlist(homePath + "/Library/LaunchAgents/" + plistFileName);

View File

@ -0,0 +1,238 @@
/****************************************************************************
**
** 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$
**
****************************************************************************/
#include "app.h"
#include "create.h"
#include <QApplication>
#include <QCommandLineParser>
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QGuiApplication>
#include <QtTest>
#include <QQuickItem>
#define DOCTEST_CONFIG_IMPLEMENT
#define DOCTEST_CONFIG_SUPER_FAST_ASSERTS
#include <doctest/doctest.h>
class ScreenPlayTest : public QObject {
Q_OBJECT
private slots:
void initTestCase()
{
Q_INIT_RESOURCE(ScreenPlayQML);
Q_INIT_RESOURCE(ScreenPlayAssets);
app.init();
m_window = qobject_cast<QQuickWindow*>(app.mainWindowEngine()->rootObjects().first());
QVERIFY(m_window);
QVERIFY(QTest::qWaitForWindowExposed(m_window));
QTest::qWait(1000);
m_installedSidebar = m_window->findChild<QQuickItem*>("installedSidebar");
QVERIFY(m_installedSidebar);
QTest::qWait(1000);
}
void start_shutdown_wallpaper();
void import_convert_video();
private:
QQuickWindow* m_window = nullptr;
QQuickItem* m_installedSidebar = nullptr;
ScreenPlay::App app;
};
/*!
* For some reason a direct findChild does not work for item
* delegates.
* https://stackoverflow.com/questions/36767512/how-to-access-qml-listview-delegate-items-from-c
*
*/
QQuickItem* findItemDelegate(QQuickItem* listView, const QString objectName)
{
if (!listView->property("contentItem").isValid())
return {};
auto contentItem = listView->property("contentItem").value<QQuickItem*>();
auto contentItemChildren = contentItem->childItems();
QQuickItem* videoImportConvertButton {};
for (auto childItem : contentItemChildren) {
if (childItem->objectName() == objectName)
return childItem;
}
return {};
}
void clickItem(QQuickItem* item, Qt::MouseButton button = Qt::LeftButton)
{
QQuickWindow* itemWindow = item->window();
QVERIFY(itemWindow);
auto centre = item->mapToScene(QPoint(item->width() / 2, item->height() / 2)).toPoint();
qInfo() << "click_:" << centre;
QTest::mouseClick(itemWindow, button, Qt::NoModifier, centre);
}
void ScreenPlayTest::import_convert_video()
{
using namespace ScreenPlay;
auto* createTab = m_window->findChild<QQuickItem*>("createTab");
QVERIFY(createTab);
clickItem(createTab);
QTest::qWait(300);
auto* stackView = m_window->findChild<QQuickItem*>("stackView");
QVERIFY(stackView);
QVERIFY(stackView->property("currentItem").isValid());
auto* createView = qvariant_cast<QQuickItem*>(stackView->property("currentItem"));
QVERIFY(createView);
QTest::qWait(300);
auto* wizardsListView = m_window->findChild<QQuickItem*>("wizardsListView");
QVERIFY(wizardsListView);
QQuickItem* videoImportConvertButton = findItemDelegate(wizardsListView, "videoImportConvert");
QVERIFY(videoImportConvertButton);
clickItem(videoImportConvertButton);
QTest::qWait(300);
auto* createWallpaperInit = m_window->findChild<QQuickItem*>("createWallpaperInit");
QVERIFY(createWallpaperInit);
const QString originalVideoPath = QString(SOURCE_DIR) + "/ScreenPlay/assets/tests/video_import.mp4";
qInfo() << originalVideoPath;
QVERIFY(QMetaObject::invokeMethod(createWallpaperInit,
QString("startConvert").toLatin1().constData(),
Qt::ConnectionType::AutoConnection,
Q_ARG(QVariant, originalVideoPath),
Q_ARG(QVariant, 1))); // VideoCodec::VP9
QTest::qWait(1000);
// Wait for Create::createWallpaperStart
{
ImportVideoState::ImportVideoState status = ImportVideoState::ImportVideoState::Idle;
QObject::connect(app.create(), &Create::createWallpaperStateChanged, this, [&status](ImportVideoState::ImportVideoState state) {
status = state;
});
while (true) {
QSignalSpy videoConvertFinishSpy(app.create(), &Create::createWallpaperStateChanged);
if (status == ImportVideoState::ImportVideoState::Finished || status == ImportVideoState::ImportVideoState::Failed) {
QVERIFY(status == ImportVideoState::ImportVideoState::Finished);
QTest::qWait(1000); // Wait for the ui to process the event
break;
}
videoConvertFinishSpy.wait();
}
}
QTest::qWait(1000);
auto* btnSave = m_window->findChild<QQuickItem*>("btnSave");
QVERIFY(btnSave);
clickItem(btnSave);
// Wait for Create::saveWallpaper
{
ImportVideoState::ImportVideoState status = ImportVideoState::ImportVideoState::Idle;
QObject::connect(app.create(), &Create::createWallpaperStateChanged, this, [&status](ImportVideoState::ImportVideoState state) {
status = state;
});
while (true) {
QSignalSpy videoConvertFinishSpy(app.create(), &Create::createWallpaperStateChanged);
if (status == ImportVideoState::ImportVideoState::CreateProjectFileFinished || status == ImportVideoState::ImportVideoState::CreateProjectFileError || status == ImportVideoState::ImportVideoState::CopyFilesError) {
QVERIFY(status == ImportVideoState::ImportVideoState::CreateProjectFileFinished);
QTest::qWait(1000); // Wait for the ui to process the event
break;
}
videoConvertFinishSpy.wait();
}
}
QTest::qWait(1000);
auto* installedTab = m_window->findChild<QQuickItem*>("installedTab");
QVERIFY(installedTab);
clickItem(installedTab);
QTest::qWait(1000);
auto* gridView = m_window->findChild<QQuickItem*>("gridView");
QVERIFY(gridView);
const QString installedListItemIndex = "0";
auto* firstInstalledItem = findItemDelegate(gridView, "installedItem" + installedListItemIndex);
QVERIFY(firstInstalledItem);
clickItem(firstInstalledItem, Qt::RightButton);
QTest::qWait(1000);
auto* installedItemContextMenu = m_window->findChild<QQuickItem*>("installedItemContextMenu");
QVERIFY(installedItemContextMenu);
auto* removeItem = findItemDelegate(installedItemContextMenu, "removeItem");
QVERIFY(removeItem);
clickItem(removeItem);
}
void ScreenPlayTest::start_shutdown_wallpaper()
{
QTest::qWait(1000);
auto* stackView = m_window->findChild<QQuickItem*>("stackView");
QVERIFY(stackView);
QVERIFY(stackView->property("currentItem").isValid());
auto* installedView = qvariant_cast<QQuickItem*>(stackView->property("currentItem"));
QVERIFY(installedView);
QTest::qWait(1000);
auto* gridView = m_window->findChild<QQuickItem*>("gridView");
QVERIFY(gridView);
const QString installedListItemIndex = "0";
auto* firstInstalledItem = findItemDelegate(gridView, "installedItem" + installedListItemIndex);
QVERIFY(firstInstalledItem);
clickItem(firstInstalledItem);
auto* monitorSelection = m_installedSidebar->findChild<QQuickItem*>("monitorSelection");
QVERIFY(monitorSelection);
QTest::qWait(1000);
QVERIFY(QMetaObject::invokeMethod(monitorSelection,
QString("selectOnly").toLatin1().constData(),
Qt::ConnectionType::AutoConnection,
Q_ARG(QVariant, 0))); // First monitor
QTest::qWait(1000);
auto* btnSetWallpaper = m_installedSidebar->findChild<QQuickItem*>("btnSetWallpaper");
QVERIFY(btnSetWallpaper);
clickItem(btnSetWallpaper);
QTest::qWait(10000);
}
QTEST_MAIN(ScreenPlayTest)
#include "tst_main.moc"

View File

@ -1,7 +0,0 @@
### How-to Update Translations?
1. Open PowerShell (in this Directory)
2. Check if you have execution policy set to bypass by executing `Get-ExecutionPolicy`
+ If you have "Bypass" or "Unrestricted" then you are good.
+ If not then execute **in Administrator PowerShell** `Set-ExecutionPolicy Bypass -Scope Process` to set current PowerShell session to Bypass or `Set-ExecutionPolicy Bypass` to set All PowerShell session to Bypass.
3. Execute `./UpdateTranslations.ps1` and follow the instruction printed on the screen.

File diff suppressed because it is too large Load Diff

View File

@ -110,65 +110,37 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CreateEmptyHtmlWallpaper</name>
<message>
<source>Abort</source>
<translation type="obsolete">Cancel</translation>
</message>
</context>
<context>
<name>CreateEmptyWidget</name>
<message>
<source>Abort</source>
<translation type="obsolete">Cancel</translation>
</message>
</context>
<context>
<name>CreateImport</name>
<message>
<source>Import a Creation</source>
<translation type="vanished">Import a Creation</translation>
</message>
</context>
<context>
<name>CreateUpload</name>
<message>
<source>Upload a Creation</source>
<translation type="vanished">Upload a Creation</translation>
</message>
</context>
<context>
<name>CreateWallpaperInit</name>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="31"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="32"/>
<source>Import any video type</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="37"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="38"/>
<source>Depending on your PC configuration it is better to convert your wallpaper to a specific video codec. If both have bad performance you can also try a QML wallpaper! Supported video formats are:
*.mp4 *.mpg *.mp2 *.mpeg *.ogv *.avi *.wmv *.m4v *.3gp *.flv</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="52"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="53"/>
<source>Set your preffered video codec:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="97"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="98"/>
<source>Quality slider. Lower value means better quality.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="112"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="113"/>
<source>Open Documentation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="130"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="132"/>
<source>Select file</source>
<translation type="unfinished"></translation>
</message>
@ -193,88 +165,88 @@
</context>
<context>
<name>CreateWallpaperVideoImportConvert</name>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="47"/>
<source>Generating preview image...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="50"/>
<source>Generating preview thumbnail image...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="57"/>
<source>Generating 5 second preview video...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="60"/>
<source>Generating preview gif...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="69"/>
<source>Converting Audio...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="72"/>
<source>Converting Video... This can take some time!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="75"/>
<source>Converting Video ERROR!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="78"/>
<source>Analyse Video ERROR!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="106"/>
<source>Convert a video to a wallpaper</source>
<translation type="unfinished">Convert a video to a background live wallpaper</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImportConvert.qml" line="164"/>
<source></source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="221"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="48"/>
<source>Generating preview image...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="51"/>
<source>Generating preview thumbnail image...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="58"/>
<source>Generating 5 second preview video...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="61"/>
<source>Generating preview gif...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="70"/>
<source>Converting Audio...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="73"/>
<source>Converting Video... This can take some time!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="77"/>
<source>Converting Video ERROR!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="80"/>
<source>Analyse Video ERROR!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="108"/>
<source>Convert a video to a wallpaper</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="219"/>
<source>Generating preview video...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="281"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="275"/>
<source>Name (required!)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="295"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="289"/>
<source>Description</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="303"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="297"/>
<source>Youtube URL</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="334"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="327"/>
<source>Abort</source>
<translation type="unfinished">Cancel</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="347"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="340"/>
<source>Save</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="382"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="377"/>
<source>Save Wallpaper...</source>
<translation type="unfinished"></translation>
</message>
@ -327,13 +299,6 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FFMPEGPopup</name>
<message>
<source>Abort</source>
<translation type="obsolete">Cancel</translation>
</message>
</context>
<context>
<name>FileSelector</name>
<message>
@ -492,88 +457,88 @@
</context>
<context>
<name>ImportWebmConvert</name>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="42"/>
<source>AnalyseVideo...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="45"/>
<source>Generating preview image...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="48"/>
<source>Generating preview thumbnail image...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="55"/>
<source>Generating 5 second preview video...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="58"/>
<source>Generating preview gif...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="67"/>
<source>Converting Audio...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="70"/>
<source>Converting Video... This can take some time!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="73"/>
<source>Converting Video ERROR!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="76"/>
<source>Analyse Video ERROR!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="104"/>
<source>Import a video to a wallpaper</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="189"/>
<source></source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="214"/>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="43"/>
<source>AnalyseVideo...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="46"/>
<source>Generating preview image...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="49"/>
<source>Generating preview thumbnail image...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="56"/>
<source>Generating 5 second preview video...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="59"/>
<source>Generating preview gif...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="68"/>
<source>Converting Audio...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="71"/>
<source>Converting Video... This can take some time!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="74"/>
<source>Converting Video ERROR!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="77"/>
<source>Analyse Video ERROR!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="105"/>
<source>Import a video to a wallpaper</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="215"/>
<source>Generating preview video...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="274"/>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="275"/>
<source>Name (required!)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="288"/>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="289"/>
<source>Description</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="296"/>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="297"/>
<source>Youtube URL</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="327"/>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="328"/>
<source>Abort</source>
<translation type="unfinished">Cancel</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="340"/>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="341"/>
<source>Save</source>
<translation type="unfinished"></translation>
</message>
@ -619,46 +584,51 @@
<context>
<name>Installed</name>
<message>
<location filename="../qml/Installed/Installed.qml" line="130"/>
<location filename="../qml/Installed/Installed.qml" line="329"/>
<source></source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="131"/>
<source>Refreshing!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="133"/>
<location filename="../qml/Installed/Installed.qml" line="148"/>
<location filename="../qml/Installed/Installed.qml" line="134"/>
<location filename="../qml/Installed/Installed.qml" line="149"/>
<source>Pull to refresh!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="178"/>
<location filename="../qml/Installed/Installed.qml" line="179"/>
<source>Get more Wallpaper &amp; Widgets via the Steam workshop!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="242"/>
<location filename="../qml/Installed/Installed.qml" line="244"/>
<source>Open containing folder</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="250"/>
<source>Deinstall Item</source>
<location filename="../qml/Installed/Installed.qml" line="252"/>
<source>Remove Item</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="252"/>
<source>Remove via Workshop</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="261"/>
<source>Open workshop Page</source>
<source>Open Workshop Page</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="276"/>
<location filename="../qml/Installed/Installed.qml" line="277"/>
<source>Are you sure you want to delete this item?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="329"/>
<source></source>
<translation></translation>
</message>
</context>
<context>
<name>InstalledWelcomeScreen</name>
@ -702,13 +672,13 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Common/LicenseSelector.qml" line="78"/>
<source>You do not share any rights and nobody is allowed to use or remix it (Not recommended). Can also used to credit work others.</source>
<location filename="../qml/Common/LicenseSelector.qml" line="71"/>
<source>You grant other to remix your work but it must remain under the GPLv3. We recommend this license for all code wallpaper!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Common/LicenseSelector.qml" line="71"/>
<source>You grant other to remix your work but it must remain under the GPLv3. We recommend this license for all code wallpaper!</source>
<location filename="../qml/Common/LicenseSelector.qml" line="78"/>
<source>You do not share any rights and nobody is allowed to use or remix it (Not recommended). Can also used to credit work others.</source>
<translation type="unfinished"></translation>
</message>
</context>
@ -929,6 +899,14 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ScreenPlayItem</name>
<message>
<location filename="../qml/Installed/ScreenPlayItem.qml" line="206"/>
<source>NEW</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Search</name>
<message>
@ -949,6 +927,11 @@
<source>Autostart</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="73"/>
<source>ScreenPlay will start with Windows and will setup your Desktop every time for you.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="84"/>
<source>High priority Autostart</source>
@ -966,7 +949,7 @@
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="99"/>
<source>Help us make ScreenPlay faster and more stable. All collected data is purely anonymous and only used for development purposes!</source>
<source>Help us make ScreenPlay faster and more stable. All collected data is purely anonymous and only used for development purposes! We use &lt;a href=&quot;https://sentry.io&quot;&gt;sentry.io&lt;/a&gt; to collect and analyze this data. A &lt;b&gt;big thanks to them&lt;/b&gt; for providing us with free premium support for open source projects!</source>
<translation type="unfinished"></translation>
</message>
<message>
@ -979,6 +962,11 @@
<source>Set location</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="116"/>
<source>Your storage path is empty!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="139"/>
<source>Important: Changing this directory has no effect on the workshop download path. ScreenPlay only supports having one content folder!</source>
@ -992,26 +980,6 @@
<message>
<location filename="../qml/Settings/Settings.qml" line="162"/>
<source>Set the ScreenPlay UI Language</source>
<translation type="unfinished">Set the ScreenPlay userinterface Language</translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="176"/>
<source>Chinese - Simplified</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="243"/>
<source>Performance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="73"/>
<source>ScreenPlay will start with Windows and will setup your Desktop every time for you.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="116"/>
<source>Your storage path is empty!</source>
<translation type="unfinished"></translation>
</message>
<message>
@ -1024,6 +992,11 @@
<source>German</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="176"/>
<source>Chinese - Simplified</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="179"/>
<source>Russian</source>
@ -1079,6 +1052,11 @@
<source>Light</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="243"/>
<source>Performance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="262"/>
<source>Pause wallpaper video rendering while another app is in the foreground</source>
@ -1210,6 +1188,56 @@
</context>
<context>
<name>Sidebar</name>
<message>
<location filename="../qml/Create/Sidebar.qml" line="118"/>
<source>Tools Overview</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="124"/>
<source>Video import and convert (all types)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="131"/>
<source>Video Import (.webm)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="137"/>
<source>GIF Wallpaper</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="143"/>
<source>QML Wallpaper</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="149"/>
<source>HTML5 Wallpaper</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="155"/>
<source>Website Wallpaper</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="161"/>
<source>QML Widget</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="167"/>
<source>HTML Widget</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="65"/>
<source>Set Wallpaper</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="68"/>
<source>Set Widget</source>
@ -1226,55 +1254,50 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="287"/>
<location filename="../qml/Installed/Sidebar.qml" line="288"/>
<source>Set Volume</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="306"/>
<location filename="../qml/Installed/Sidebar.qml" line="307"/>
<source>Fill Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="325"/>
<location filename="../qml/Installed/Sidebar.qml" line="326"/>
<source>Stretch</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="328"/>
<location filename="../qml/Installed/Sidebar.qml" line="329"/>
<source>Fill</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="331"/>
<location filename="../qml/Installed/Sidebar.qml" line="332"/>
<source>Contain</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="334"/>
<location filename="../qml/Installed/Sidebar.qml" line="335"/>
<source>Cover</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="337"/>
<location filename="../qml/Installed/Sidebar.qml" line="338"/>
<source>Scale-Down</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="65"/>
<source>Set Wallpaper</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Sidebar.qml" line="81"/>
<source> MB</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Sidebar.qml" line="81"/>
<source>Size: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Sidebar.qml" line="81"/>
<source> MB</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Sidebar.qml" line="87"/>
<source>No description...</source>
@ -1310,46 +1333,6 @@
<source>Subscribe</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="116"/>
<source>Tools Overview</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="128"/>
<source>Video Import (.webm)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="134"/>
<source>GIF Wallpaper</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="140"/>
<source>QML Wallpaper</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="146"/>
<source>HTML5 Wallpaper</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="152"/>
<source>Website Wallpaper</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="158"/>
<source>QML Widget</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="164"/>
<source>HTML Widget</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StartInfo</name>
@ -1372,6 +1355,123 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SteamProfile</name>
<message>
<location filename="../qml/Workshop/SteamProfile.qml" line="78"/>
<location filename="../qml/Workshop/SteamProfile.qml" line="138"/>
<source>Back</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamProfile.qml" line="160"/>
<source>Forward</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SteamWorkshop</name>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="151"/>
<source>Loading</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="163"/>
<source>Download now!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="168"/>
<source>Downloading...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="176"/>
<source>Details</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="202"/>
<source>Open In Steam</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="286"/>
<source>Profile</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="305"/>
<source>Search for Wallpaper and Widgets...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="349"/>
<source>Open Workshop in Steam</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="373"/>
<source>Ranked By Vote</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="376"/>
<source>Publication Date</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="379"/>
<source>Ranked By Trend</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="382"/>
<source>Favorited By Friends</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="385"/>
<source>Created By Friends</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="388"/>
<source>Created By Followed Users</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="391"/>
<source>Not Yet Rated</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="394"/>
<source>Total VotesAsc</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="397"/>
<source>Votes Up</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="400"/>
<source>Total Unique Subscriptions</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="449"/>
<source>Back</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="473"/>
<source>Forward</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TagSelector</name>
<message>
@ -1458,7 +1558,7 @@
<message>
<location filename="../qml/Workshop/upload/UploadProject.qml" line="142"/>
<source>Abort</source>
<translation type="unfinished">Cancel</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/upload/UploadProject.qml" line="157"/>
@ -2123,109 +2223,6 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Workshop</name>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="171"/>
<source>Loading</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="183"/>
<source>Download now!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="188"/>
<source>Downloading...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="196"/>
<source>Details</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="222"/>
<source>Open In Steam</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="281"/>
<source>Search for Wallpaper and Widgets...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="347"/>
<source>Open Workshop in Steam</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="359"/>
<source>Open GameHub in Steam</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="383"/>
<source>Ranked By Vote</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="386"/>
<source>Publication Date</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="389"/>
<source>Ranked By Trend</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="392"/>
<source>Favorited By Friends</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="395"/>
<source>Created By Friends</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="398"/>
<source>Created By Followed Users</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="401"/>
<source>Not Yet Rated</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="404"/>
<source>Total VotesAsc</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="407"/>
<source>Votes Up</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="410"/>
<source>Total Unique Subscriptions</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="460"/>
<source>Back</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="484"/>
<source>Forward</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>WorkshopItem</name>
<message>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -89,7 +89,7 @@
<message>
<location filename="../qml/Community/Community.qml" line="56"/>
<source>Issue List</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../qml/Community/Community.qml" line="62"/>
@ -99,7 +99,7 @@
<message>
<location filename="../qml/Community/Community.qml" line="68"/>
<source>Steam Workshop</source>
<translation></translation>
<translation>Steam </translation>
</message>
</context>
<context>
@ -107,42 +107,42 @@
<message>
<location filename="../qml/Community/CommunityNavItem.qml" line="57"/>
<source>Open in browser</source>
<translation></translation>
<translation></translation>
</message>
</context>
<context>
<name>CreateWallpaperInit</name>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="31"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="32"/>
<source>Import any video type</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="37"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="38"/>
<source>Depending on your PC configuration it is better to convert your wallpaper to a specific video codec. If both have bad performance you can also try a QML wallpaper! Supported video formats are:
*.mp4 *.mpg *.mp2 *.mpeg *.ogv *.avi *.wmv *.m4v *.3gp *.flv</source>
<translation>PC配置QML壁纸
<translation>PC配置 QML
*.mp4 *.mpg *.mp2 *.mpeg *.ogv *.avi *.wmv *.m4v *.3gp *.flv</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="52"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="53"/>
<source>Set your preffered video codec:</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="97"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="98"/>
<source>Quality slider. Lower value means better quality.</source>
<translation> </translation>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="112"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="113"/>
<source>Open Documentation</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="130"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml" line="132"/>
<source>Select file</source>
<translation></translation>
</message>
@ -157,7 +157,7 @@
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperResult.qml" line="91"/>
<source>Copy text to clipboard</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperResult.qml" line="102"/>
@ -167,90 +167,90 @@
</context>
<context>
<name>CreateWallpaperVideoImportConvert</name>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="47"/>
<source>Generating preview image...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="50"/>
<source>Generating preview thumbnail image...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="57"/>
<source>Generating 5 second preview video...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="60"/>
<source>Generating preview gif...</source>
<translation>gif...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="69"/>
<source>Converting Audio...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="72"/>
<source>Converting Video... This can take some time!</source>
<translation>... </translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="75"/>
<source>Converting Video ERROR!</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="78"/>
<source>Analyse Video ERROR!</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="106"/>
<source>Convert a video to a wallpaper</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImportConvert.qml" line="198"/>
<source></source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="221"/>
<source>Generating preview video...</source>
<translation>...</translation>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="48"/>
<source>Generating preview image...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="281"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="51"/>
<source>Generating preview thumbnail image...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="58"/>
<source>Generating 5 second preview video...</source>
<translation>5...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="61"/>
<source>Generating preview gif...</source>
<translation>GIF...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="70"/>
<source>Converting Audio...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="73"/>
<source>Converting Video... This can take some time!</source>
<translation>... </translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="77"/>
<source>Converting Video ERROR!</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="80"/>
<source>Analyse Video ERROR!</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="108"/>
<source>Convert a video to a wallpaper</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="219"/>
<source>Generating preview video...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="275"/>
<source>Name (required!)</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="295"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="289"/>
<source>Description</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="303"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="297"/>
<source>Youtube URL</source>
<translation>Youtube链接</translation>
<translation>Youtube </translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="334"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="327"/>
<source>Abort</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="347"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="340"/>
<source>Save</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="382"/>
<location filename="../qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml" line="377"/>
<source>Save Wallpaper...</source>
<translation>...</translation>
<translation>...</translation>
</message>
</context>
<context>
@ -268,7 +268,7 @@
<message>
<location filename="../qml/Monitors/DefaultVideoControls.qml" line="66"/>
<source>Current Video Time</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../qml/Monitors/DefaultVideoControls.qml" line="83"/>
@ -298,7 +298,7 @@
<message>
<location filename="../qml/Monitors/DefaultVideoControls.qml" line="114"/>
<source>Scale_Down</source>
<translation></translation>
<translation></translation>
</message>
</context>
<context>
@ -324,17 +324,17 @@
<message>
<location filename="../qml/Create/Wizards/GifWallpaper.qml" line="26"/>
<source>Import a Gif Wallpaper</source>
<translation>GIF壁纸</translation>
<translation> GIF </translation>
</message>
<message>
<location filename="../qml/Create/Wizards/GifWallpaper.qml" line="82"/>
<source>Drop a *.gif file here or use &apos;Select file&apos; below.</source>
<translation>gif文件拖到这使&apos;&apos;</translation>
<translation> *.gif 使 &apos;&apos;</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/GifWallpaper.qml" line="105"/>
<source>Select your gif</source>
<translation>GIF</translation>
<translation> GIF</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/GifWallpaper.qml" line="120"/>
@ -344,7 +344,7 @@
<message>
<location filename="../qml/Create/Wizards/GifWallpaper.qml" line="127"/>
<source>Wallpaper name</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/GifWallpaper.qml" line="135"/>
@ -362,7 +362,7 @@
<message>
<location filename="../qml/Create/Wizards/HTMLWallpaper.qml" line="29"/>
<source>Create a HTML Wallpaper</source>
<translation>HTML壁</translation>
<translation> HTML </translation>
</message>
<message>
<location filename="../qml/Create/Wizards/HTMLWallpaper.qml" line="34"/>
@ -372,12 +372,12 @@
<message>
<location filename="../qml/Create/Wizards/HTMLWallpaper.qml" line="44"/>
<source>Wallpaper name</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/HTMLWallpaper.qml" line="53"/>
<source>Created By</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/HTMLWallpaper.qml" line="62"/>
@ -400,7 +400,7 @@
<message>
<location filename="../qml/Create/Wizards/HTMLWidget.qml" line="20"/>
<source>Create a HTML widget</source>
<translation>HTML部</translation>
<translation> HTML </translation>
</message>
<message>
<location filename="../qml/Create/Wizards/HTMLWidget.qml" line="74"/>
@ -410,7 +410,7 @@
<message>
<location filename="../qml/Create/Wizards/HTMLWidget.qml" line="82"/>
<source>Widget name</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/HTMLWidget.qml" line="90"/>
@ -436,7 +436,7 @@
<message>
<location filename="../qml/Common/HeadlineSection.qml" line="6"/>
<source>Headline Section</source>
<translation></translation>
<translation></translation>
</message>
</context>
<context>
@ -444,7 +444,7 @@
<message>
<location filename="../qml/Common/ImageSelector.qml" line="118"/>
<source>Set your own preview image</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../qml/Common/ImageSelector.qml" line="159"/>
@ -459,95 +459,95 @@
</context>
<context>
<name>ImportWebmConvert</name>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="42"/>
<source>AnalyseVideo...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="45"/>
<source>Generating preview image...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="48"/>
<source>Generating preview thumbnail image...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="55"/>
<source>Generating 5 second preview video...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="58"/>
<source>Generating preview gif...</source>
<translation>gif...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="67"/>
<source>Converting Audio...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="70"/>
<source>Converting Video... This can take some time!</source>
<translation>... </translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="73"/>
<source>Converting Video ERROR!</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="76"/>
<source>Analyse Video ERROR!</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="104"/>
<source>Import a video to a wallpaper</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="189"/>
<source></source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="214"/>
<source>Generating preview video...</source>
<translation>...</translation>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="43"/>
<source>AnalyseVideo...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="274"/>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="46"/>
<source>Generating preview image...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="49"/>
<source>Generating preview thumbnail image...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="56"/>
<source>Generating 5 second preview video...</source>
<translation>5...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="59"/>
<source>Generating preview gif...</source>
<translation> GIF...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="68"/>
<source>Converting Audio...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="71"/>
<source>Converting Video... This can take some time!</source>
<translation>... </translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="74"/>
<source>Converting Video ERROR!</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="77"/>
<source>Analyse Video ERROR!</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="105"/>
<source>Import a video to a wallpaper</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="215"/>
<source>Generating preview video...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="275"/>
<source>Name (required!)</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="288"/>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="289"/>
<source>Description</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="296"/>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="297"/>
<source>Youtube URL</source>
<translation>Youtube链接</translation>
<translation>Youtube </translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="327"/>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="328"/>
<source>Abort</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="340"/>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="341"/>
<source>Save</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml" line="375"/>
<source>Save Wallpaper...</source>
<translation>...</translation>
<translation>...</translation>
</message>
</context>
<context>
@ -555,17 +555,17 @@
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmInit.qml" line="32"/>
<source>Import a .webm video</source>
<translation>webm视</translation>
<translation> .webm </translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmInit.qml" line="48"/>
<source>When importing webm we can skip the long conversion. When you get unsatisfying results with the ScreenPlay importer from &apos;ideo import and convert (all types)&apos; you can also convert via the free and open source HandBrake!</source>
<translation>webm时&apos;ideo导入和转&apos;ScreenPlay导入器得到的结果不满意时使HandBrake!</translation>
<translation>webm时&apos;&apos; ScreenPlay 使HandBrake!</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmInit.qml" line="74"/>
<source>Invalid file type. Must be valid VP8 or VP9 (*.webm)!</source>
<translation>VP8/VP9*.webm</translation>
<translation> VP8 / VP9*.webm</translation>
</message>
<message>
<location filename="../qml/Create/Wizards/ImportWebm/ImportWebmInit.qml" line="97"/>
@ -586,38 +586,43 @@
<context>
<name>Installed</name>
<message>
<location filename="../qml/Installed/Installed.qml" line="130"/>
<location filename="../qml/Installed/Installed.qml" line="131"/>
<source>Refreshing!</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="133"/>
<location filename="../qml/Installed/Installed.qml" line="148"/>
<location filename="../qml/Installed/Installed.qml" line="134"/>
<location filename="../qml/Installed/Installed.qml" line="149"/>
<source>Pull to refresh!</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="178"/>
<location filename="../qml/Installed/Installed.qml" line="179"/>
<source>Get more Wallpaper &amp; Widgets via the Steam workshop!</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="242"/>
<location filename="../qml/Installed/Installed.qml" line="244"/>
<source>Open containing folder</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="250"/>
<source>Deinstall Item</source>
<translation></translation>
<location filename="../qml/Installed/Installed.qml" line="252"/>
<source>Remove Item</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="252"/>
<source>Remove via Workshop</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="261"/>
<source>Open workshop Page</source>
<source>Open Workshop Page</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Installed.qml" line="276"/>
<location filename="../qml/Installed/Installed.qml" line="277"/>
<source>Are you sure you want to delete this item?</source>
<translation></translation>
</message>
@ -892,6 +897,14 @@
<translation></translation>
</message>
</context>
<context>
<name>ScreenPlayItem</name>
<message>
<location filename="../qml/Installed/ScreenPlayItem.qml" line="206"/>
<source>NEW</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Search</name>
<message>
@ -927,11 +940,6 @@
<source>Send anonymous crash reports and statistics</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="99"/>
<source>Help us make ScreenPlay faster and more stable. All collected data is purely anonymous and only used for development purposes!</source>
<translation>ScreenPlay更快更稳定</translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="110"/>
<source>Set save location</source>
@ -967,6 +975,11 @@
<source>ScreenPlay will start with Windows and will setup your Desktop every time for you.</source>
<translation>ScreenPlay将在操作系统启动时启动</translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="99"/>
<source>Help us make ScreenPlay faster and more stable. All collected data is purely anonymous and only used for development purposes! We use &lt;a href=&quot;https://sentry.io&quot;&gt;sentry.io&lt;/a&gt; to collect and analyze this data. A &lt;b&gt;big thanks to them&lt;/b&gt; for providing us with free premium support for open source projects!</source>
<translation> ScreenPlay 使&lt;a href=&quot;https://sentry.io&quot;&gt;sentry.io&lt;/a&gt; 收集与分析数据。&lt;b&gt;感谢他们&lt;/b&gt; 为我们提供对开源项目免费而优质的服务!</translation>
</message>
<message>
<location filename="../qml/Settings/Settings.qml" line="116"/>
<source>Your storage path is empty!</source>
@ -1189,37 +1202,37 @@
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="287"/>
<location filename="../qml/Installed/Sidebar.qml" line="288"/>
<source>Set Volume</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="306"/>
<location filename="../qml/Installed/Sidebar.qml" line="307"/>
<source>Fill Mode</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="325"/>
<location filename="../qml/Installed/Sidebar.qml" line="326"/>
<source>Stretch</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="328"/>
<location filename="../qml/Installed/Sidebar.qml" line="329"/>
<source>Fill</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="331"/>
<location filename="../qml/Installed/Sidebar.qml" line="332"/>
<source>Contain</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="334"/>
<location filename="../qml/Installed/Sidebar.qml" line="335"/>
<source>Cover</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Installed/Sidebar.qml" line="337"/>
<location filename="../qml/Installed/Sidebar.qml" line="338"/>
<source>Scale-Down</source>
<translation></translation>
</message>
@ -1274,42 +1287,47 @@
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="116"/>
<location filename="../qml/Create/Sidebar.qml" line="118"/>
<source>Tools Overview</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="128"/>
<location filename="../qml/Create/Sidebar.qml" line="124"/>
<source>Video import and convert (all types)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="131"/>
<source>Video Import (.webm)</source>
<translation> (.webm)</translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="134"/>
<location filename="../qml/Create/Sidebar.qml" line="137"/>
<source>GIF Wallpaper</source>
<translation>GIF </translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="140"/>
<location filename="../qml/Create/Sidebar.qml" line="143"/>
<source>QML Wallpaper</source>
<translation>QML </translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="146"/>
<location filename="../qml/Create/Sidebar.qml" line="149"/>
<source>HTML5 Wallpaper</source>
<translation>HTML5 </translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="152"/>
<location filename="../qml/Create/Sidebar.qml" line="155"/>
<source>Website Wallpaper</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="158"/>
<location filename="../qml/Create/Sidebar.qml" line="161"/>
<source>QML Widget</source>
<translation>QML </translation>
</message>
<message>
<location filename="../qml/Create/Sidebar.qml" line="164"/>
<location filename="../qml/Create/Sidebar.qml" line="167"/>
<source>HTML Widget</source>
<translation>HTML </translation>
</message>
@ -1335,6 +1353,123 @@
<translation>steam集成</translation>
</message>
</context>
<context>
<name>SteamProfile</name>
<message>
<location filename="../qml/Workshop/SteamProfile.qml" line="78"/>
<location filename="../qml/Workshop/SteamProfile.qml" line="138"/>
<source>Back</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamProfile.qml" line="160"/>
<source>Forward</source>
<translation></translation>
</message>
</context>
<context>
<name>SteamWorkshop</name>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="151"/>
<source>Loading</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="163"/>
<source>Download now!</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="168"/>
<source>Downloading...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="176"/>
<source>Details</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="202"/>
<source>Open In Steam</source>
<translation>Steam打开</translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="286"/>
<source>Profile</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="305"/>
<source>Search for Wallpaper and Widgets...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="349"/>
<source>Open Workshop in Steam</source>
<translation>Steam中打开创意工坊</translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="373"/>
<source>Ranked By Vote</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="376"/>
<source>Publication Date</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="379"/>
<source>Ranked By Trend</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="382"/>
<source>Favorited By Friends</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="385"/>
<source>Created By Friends</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="388"/>
<source>Created By Followed Users</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="391"/>
<source>Not Yet Rated</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="394"/>
<source>Total VotesAsc</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="397"/>
<source>Votes Up</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="400"/>
<source>Total Unique Subscriptions</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="449"/>
<source>Back</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/SteamWorkshop.qml" line="473"/>
<source>Forward</source>
<translation></translation>
</message>
</context>
<context>
<name>TagSelector</name>
<message>
@ -2086,109 +2221,6 @@
<translation>...</translation>
</message>
</context>
<context>
<name>Workshop</name>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="171"/>
<source>Loading</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="183"/>
<source>Download now!</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="188"/>
<source>Downloading...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="196"/>
<source>Details</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="222"/>
<source>Open In Steam</source>
<translation>Steam打开</translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="281"/>
<source>Search for Wallpaper and Widgets...</source>
<translation>...</translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="347"/>
<source>Open Workshop in Steam</source>
<translation>Steam中打开创意工坊</translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="359"/>
<source>Open GameHub in Steam</source>
<translation>Steam中打开游戏社区</translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="383"/>
<source>Ranked By Vote</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="386"/>
<source>Publication Date</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="389"/>
<source>Ranked By Trend</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="392"/>
<source>Favorited By Friends</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="395"/>
<source>Created By Friends</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="398"/>
<source>Created By Followed Users</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="401"/>
<source>Not Yet Rated</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="404"/>
<source>Total VotesAsc</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="407"/>
<source>Votes Up</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="410"/>
<source>Total Unique Subscriptions</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="460"/>
<source>Back</source>
<translation></translation>
</message>
<message>
<location filename="../qml/Workshop/Workshop.qml" line="484"/>
<source>Forward</source>
<translation></translation>
</message>
</context>
<context>
<name>WorkshopItem</name>
<message>

View File

@ -1,42 +0,0 @@
Function Execute-Command ($commandTitle, $commandPath, $commandArguments)
{
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "$commandPath"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.WorkingDirectory = "$PSScriptRoot"
$pinfo.Arguments = $commandArguments
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$exitcodestr = $p.ExitCode.ToString()
Write-Output $p.StandardOutput.ReadToEnd()
Write-Output $p.StandardError.ReadToEnd()
Write-Output "Exit code: $exitcodestr"
}
$MSVCPATH = Read-Host 'Type your ABSOLUTE Qt "bin" directory (default is C:\Qt\5.15.2\msvc2019_64\bin)'
if ($MSVCPATH -eq "") {
echo "Using default directory..."
$MSVCPATH = "C:\Qt\5.15.2\msvc2019_64\bin"
}
echo "Testing directory..."
if (((Test-Path -Path "$MSVCPATH\lupdate.exe") -eq $true) -and ((Test-Path -Path "$MSVCPATH\lrelease.exe") -eq $true)) {
echo "Begin update translations..."
$files = Get-ChildItem ".\*.ts"
foreach ($f in $files){
echo $PSScriptRoot
echo "Processing $f (1/2)"
Execute-Command -commandTitle "Update translation file: $f" -commandPath "$MSVCPATH\lupdate.exe" -commandArguments "-extensions qml ..\qml -ts ""$f"""
echo "Processing $f (2/2)"
Execute-Command -commandTitle "Compile translation file: $f" -commandPath "$MSVCPATH\lrelease.exe" -commandArguments """$f"""
echo "Done"
}
echo "Updated translations."
}
else
{
echo "lupdate or lrelease dosen't exist, failed to update translations..."
}
pause

View File

@ -1,28 +0,0 @@
#!/bin/bash
read -p 'Type your ABSOLUTE Qt "bin" directory (default is /usr/bin): ' path
if [ o$path == "o" ]
then
echo "Using default directory..."
path="/usr/bin"
fi
echo "Testing directory..."
if [[ -f "$path/lupdate" ]] && [[ -f "$path/lrelease" ]]
then
echo "Begin update translations..."
for f in ls *.ts
do
echo "Processing $f (1/2)"
$path/lupdate -extensions qml ../qml -ts $f
echo "Processing $f (2/2)"
$path/lrelease $f
echo "Done"
done
echo "Updated translations."
else
echo "lupdate or lrelease dosen't exist, failed to update translations..."
fi
echo Enter to exit.
read

View File

@ -3,12 +3,9 @@ project(ScreenPlaySDK LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)
find_package(
QT NAMES Qt6 Qt5
COMPONENTS Quick Network Core
REQUIRED)
find_package(
Qt${QT_VERSION_MAJOR}
Qt6
COMPONENTS Quick Network Core
REQUIRED)
@ -20,5 +17,4 @@ add_library(${PROJECT_NAME} ${src} ${headers})
target_include_directories(${PROJECT_NAME} PUBLIC inc)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Network)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick Qt6::Gui Qt6::Network)

View File

@ -3,12 +3,9 @@ project(ScreenPlayShader LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)
find_package(
QT NAMES Qt6 Qt5
COMPONENTS Quick Core
REQUIRED)
find_package(
Qt${QT_VERSION_MAJOR}
Qt6
COMPONENTS Quick Core
REQUIRED)
@ -26,7 +23,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC inc)
set(URI "ScreenPlay/Shader")
string(REPLACE "." "/" TARGETPATH ${URI})
if(NOT DEFINED QT_QMAKE_EXECUTABLE)
get_target_property(QT_QMAKE_EXECUTABLE Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION)
get_target_property(QT_QMAKE_EXECUTABLE Qt6::qmake IMPORTED_LOCATION)
if(NOT QT_QMAKE_EXECUTABLE)
message(FATAL_ERROR "Cannot find qmake")
endif()
@ -56,4 +53,4 @@ else()
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:ScreenPlayShader> ${DESTDIR}/$<TARGET_FILE_NAME:ScreenPlayShader>)
endif()
target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick Qt${QT_VERSION_MAJOR}::Gui)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick Qt6::Gui)

View File

@ -5,13 +5,9 @@ set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)
find_package(infoware CONFIG REQUIRED)
find_package(
QT NAMES Qt6 Qt5
COMPONENTS Quick Core
REQUIRED)
find_package(
Qt${QT_VERSION_MAJOR}
Qt6
COMPONENTS Quick Core
REQUIRED)
@ -40,7 +36,7 @@ add_library(${PROJECT_NAME} SHARED ${src} ${headers})
set(URI "ScreenPlay/Sysinfo")
string(REPLACE "." "/" TARGETPATH ${URI})
if(NOT DEFINED QT_QMAKE_EXECUTABLE)
get_target_property(QT_QMAKE_EXECUTABLE Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION)
get_target_property(QT_QMAKE_EXECUTABLE Qt6::qmake IMPORTED_LOCATION)
if(NOT QT_QMAKE_EXECUTABLE)
message(FATAL_ERROR "Cannot find qmake")
endif()
@ -61,4 +57,4 @@ add_custom_command(
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:ScreenPlaySysInfo> ${DESTDIR}/$<TARGET_FILE_NAME:ScreenPlaySysInfo>)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick infoware)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick infoware)

View File

@ -3,12 +3,9 @@ project(ScreenPlayUtil LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)
find_package(
QT NAMES Qt6 Qt5
COMPONENTS Core
REQUIRED)
find_package(
Qt${QT_VERSION_MAJOR}
Qt6
COMPONENTS Core
REQUIRED)
@ -17,10 +14,8 @@ 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_include_directories(
${PROJECT_NAME}
PUBLIC inc/public/
PRIVATE src/)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Core)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core)

View File

@ -34,6 +34,7 @@
#pragma once
#include <QDateTime>
#include <QDebug>
#include <QJsonArray>
#include <QJsonObject>
@ -58,6 +59,7 @@ struct ProjectFile {
const QJsonObject& obj,
const QString& folderName,
const QUrl& absolutePath,
const bool isNew,
const QDateTime& lastModified)
{
@ -114,6 +116,7 @@ struct ProjectFile {
m_preview = m_previewGIF;
}
m_searchType = ScreenPlayUtil::getSearchTypeFromInstalledType(m_type);
m_isNew = isNew;
m_lastModified = lastModified;
}
@ -135,6 +138,7 @@ struct ProjectFile {
InstalledType::InstalledType m_type = InstalledType::InstalledType::Unknown;
SearchType::SearchType m_searchType = SearchType::SearchType::All;
bool m_isNew = false;
QDateTime m_lastModified;
};
}

View File

@ -4,7 +4,21 @@ set(CMAKE_CXX_STANDARD 20)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core)
find_package(QT NAMES Qt6 COMPONENTS Core)
find_package(
Qt6
COMPONENTS Core
Quick
Gui
Widgets
WebSockets
Svg
Multimedia
WebEngineCore
WebEngineQuick
WebChannel
Positioning)
if(WIN32)
set(src_plattform src/windowsdesktopproperties.cpp src/winwindow.cpp)
@ -21,13 +35,25 @@ set(src main.cpp src/basewindow.cpp)
set(headers src/basewindow.h)
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
qt6_add_resources (resources SPWResources.qrc)
qt6_add_resources(resources SPWResources.qrc)
else()
qt6_add_resources (resources SPWResources.qrc)
qt6_add_resources(resources SPWResources.qrc)
endif()
add_executable(${PROJECT_NAME} ${src} ${headers} ${src_plattform} ${headers_plattform} ${resources})
target_link_libraries(
${PROJECT_NAME}
PRIVATE Qt6::Quick
Qt6::Gui
Qt6::Widgets
Qt6::Core
Qt6::WebSockets
Qt6::Svg
Qt6::Multimedia
Qt6::WebEngineCore
Qt6::WebEngineQuick)
if(WIN32)
# Disable console window on Windows
# https://stackoverflow.com/questions/8249028/how-do-i-keep-my-qt-c-program-from-opening-a-console-in-windows
@ -42,48 +68,14 @@ endif()
target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlaySDK ScreenPlayUtil)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
find_package(
Qt${QT_VERSION_MAJOR}
COMPONENTS Core
Quick
Gui
Widgets
WebSockets
Svg
Multimedia
WebEngineCore
WebEngineQuick
WebChannel
Positioning)
target_link_libraries(
${PROJECT_NAME}
PRIVATE Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::WebSockets
Qt${QT_VERSION_MAJOR}::Svg
Qt6::Multimedia
Qt6::WebEngineCore
Qt6::WebEngineQuick)
else()
find_package(
Qt${QT_VERSION_MAJOR}
COMPONENTS Core
Quick
Gui
Widgets
WebSockets
Svg
WebEngine)
target_link_libraries(
${PROJECT_NAME}
PRIVATE Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::WebSockets
Qt${QT_VERSION_MAJOR}::Svg
Qt5::WebEngine)
if(WIN32)
# Disable console window on Windows
# https://stackoverflow.com/questions/8249028/how-do-i-keep-my-qt-c-program-from-opening-a-console-in-windows
set_property(TARGET ${PROJECT_NAME} PROPERTY WIN32_EXECUTABLE true)
target_link_libraries(${PROJECT_NAME} PRIVATE shcore.lib)
endif()
if(APPLE)
set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE TRUE MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist)
target_link_libraries(${PROJECT_NAME} PRIVATE "-framework Cocoa")
endif()

View File

@ -16,10 +16,12 @@
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleDisplayName</key>
<string>ScreenPlayWallpaper</string>
<key>CFBundleVersion</key>
<string>0.14</string>
<key>CFBundleShortVersionString</key>
<string>0.14</string>
<key>NSUIElement</key>
<string>1</string>
<key>LSUIElement</key>

View File

@ -1,13 +1,13 @@
<RCC>
<qresource prefix="/">
<file>Wallpaper.qml</file>
<file>Test.qml</file>
<file>dot.png</file>
<file>qtquickcontrols2.conf</file>
<file>WebView.qml</file>
<file>index.html</file>
<file>GifWallpaper.qml</file>
<file>WebsiteWallpaper.qml</file>
<file>MultimediaView.qml</file>
<file>qml/GifWallpaper.qml</file>
<file>qml/Test.qml</file>
<file>qml/Wallpaper.qml</file>
<file>qml/WebsiteWallpaper.qml</file>
<file>qml/WebView.qml</file>
<file>qml/MultimediaView.qml</file>
</qresource>
</RCC>

View File

@ -47,9 +47,9 @@ int main(int argc, char* argv[])
WinWindow window1({ 0 }, "test", "appID=test", "1", "fill", "videoWallpaper", true, true);
//WinWindow window1({ 0 }, "C:/Program Files (x86)/Steam/steamapps/workshop/content/672870/_tmp_171806", "appID=test", "1", "fill", "videoWallpaper", true, true);
#elif defined(Q_OS_LINUX)
LinuxWindow window({ 0 }, "test", "appid", "1", "fill", false);
LinuxWindow window({ 0 }, "test", "appID=test", "1", "fill", "videoWallpaper", false, true);
#elif defined(Q_OS_OSX)
MacWindow window({ 0 }, "test", "appID=test", "1", "fill","videoWallpaper", true, true);
MacWindow window({ 0 }, "test", "appID=test", "1", "fill", "videoWallpaper", true, true);
#endif
return app.exec();
}
@ -93,21 +93,23 @@ int main(int argc, char* argv[])
#elif defined(Q_OS_LINUX)
LinuxWindow window(
activeScreensList.value(),
projectPath,
projectFilePath,
appID,
fillmode,
volume,
checkWallpaperVisible);
fillmode,
type,
checkWallpaperVisible,
debugMode);
#elif defined(Q_OS_OSX)
MacWindow window(
activeScreensList.value(),
projectFilePath,
appID,
volume,
fillmode,
type,
checkWallpaperVisible,
debugMode);
activeScreensList.value(),
projectFilePath,
appID,
volume,
fillmode,
type,
checkWallpaperVisible,
debugMode);
#endif
return app.exec();

View File

@ -3,8 +3,6 @@ import QtQuick 2.14
import QtQuick.Controls 2.14
import ScreenPlayWallpaper 1.0
import ScreenPlay.Enums.InstalledType 1.0
import ScreenPlay.Shader 1.0
import "ShaderWrapper" as ShaderWrapper
Rectangle {
id: root
@ -17,7 +15,7 @@ Rectangle {
loader.source = "qrc:/MultimediaView.qml";
break;
case InstalledType.HTMLWallpaper:
loader.setSource("qrc:/WebView.qml", {
loader.setSource("qrc:/qml/WebView.qml", {
"url": Qt.resolvedUrl(Wallpaper.projectSourceFileAbsolute)
});
break;
@ -26,13 +24,13 @@ Rectangle {
fadeIn();
break;
case InstalledType.WebsiteWallpaper:
loader.setSource("qrc:/WebsiteWallpaper.qml", {
loader.setSource("qrc:/qml/WebsiteWallpaper.qml", {
"url": Wallpaper.projectSourceFileAbsolute
});
fadeIn();
break;
case InstalledType.GifWallpaper:
loader.setSource("qrc:/GifWallpaper.qml", {
loader.setSource("qrc:/qml/GifWallpaper.qml", {
"source": Qt.resolvedUrl(Wallpaper.projectSourceFileAbsolute)
});
fadeIn();
@ -96,7 +94,7 @@ Rectangle {
return ;
imgCover.state = "showDefaultBackgroundImage";
loader.source = "qrc:/WebView.qml";
loader.source = "qrc:/qml/WebView.qml";
}
target: Wallpaper

View File

@ -8,31 +8,31 @@ Item {
property alias url: webView.url
signal requestFadeIn()
signal requestFadeIn
function getSetVideoCommand() {
// TODO 30:
// Currently wont work. Commit anyways til QtCreator and Qt work with js template literals
var src = "";
src += "var videoPlayer = document.getElementById('videoPlayer');";
src += "var videoSource = document.getElementById('videoSource');";
src += "videoSource.src = '" + Wallpaper.projectSourceFileAbsolute + "';";
src += "videoPlayer.load();";
src += "videoPlayer.volume = " + Wallpaper.volume + ";";
src += "videoPlayer.setAttribute('style', 'object-fit :" + Wallpaper.fillMode + ";');";
src += "videoPlayer.play();";
return src;
var src = ""
src += "var videoPlayer = document.getElementById('videoPlayer');"
src += "var videoSource = document.getElementById('videoSource');"
src += "videoSource.src = '" + Wallpaper.projectSourceFileAbsolute + "';"
src += "videoPlayer.load();"
src += "videoPlayer.volume = " + Wallpaper.volume + ";"
src += "videoPlayer.setAttribute('style', 'object-fit :" + Wallpaper.fillMode + ";');"
src += "videoPlayer.play();"
return src
}
Component.onCompleted: {
WebEngine.settings.localContentCanAccessFileUrls = true;
WebEngine.settings.localContentCanAccessRemoteUrls = true;
WebEngine.settings.allowRunningInsecureContent = true;
WebEngine.settings.accelerated2dCanvasEnabled = true;
WebEngine.settings.javascriptCanOpenWindows = false;
WebEngine.settings.showScrollBars = false;
WebEngine.settings.playbackRequiresUserGesture = false;
WebEngine.settings.focusOnNavigationEnabled = true;
WebEngine.settings.localContentCanAccessFileUrls = true
WebEngine.settings.localContentCanAccessRemoteUrls = true
WebEngine.settings.allowRunningInsecureContent = true
WebEngine.settings.accelerated2dCanvasEnabled = true
WebEngine.settings.javascriptCanOpenWindows = false
WebEngine.settings.showScrollBars = false
WebEngine.settings.playbackRequiresUserGesture = false
WebEngine.settings.focusOnNavigationEnabled = true
}
WebEngineView {
@ -45,18 +45,18 @@ Item {
onLoadProgressChanged: {
if ((loadProgress === 100)) {
if (Wallpaper.type === InstalledType.VideoWallpaper)
webView.runJavaScript(root.getSetVideoCommand(), function(result) {
requestFadeIn();
});
webView.runJavaScript(root.getSetVideoCommand(),
function (result) {
requestFadeIn()
})
else
requestFadeIn();
requestFadeIn()
}
}
}
Text {
id: txtVisualsPaused
text: qsTr("If you can read this, then the VisualsPaused optimization does not work on your system. You can fix this by disable this in: \n Settings -> Perfromance -> Pause wallpaper video rendering while another app is in the foreground ")
font.pointSize: 32
visible: false
@ -73,77 +73,82 @@ Item {
interval: 300
onTriggered: {
webView.visible = !Wallpaper.visualsPaused;
txtVisualsPaused.visible = Wallpaper.visualsPaused;
webView.visible = !Wallpaper.visualsPaused
txtVisualsPaused.visible = Wallpaper.visualsPaused
}
}
Connections {
function onReloadVideo(oldType) {
webView.runJavaScript(root.getSetVideoCommand());
webView.runJavaScript(root.getSetVideoCommand())
}
function onQmlExit() {
webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = 0;");
webView.runJavaScript(
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = 0;")
}
function onMutedChanged(muted) {
if (muted)
webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = 0;");
webView.runJavaScript(
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = 0;")
else
webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = " + Wallpaper.volume + ";");
webView.runJavaScript(
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = " + Wallpaper.volume + ";")
}
function onFillModeChanged(fillMode) {
if (webView.loadProgress === 100)
webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.setAttribute('style', 'object-fit :" + fillMode + ";');");
webView.runJavaScript(
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.setAttribute('style', 'object-fit :" + fillMode + ";');")
}
function onLoopsChanged(loops) {
if (webView.loadProgress === 100)
webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.loop = " + loops + ";");
webView.runJavaScript(
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.loop = " + loops + ";")
}
function onVolumeChanged(volume) {
if (webView.loadProgress === 100)
webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = " + volume + ";");
webView.runJavaScript(
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = " + volume + ";")
}
function onCurrentTimeChanged(currentTime) {
if (webView.loadProgress === 100)
webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.currentTime = " + currentTime + " * videoPlayer.duration;");
webView.runJavaScript(
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.currentTime = "
+ currentTime + " * videoPlayer.duration;")
}
function onPlaybackRateChanged(playbackRate) {
if (webView.loadProgress === 100)
webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.playbackRate = " + playbackRate + ";");
webView.runJavaScript(
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.playbackRate = " + playbackRate + ";")
}
function onVisualsPausedChanged(visualsPaused) {
if (visualsPaused) {
// Wait until Wallpaper animation is finsihed
timerCover.restart();
timerCover.restart()
} else {
webView.visible = true;
txtVisualsPaused.visible = false;
webView.visible = true
txtVisualsPaused.visible = false
}
}
function onIsPlayingChanged(isPlaying) {
if (webView.loadProgress === 100) {
if (isPlaying)
webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.play();");
webView.runJavaScript(
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.play();")
else
webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.pause();");
webView.runJavaScript(
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.pause();")
}
}
target: Wallpaper
}
}

View File

@ -54,7 +54,7 @@ BaseWindow::BaseWindow(
if (projectFilePath == "test") {
setType(ScreenPlay::InstalledType::InstalledType::QMLWallpaper);
setProjectSourceFileAbsolute({ "qrc:/Test.qml" });
setProjectSourceFileAbsolute({ "qrc:/qml/Test.qml" });
setupLiveReloading();
return;
}

View File

@ -150,6 +150,7 @@ public slots:
virtual void destroyThis() { }
virtual void setVisible(bool show) { Q_UNUSED(show) }
virtual void messageReceived(QString key, QString value) final;
virtual void clearComponentCache() {}
virtual void replaceWallpaper(
const QString absolutePath,
const QString file,
@ -357,31 +358,31 @@ private:
private:
bool m_checkWallpaperVisible { false };
bool m_visualsPaused { false };
bool m_loops { true };
bool m_isPlaying { true };
bool m_muted { false };
bool m_canFade { false };
bool m_debugMode { false };
float m_volume { 1.0f };
float m_playbackRate { 1.0f };
float m_currentTime { 0.0f };
QString m_contentBasePath;
QString m_projectPath;
QString m_projectSourceFile;
QString m_appID;
ScreenPlay::InstalledType::InstalledType m_type = ScreenPlay::InstalledType::InstalledType::Unknown;
QString m_OSVersion;
QString m_fillMode;
int m_width { 0 };
int m_height { 0 };
ScreenPlay::InstalledType::InstalledType m_type = ScreenPlay::InstalledType::InstalledType::Unknown;
QVector<int> m_activeScreensList;
QFileSystemWatcher m_fileSystemWatcher;
QTimer m_liveReloadLimiter;
QSysInfo m_sysinfo;
bool m_debugMode = false;
std::unique_ptr<ScreenPlaySDK> m_sdk;
QString m_contentBasePath;
QString m_projectPath;
QString m_projectSourceFile;
QUrl m_projectSourceFileAbsolute;
};

View File

@ -1,15 +1,28 @@
#include "linuxwindow.h"
LinuxWindow::LinuxWindow(QVector<int> activeScreensList, QString projectPath, QString id, QString volume, const QString fillmode, const bool checkWallpaperVisible, QObject* parent)
: BaseWindow(projectPath, activeScreensList, checkWallpaperVisible)
LinuxWindow::LinuxWindow(
const QVector<int>& activeScreensList,
const QString& projectFilePath,
const QString& appID,
const QString& volume,
const QString& fillmode,
const QString& type,
const bool checkWallpaperVisible,
const bool debugMode,
QObject* parent)
: BaseWindow(
activeScreensList,
projectFilePath,
type,
checkWallpaperVisible,
appID,
debugMode)
{
m_window.setWidth(1920);
m_window.setHeight(1080);
m_window.show();
setAppID(id);
bool ok = false;
float volumeParsed = volume.toFloat(&ok);
if (!ok) {

View File

@ -50,7 +50,16 @@
class LinuxWindow : public BaseWindow {
Q_OBJECT
public:
explicit LinuxWindow(QVector<int> activeScreensList, QString projectPath, QString id, QString volume, const QString fillmode, const bool checkWallpaperVisible, QObject* parent = nullptr);
explicit LinuxWindow(
const QVector<int>& activeScreensList,
const QString& projectFilePath,
const QString& appID,
const QString& volume,
const QString& fillmode,
const QString& type,
const bool checkWallpaperVisible,
const bool debugMode,
QObject* parent = nullptr);
signals:

View File

@ -46,7 +46,7 @@ MacWindow::MacWindow(
m_window.setFlags(flags | Qt::FramelessWindowHint | Qt::Desktop);
m_window.setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView);
m_window.setTextRenderType(QQuickWindow::TextRenderType::NativeTextRendering);
m_window.setSource(QUrl("qrc:/Wallpaper.qml"));
m_window.setSource(QUrl("qrc:/qml/Wallpaper.qml"));
MacIntegration* macIntegration = new MacIntegration(this);
macIntegration->SetBackgroundLevel(&m_window);
@ -63,3 +63,8 @@ void MacWindow::destroyThis()
{
QCoreApplication::quit();
}
void MacWindow::clearComponentCache()
{
m_window.engine()->clearComponentCache();
}

View File

@ -65,6 +65,7 @@ signals:
public slots:
void setVisible(bool show) override;
void destroyThis() override;
void clearComponentCache() override;
private:
QQuickView m_window;

View File

@ -189,6 +189,15 @@ WinWindow::WinWindow(
connect(sdk(), &ScreenPlaySDK::incommingMessage, this, &WinWindow::messageReceived);
connect(sdk(), &ScreenPlaySDK::replaceWallpaper, this, &WinWindow::replaceWallpaper);
connect(&m_checkForFullScreenWindowTimer, &QTimer::timeout, this, &WinWindow::checkForFullScreenWindow);
connect(
&m_window, &QQuickView::statusChanged,
this, [](auto status) {
if (status == QQuickView::Status::Error) {
qInfo() << status;
QCoreApplication::exit(-1);
}
},
Qt::QueuedConnection);
const auto screens = QApplication::screens();
for (const auto& screen : screens) {
@ -480,7 +489,7 @@ void WinWindow::configureWindowGeometry()
// Instead of setting "renderType: Text.NativeRendering" every time we can set it here once
m_window.setTextRenderType(QQuickWindow::TextRenderType::NativeTextRendering);
m_window.setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView);
m_window.setSource(QUrl("qrc:/Wallpaper.qml"));
m_window.setSource(QUrl("qrc:/qml/Wallpaper.qml"));
m_window.hide();
}

View File

@ -73,7 +73,7 @@ public slots:
void setVisible(bool show) override;
void destroyThis() override;
void terminate();
void clearComponentCache();
void clearComponentCache() override;
void setWindowsDesktopProperties(WindowsDesktopProperties* windowsDesktopProperties)
{

View File

@ -4,11 +4,24 @@ set(CMAKE_CXX_STANDARD 20)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core)
find_package(QT NAMES Qt6 COMPONENTS Core)
set(src main.cpp src/widgetwindow.cpp)
set(headers src/widgetwindow.h)
find_package(
Qt6
COMPONENTS Core
Quick
Gui
Widgets
WebSockets
Svg
WebEngineCore
WebEngineQuick
WebChannel
Positioning)
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
qt_add_resources(resources SPWidgetResources.qrc)
else()
@ -17,6 +30,19 @@ endif()
add_executable(${PROJECT_NAME} ${src} ${headers} ${resources})
target_link_libraries(
${PROJECT_NAME}
PRIVATE Qt6::Quick
Qt6::Gui
Qt6::Widgets
Qt6::Core
Qt6::WebSockets
Qt6::Svg
Qt6::WebEngineCore
Qt6::WebEngineQuick)
target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlaySDK ScreenPlayUtil)
if(WIN32)
# Disable console window on Windows
# https://stackoverflow.com/questions/8249028/how-do-i-keep-my-qt-c-program-from-opening-a-console-in-windows
@ -26,49 +52,3 @@ endif()
if(APPLE)
set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE TRUE MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist)
endif()
target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlaySDK ScreenPlayUtil)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
find_package(
Qt${QT_VERSION_MAJOR}
COMPONENTS Core
Quick
Gui
Widgets
WebSockets
Svg
WebEngineCore
WebEngineQuick
WebChannel
Positioning)
target_link_libraries(
${PROJECT_NAME}
PRIVATE Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::WebSockets
Qt${QT_VERSION_MAJOR}::Svg
Qt6::WebEngineCore
Qt6::WebEngineQuick)
else()
find_package(
Qt${QT_VERSION_MAJOR}
COMPONENTS Core
Quick
Gui
Widgets
WebSockets
Svg
WebEngine)
target_link_libraries(
${PROJECT_NAME}
PRIVATE Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::WebSockets
Qt${QT_VERSION_MAJOR}::Svg
Qt5::WebEngine)
endif()

Some files were not shown because too many files have changed in this diff Show More