Compare commits

..

25 Commits

Author SHA1 Message Date
9f57ba69ac Remove camera reboot, bump version to 1.0.0 2025-04-11 22:49:58 -05:00
5afd22a7bf Update copyright year in About 2025-03-29 14:50:54 -05:00
af07f8853a Fix SettingsDialog to do validity check when OK is pressed 2025-03-29 14:45:32 -05:00
2e9b37f3b4 Fix default Show button 2025-03-27 20:32:53 -05:00
c4e792c9a7 Bump version to 1.0-beta6 2025-03-27 20:29:46 -05:00
01cd6b7ba8 Add icon 2025-03-27 20:26:25 -05:00
e42c3a7dc8 Fix 'make run' and 'make debug' 2024-10-30 00:40:31 -05:00
1d66bcc3bb Remove .idea 2024-10-29 23:51:26 -05:00
efab455a24 Cleanup 2024-10-29 23:45:58 -05:00
834a36c417 Fix make run for new buildcore 2024-10-29 23:45:31 -05:00
59aee596e9 Add icon 2024-10-29 23:44:54 -05:00
b96b75a735 [buildcore] Update buildcore 2024-10-29 23:44:45 -05:00
215f9b4d1d Cleanup 2024-10-29 00:46:30 -05:00
4957bec1c6 Cleanup 2024-10-29 00:45:16 -05:00
ef24f01566 Disable Fusion theme on Mac 2024-10-29 00:26:32 -05:00
d0eaad7dfe Remove debug code 2024-10-28 23:59:54 -05:00
fff098d80e Set app organization name 2024-10-28 20:29:42 -05:00
ec18a0c507 Switch Fusion dark theme 2024-10-28 19:46:06 -05:00
88da18a380 Up version 2024-10-27 14:49:16 -05:00
0db9bff0de Split slide tag across lines 2024-10-25 00:44:58 -05:00
a0a1cd8af1 Upgrade OpenLPClient to target OpenLP 3 2024-10-23 22:22:53 -05:00
f4e0b5ab9f Update year in copyright notices 2024-03-08 22:07:39 -06:00
bb825f947e Update version 2024-03-03 21:25:14 -06:00
b71a64ca33 Add Apply button to settings dialog 2024-03-03 21:21:00 -06:00
048b06db97 Fix Image Preview button to use the correct image settings 2024-03-03 21:14:14 -06:00
35 changed files with 369 additions and 240 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
.clangd .clangd
.conanbuild .conanbuild
.current_build .current_build
.idea
__pycache__ __pycache__
CMakeLists.txt.user CMakeLists.txt.user
Session.vim Session.vim

7
.idea/misc.xml generated
View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
<component name="CompDBWorkspace">
<contentRoot DIR="$PROJECT_DIR$" />
</component>
</project>

6
.idea/vcs.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -2,7 +2,7 @@
source: source:
- . - .
copyright_notice: |- copyright_notice: |-
Copyright 2021 - 2023 gary@drinkingtea.net Copyright 2021 - 2024 gary@drinkingtea.net
This Source Code Form is subject to the terms of the Mozilla Public This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -14,6 +14,10 @@ if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-conversion") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-conversion")
endif() endif()
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_INSTALL_RPATH "$ORIGIN" "$ORIGIN/../") set(CMAKE_INSTALL_RPATH "$ORIGIN" "$ORIGIN/../")
if(QTDIR) if(QTDIR)
set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_RPATH} "${QTDIR}/lib") set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_RPATH} "${QTDIR}/lib")

View File

@ -3,15 +3,15 @@ BUILDCORE_PATH=deps/buildcore
VCPKG_PKGS= VCPKG_PKGS=
include ${BUILDCORE_PATH}/base.mk include ${BUILDCORE_PATH}/base.mk
ifeq ($(OS),darwin) ifeq ($(BC_VAR_OS),darwin)
PROJECT_EXECUTABLE=./dist/${CURRENT_BUILD}/${PROJECT_NAME}.app/Contents/MacOS/SlideController PROJECT_EXECUTABLE=./build/${BC_VAR_CURRENT_BUILD}/bin/${PROJECT_NAME}.app/Contents/MacOS/SlideController
else else
PROJECT_EXECUTABLE=./dist/${CURRENT_BUILD}/bin/SlideController PROJECT_EXECUTABLE=./build/${BC_VAR_CURRENT_BUILD}/bin/${PROJECT_NAME}
endif endif
.PHONY: run .PHONY: run
run: install run: build
${ENV_RUN} ${PROJECT_EXECUTABLE} ${ENV_RUN} ${PROJECT_EXECUTABLE}
.PHONY: debug .PHONY: debug
debug: install debug: build
${DEBUGGER} ${PROJECT_EXECUTABLE} ${DEBUGGER} ${PROJECT_EXECUTABLE}

View File

@ -14,7 +14,6 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
# enable ccache # enable ccache
if(NOT DEFINED ENV{BUILDCORE_SUPPRESS_CCACHE}) if(NOT DEFINED ENV{BUILDCORE_SUPPRESS_CCACHE})
find_program(CCACHE_PROGRAM ccache) find_program(CCACHE_PROGRAM ccache)

200
deps/buildcore/base.mk vendored
View File

@ -6,97 +6,106 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
# #
ifndef USE_CONAN
USE_CONAN=0
endif
ifeq (${OS},Windows_NT) ifeq (${OS},Windows_NT)
SHELL := powershell.exe SHELL := powershell.exe
.SHELLFLAGS := -NoProfile -Command .SHELLFLAGS := -NoProfile -Command
OS=windows BC_VAR_OS=windows
HOST_ENV=${OS} BC_CMD_HOST_PY3=python
else else
OS=$(shell uname | tr [:upper:] [:lower:]) BC_VAR_OS=$(shell uname | tr [:upper:] [:lower:])
HOST_ENV=${OS}-$(shell uname -m) ifneq ($(shell which python3 2> /dev/null),)
endif BC_CMD_HOST_PY3=python3
else
DEVENV=devenv$(shell pwd | sed 's/\//-/g') ifeq ($(shell python -c 'import sys; print(sys.version_info[0])'),3)
DEVENV_IMAGE=${PROJECT_NAME}-devenv BC_CMD_HOST_PY3=python
ifneq ($(shell which docker 2> /dev/null),) else
ifeq ($(shell docker inspect --format="{{.State.Status}}" ${DEVENV} 2>&1),running) echo 'Please install Python3 on host'
ENV_RUN=docker exec -i -t --user $(shell id -u ${USER}) ${DEVENV} exit 1
endif
endif endif
endif endif
ifneq ($(shell ${ENV_RUN} which python3 2> /dev/null),)
PYTHON3=python3 ifdef BC_VAR_USE_DOCKER_DEVENV
else ifneq ($(shell which docker 2> /dev/null),)
ifeq ($(shell ${ENV_RUN} python -c 'import sys; print(sys.version_info[0])'),3) BC_VAR_DEVENV=devenv$(shell pwd | sed 's/\//-/g')
PYTHON3=python BC_VAR_DEVENV_IMAGE=${BC_VAR_PROJECT_NAME}-devenv
ifeq ($(shell docker inspect --format="{{.State.Status}}" ${BC_VAR_DEVENV} 2>&1),running)
BC_CMD_ENVRUN=docker exec -i -t --user $(shell id -u ${USER}) ${BC_VAR_DEVENV}
endif endif
endif
ifneq ($(shell ${BC_CMD_ENVRUN} which python3 2> /dev/null),)
BC_CMD_PY3=${BC_CMD_ENVRUN} python3
else
ifeq ($(shell ${BC_CMD_ENVRUN} python -c 'import sys; print(sys.version_info[0])'),3)
BC_CMD_PY3=${BC_CMD_ENVRUN} python
else
echo 'Please install Python3 in devenv'
exit 1
endif
endif
ifndef BC_VAR_DEVENV_ROOT
BC_VAR_DEVENV_ROOT="."
endif
else
BC_CMD_PY3=${BC_CMD_HOST_PY3}
endif endif
SCRIPTS=${BUILDCORE_PATH}/scripts BC_VAR_SCRIPTS=${BUILDCORE_PATH}/scripts
SETUP_BUILD=${PYTHON3} ${SCRIPTS}/setup-build.py BC_CMD_SETUP_BUILD=${BC_CMD_PY3} ${BC_VAR_SCRIPTS}/setup-build.py
PYBB=${PYTHON3} ${SCRIPTS}/pybb.py BC_CMD_PYBB=${BC_CMD_PY3} ${BC_VAR_SCRIPTS}/pybb.py
CMAKE_BUILD=${PYBB} cmake-build BC_CMD_HOST_PYBB=${BC_CMD_HOST_PY3} ${BC_VAR_SCRIPTS}/pybb.py
GET_ENV=${PYBB} getenv BC_CMD_CMAKE_BUILD=${BC_CMD_PYBB} cmake-build
CTEST=${PYBB} ctest-all BC_CMD_GETENV=${BC_CMD_PYBB} getenv
RM_RF=${PYBB} rm BC_CMD_CTEST=${BC_CMD_PYBB} ctest-all
HOST=$(shell ${PYBB} hostname) BC_CMD_RM_RF=${BC_CMD_PYBB} rm
BUILDCORE_HOST_SPECIFIC_BUILDPATH=$(shell ${GET_ENV} BUILDCORE_HOST_SPECIFIC_BUILDPATH) BC_CMD_MKDIR_P=${BC_CMD_PYBB} mkdir
ifneq (${BUILDCORE_HOST_SPECIFIC_BUILDPATH},) BC_CMD_CAT=${BC_CMD_PYBB} cat
BUILD_PATH=build/${HOST} BC_CMD_DEBUGGER=${BC_CMD_PYBB} debug
else BC_CMD_HOST_DEBUGGER=${BC_CMD_HOST_PYBB} debug
BUILD_PATH=build BC_VAR_HOSTENV=$(shell ${BC_CMD_ENVRUN} ${BC_CMD_PYBB} hostenv)
endif BC_VAR_BUILD_PATH=build
ifdef USE_VCPKG BC_VAR_CURRENT_BUILD=$(BC_VAR_HOSTENV)-$(shell ${BC_CMD_ENVRUN} ${BC_CMD_CAT} .current_build)
ifndef VCPKG_DIR_BASE
VCPKG_DIR_BASE=.vcpkg
endif
ifndef VCPKG_VERSION
VCPKG_VERSION=2020.06
endif
VCPKG_TOOLCHAIN=--toolchain=${VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake
endif
ifeq ($(OS),darwin)
DEBUGGER=lldb --
else
DEBUGGER=gdb --args
endif
VCPKG_DIR=$(VCPKG_DIR_BASE)/$(VCPKG_VERSION)-$(HOST_ENV) ifdef BC_VAR_USE_VCPKG
CURRENT_BUILD=$(HOST_ENV)-$(shell ${ENV_RUN} ${PYBB} cat .current_build) ifndef BC_VAR_VCPKG_DIR_BASE
BC_VAR_VCPKG_DIR_BASE=.vcpkg
endif
ifndef BC_VAR_VCPKG_VERSION
BC_VAR_VCPKG_VERSION=2023.08.09
endif
endif
.PHONY: build .PHONY: build
build: build:
${ENV_RUN} ${CMAKE_BUILD} ${BUILD_PATH} ${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH}
.PHONY: install .PHONY: install
install: install:
${ENV_RUN} ${CMAKE_BUILD} ${BUILD_PATH} install ${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} install
.PHONY: clean .PHONY: clean
clean: clean:
${ENV_RUN} ${CMAKE_BUILD} ${BUILD_PATH} clean ${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} clean
.PHONY: purge .PHONY: purge
purge: purge:
${ENV_RUN} ${RM_RF} .current_build ${BC_CMD_RM_RF} .current_build
${ENV_RUN} ${RM_RF} ${BUILD_PATH} ${BC_CMD_RM_RF} ${BC_VAR_BUILD_PATH}
${ENV_RUN} ${RM_RF} dist ${BC_CMD_RM_RF} dist
${ENV_RUN} ${RM_RF} compile_commands.json ${BC_CMD_RM_RF} compile_commands.json
.PHONY: test .PHONY: test
test: build test: build
${ENV_RUN} mypy ${SCRIPTS} ${BC_CMD_ENVRUN} mypy ${BC_VAR_SCRIPTS}
${ENV_RUN} ${CMAKE_BUILD} ${BUILD_PATH} test ${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} test
.PHONY: test-verbose .PHONY: test-verbose
test-verbose: build test-verbose: build
${ENV_RUN} ${CTEST} ${BUILD_PATH} --output-on-failure ${BC_CMD_CTEST} ${BC_VAR_BUILD_PATH} --output-on-failure
.PHONY: test-rerun-verbose .PHONY: test-rerun-verbose
test-rerun-verbose: build test-rerun-verbose: build
${ENV_RUN} ${CTEST} ${BUILD_PATH} --rerun-failed --output-on-failure ${BC_CMD_CTEST} ${BC_VAR_BUILD_PATH} --rerun-failed --output-on-failure
ifdef BC_VAR_USE_DOCKER_DEVENV
.PHONY: devenv-image .PHONY: devenv-image
devenv-image: devenv-image:
docker build . -t ${DEVENV_IMAGE} docker build ${BC_VAR_DEVENV_ROOT} -t ${BC_VAR_DEVENV_IMAGE}
.PHONY: devenv-create .PHONY: devenv-create
devenv-create: devenv-create:
docker run -d \ docker run -d \
@ -108,66 +117,77 @@ devenv-create:
-v $(shell pwd):/usr/src/project \ -v $(shell pwd):/usr/src/project \
-v /dev/shm:/dev/shm \ -v /dev/shm:/dev/shm \
--restart=always \ --restart=always \
--name ${DEVENV} \ --name ${BC_VAR_DEVENV} \
-t ${DEVENV_IMAGE} bash -t ${BC_VAR_DEVENV_IMAGE} bash
.PHONY: devenv-destroy .PHONY: devenv-destroy
devenv-destroy: devenv-destroy:
docker rm -f ${DEVENV} docker rm -f ${BC_VAR_DEVENV}
ifdef ENV_RUN ifdef BC_CMD_ENVRUN
.PHONY: devenv-shell .PHONY: devenv-shell
devenv-shell: devenv-shell:
${ENV_RUN} bash ${BC_CMD_ENVRUN} bash
endif
endif endif
ifdef USE_VCPKG ifdef BC_VAR_USE_VCPKG
BC_VAR_VCPKG_TOOLCHAIN=--toolchain=${BC_VAR_VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake
BC_VAR_VCPKG_DIR=$(BC_VAR_VCPKG_DIR_BASE)/$(BC_VAR_VCPKG_VERSION)-$(BC_VAR_HOSTENV)
.PHONY: vcpkg .PHONY: vcpkg
vcpkg: ${VCPKG_DIR} vcpkg-install vcpkg: ${BC_VAR_VCPKG_DIR} vcpkg-install
${VCPKG_DIR}: ${BC_VAR_VCPKG_DIR}:
${ENV_RUN} ${RM_RF} ${VCPKG_DIR} ${BC_CMD_RM_RF} ${BC_VAR_VCPKG_DIR}
${ENV_RUN} mkdir -p ${VCPKG_DIR_BASE} ${BC_CMD_PYBB} mkdir ${BC_VAR_VCPKG_DIR_BASE}
${ENV_RUN} git clone -b release --depth 1 --branch ${VCPKG_VERSION} https://github.com/microsoft/vcpkg.git ${VCPKG_DIR} ${BC_CMD_ENVRUN} git clone -b release --depth 1 --branch ${BC_VAR_VCPKG_VERSION} https://github.com/microsoft/vcpkg.git ${BC_VAR_VCPKG_DIR}
ifneq (${OS},windows) ifneq (${BC_VAR_OS},windows)
${ENV_RUN} ${VCPKG_DIR}/bootstrap-vcpkg.sh ${BC_CMD_ENVRUN} ${BC_VAR_VCPKG_DIR}/bootstrap-vcpkg.sh
else else
${ENV_RUN} ${VCPKG_DIR}/bootstrap-vcpkg.bat ${BC_CMD_ENVRUN} ${BC_VAR_VCPKG_DIR}/bootstrap-vcpkg.bat
endif
endif endif
.PHONY: vcpkg-install .PHONY: vcpkg-install
vcpkg-install: vcpkg-install:
ifneq (${OS},windows) ifneq (${BC_VAR_OS},windows)
${VCPKG_DIR}/vcpkg install ${VCPKG_PKGS} ${BC_CMD_ENVRUN} ${BC_VAR_VCPKG_DIR}/vcpkg install ${BC_VAR_VCPKG_PKGS}
else else
${VCPKG_DIR}/vcpkg install --triplet x64-windows ${VCPKG_PKGS} ${BC_CMD_ENVRUN} ${BC_VAR_VCPKG_DIR}/vcpkg install --triplet x64-windows ${BC_VAR_VCPKG_PKGS}
endif endif
ifeq (${USE_CONAN},1) # USE_CONAN ################################################ else ifdef USE_CONAN # USE_VCPKG / USE_CONAN ####################################
.PHONY: conan-config .PHONY: setup-conan
conan-config: conan-config:
${ENV_RUN} conan profile detect -f --name ${PROJECT_NAME} ${BC_CMD_ENVRUN} conan profile new ${BC_VAR_PROJECT_NAME} --detect --force
ifeq ($(BC_VAR_OS),linux)
${BC_CMD_ENVRUN} conan profile update settings.compiler.libcxx=libstdc++11 ${BC_VAR_PROJECT_NAME}
else
${BC_CMD_ENVRUN} conan profile update settings.compiler.cppstd=20 ${BC_VAR_PROJECT_NAME}
ifeq ($(BC_VAR_OS),windows)
${BC_CMD_ENVRUN} conan profile update settings.compiler.runtime=static ${BC_VAR_PROJECT_NAME}
endif
endif
.PHONY: conan .PHONY: conan
conan: conan:
${ENV_RUN} ${PYBB} conan-install ${PROJECT_NAME} ${BC_CMD_PYBB} conan-install ${BC_VAR_PROJECT_NAME}
endif # USE_CONAN ############################################### endif # USE_CONAN ###############################################
ifeq (${OS},darwin) ifeq (${BC_VAR_OS},darwin)
.PHONY: configure-xcode .PHONY: configure-xcode
configure-xcode: configure-xcode:
${ENV_RUN} ${SETUP_BUILD} ${VCPKG_TOOLCHAIN} --build_tool=xcode --current_build=0 --build_root=${BUILD_PATH} --use_conan=${USE_CONAN} ${BC_CMD_SETUP_BUILD} ${BC_VAR_VCPKG_TOOLCHAIN} --build_tool=xcode --current_build=0 --build_root=${BC_VAR_BUILD_PATH}
endif endif
.PHONY: configure-release .PHONY: configure-release
configure-release: configure-release:
${ENV_RUN} ${SETUP_BUILD} ${VCPKG_TOOLCHAIN} --build_type=release --build_root=${BUILD_PATH} --use_conan=${USE_CONAN} ${BC_CMD_SETUP_BUILD} ${BC_VAR_VCPKG_TOOLCHAIN} --build_type=release --build_root=${BC_VAR_BUILD_PATH}
.PHONY: configure-debug .PHONY: configure-debug
configure-debug: configure-debug:
${ENV_RUN} ${SETUP_BUILD} ${VCPKG_TOOLCHAIN} --build_type=debug --build_root=${BUILD_PATH} --use_conan=${USE_CONAN} ${BC_CMD_SETUP_BUILD} ${BC_VAR_VCPKG_TOOLCHAIN} --build_type=debug --build_root=${BC_VAR_BUILD_PATH}
.PHONY: configure-asan .PHONY: configure-asan
configure-asan: configure-asan:
${ENV_RUN} ${SETUP_BUILD} ${VCPKG_TOOLCHAIN} --build_type=asan --build_root=${BUILD_PATH} --use_conan=${USE_CONAN} ${BC_CMD_SETUP_BUILD} ${BC_VAR_VCPKG_TOOLCHAIN} --build_type=asan --build_root=${BC_VAR_BUILD_PATH}

28
deps/buildcore/scripts/file_to_c.py vendored Normal file
View File

@ -0,0 +1,28 @@
#! /usr/bin/env python3
#
# Copyright 2016 - 2022 gary@drinkingtea.net
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
import argparse
import sys
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--out-cpp', help='path to output cpp file')
parser.add_argument('--out-hpp', help='path to output hpp file')
args = parser.parse_args()
return 0
if __name__ == '__main__':
try:
err = main()
sys.exit(err)
except KeyboardInterrupt:
sys.exit(1)

View File

@ -1,7 +1,7 @@
#! /usr/bin/env python3 #! /usr/bin/env python3
# #
# Copyright 2016 - 2023 gary@drinkingtea.net # Copyright 2016 - 2021 gary@drinkingtea.net
# #
# This Source Code Form is subject to the terms of the Mozilla Public # This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this # License, v. 2.0. If a copy of the MPL was not distributed with this
@ -18,18 +18,20 @@ import subprocess
import sys import sys
from typing import List, Optional from typing import List, Optional
import util
def mkdir(path: str):
if not os.path.exists(path):
os.mkdir(path)
# this exists because Windows is utterly incapable of providing a proper rm -rf def mkdir(path: str) -> int:
def rm(path: str): try:
if (os.path.exists(path) or os.path.islink(path)) and not os.path.isdir(path): util.mkdir_p(path)
os.remove(path) except Exception:
elif os.path.isdir(path): return 1
shutil.rmtree(path) return 0
def rm_multi(paths: List[str]):
for path in paths:
util.rm(path)
def ctest_all() -> int: def ctest_all() -> int:
@ -70,16 +72,13 @@ def conan() -> int:
err = 0 err = 0
try: try:
mkdir(conan_dir) mkdir(conan_dir)
except: except Exception:
return 1 return 1
if err != 0: if err != 0:
return err return err
args = ['conan', 'install', '../', '-of', '.', '--build=missing', '-pr', project_name] args = ['conan', 'install', '../', '--build=missing', '-pr', project_name]
os.chdir(conan_dir) os.chdir(conan_dir)
err = subprocess.run(args).returncode return subprocess.run(args).returncode
if err != 0:
return err
return 0
def cat(paths: List[str]) -> int: def cat(paths: List[str]) -> int:
@ -87,48 +86,70 @@ def cat(paths: List[str]) -> int:
try: try:
with open(path) as f: with open(path) as f:
data = f.read() data = f.read()
sys.stdout.write(data) print(data)
except FileNotFoundError: except FileNotFoundError:
sys.stderr.write('cat: {}: no such file or directory\n'.format(path)) sys.stderr.write(f'cat: {path}: no such file or directory\n')
return 1 return 1
sys.stdout.write('\n')
return 0 return 0
def debug(paths: List[str]) -> int:
if shutil.which('gdb') is not None:
args = ['gdb', '--args']
elif shutil.which('lldb') is not None:
args = ['lldb', '--']
else:
sys.stderr.write('debug: could not find a supported debugger\n')
return 1
args.extend(paths)
return subprocess.run(args).returncode
def get_env(var_name: str) -> int: def get_env(var_name: str) -> int:
if var_name not in os.environ: if var_name not in os.environ:
return 1 return 1
sys.stdout.write(os.environ[var_name]) print(os.environ[var_name])
return 0 return 0
def hostname() -> int: def hostname() -> int:
sys.stdout.write(platform.node()) print(platform.node())
return 0 return 0
def host_env() -> int:
os_name = platform.system().lower()
arch = util.get_arch()
print(f'{os_name}-{arch}')
return 0
def clarg(idx: int) -> Optional[str]:
return sys.argv[idx] if len(sys.argv) > idx else None
def main() -> int: def main() -> int:
err = 0 err = 0
if sys.argv[1] == 'mkdir': if sys.argv[1] == 'mkdir':
try: err = mkdir(sys.argv[2])
mkdir(sys.argv[2])
except:
err = 1
elif sys.argv[1] == 'rm': elif sys.argv[1] == 'rm':
for i in range(2, len(sys.argv)): rm_multi(sys.argv[2:])
rm(sys.argv[i])
elif sys.argv[1] == 'conan-install': elif sys.argv[1] == 'conan-install':
err = conan() err = conan()
elif sys.argv[1] == 'ctest-all': elif sys.argv[1] == 'ctest-all':
err = ctest_all() err = ctest_all()
elif sys.argv[1] == 'cmake-build': elif sys.argv[1] == 'cmake-build':
err = cmake_build(sys.argv[2], sys.argv[3] if len(sys.argv) > 3 else None) err = cmake_build(sys.argv[2], clarg(3))
elif sys.argv[1] == 'cat': elif sys.argv[1] == 'cat':
err = cat(sys.argv[2:]) err = cat(sys.argv[2:])
elif sys.argv[1] == 'debug':
err = debug(sys.argv[2:])
elif sys.argv[1] == 'getenv': elif sys.argv[1] == 'getenv':
err = get_env(sys.argv[2]) err = get_env(sys.argv[2])
elif sys.argv[1] == 'hostname': elif sys.argv[1] == 'hostname':
err = hostname() err = hostname()
elif sys.argv[1] == 'hostenv':
err = host_env()
else: else:
sys.stderr.write('Command not found\n') sys.stderr.write('Command not found\n')
err = 1 err = 1

View File

@ -1,7 +1,7 @@
#! /usr/bin/env python3 #! /usr/bin/env python3
# #
# Copyright 2016 - 2023 gary@drinkingtea.net # Copyright 2016 - 2021 gary@drinkingtea.net
# #
# This Source Code Form is subject to the terms of the Mozilla Public # This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this # License, v. 2.0. If a copy of the MPL was not distributed with this
@ -15,20 +15,35 @@ import shutil
import subprocess import subprocess
import sys import sys
from pybb import mkdir, rm import util
os_name = os.uname().sysname.lower()
def main() -> int: def main() -> int:
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('--target', help='Platform target', parser.add_argument(
default='{:s}-{:s}'.format(os_name, platform.machine())) '--target',
parser.add_argument('--build_type', help='Build type (asan,debug,release)', default='release') help='Platform target',
parser.add_argument('--build_tool', help='Build tool (default,xcode)', default='') default=f'{util.get_os()}-{util.get_arch()}')
parser.add_argument('--build_root', help='Path to the root of build directories (must be in project dir)', default='build') parser.add_argument(
parser.add_argument('--toolchain', help='Path to CMake toolchain file', default='') '--build_type',
parser.add_argument('--current_build', help='Indicates whether or not to make this the active build', default=1) help='Build type (asan,debug,release)',
parser.add_argument('--use_conan', help='Indicates whether or not should use .conanbuild/conan_toolchain.cmake', default='0') default='release')
parser.add_argument(
'--build_tool',
help='Build tool (default,xcode)',
default='')
parser.add_argument(
'--build_root',
help='Path to the root build directory (must be in project dir)',
default='build')
parser.add_argument(
'--toolchain',
help='Path to CMake toolchain file',
default='')
parser.add_argument(
'--current_build',
help='Indicates whether or not to make this the active build',
default=1)
args = parser.parse_args() args = parser.parse_args()
if args.build_type == 'asan': if args.build_type == 'asan':
@ -66,10 +81,10 @@ def main() -> int:
return 1 return 1
project_dir = os.getcwd() project_dir = os.getcwd()
build_dir = '{:s}/{:s}/{:s}'.format(project_dir, args.build_root, build_config) build_dir = f'{project_dir}/{args.build_root}/{build_config}'
rm(build_dir) util.rm(build_dir)
cmake_cmd = [ cmake_cmd = [
'cmake', '-S', project_dir, '-B', build_dir, build_tool, 'cmake', '-S', project_dir, '-B', build_dir,
'-DCMAKE_EXPORT_COMPILE_COMMANDS=ON', '-DCMAKE_EXPORT_COMPILE_COMMANDS=ON',
'-DCMAKE_TOOLCHAIN_FILE={:s}'.format(args.toolchain), '-DCMAKE_TOOLCHAIN_FILE={:s}'.format(args.toolchain),
'-DCMAKE_BUILD_TYPE={:s}'.format(build_type_arg), '-DCMAKE_BUILD_TYPE={:s}'.format(build_type_arg),
@ -77,24 +92,27 @@ def main() -> int:
'-DBUILDCORE_BUILD_CONFIG={:s}'.format(build_config), '-DBUILDCORE_BUILD_CONFIG={:s}'.format(build_config),
'-DBUILDCORE_TARGET={:s}'.format(args.target), '-DBUILDCORE_TARGET={:s}'.format(args.target),
] ]
if args.use_conan != '0': if build_tool != '':
cmake_cmd.append('-DCMAKE_TOOLCHAIN_FILE={:s}'.format('.conanbuild/conan_toolchain.cmake')) cmake_cmd.append(build_tool)
if qt_path != '': if qt_path != '':
cmake_cmd.append(qt_path) cmake_cmd.append(qt_path)
if platform.system() == 'Windows': if platform.system() == 'Windows' and platform.system() == 'AMD64':
cmake_cmd.append('-A x64') cmake_cmd.append('-A x64')
subprocess.run(cmake_cmd) cmake_err = subprocess.run(cmake_cmd).returncode
if cmake_err != 0:
return cmake_err
mkdir('dist') util.mkdir_p('dist')
if int(args.current_build) != 0: if int(args.current_build) != 0:
cb = open('.current_build', 'w') cb = open('.current_build', 'w')
cb.write(args.build_type) cb.write(args.build_type)
cb.close() cb.close()
rm('compile_commands.json') util.rm('compile_commands.json')
if platform.system() != 'Windows': if platform.system() != 'Windows':
os.symlink('{:s}/compile_commands.json'.format(build_dir), 'compile_commands.json') os.symlink(f'{build_dir}/compile_commands.json',
'compile_commands.json')
return 0 return 0

38
deps/buildcore/scripts/util.py vendored Normal file
View File

@ -0,0 +1,38 @@
#
# Copyright 2016 - 2021 gary@drinkingtea.net
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
import os
import platform
import shutil
def mkdir_p(path: str):
if not os.path.exists(path):
os.mkdir(path)
# this exists because Windows is utterly incapable of providing a proper rm -rf
def rm(path: str):
file_exists = os.path.exists(path)
is_link = os.path.islink(path)
is_dir = os.path.isdir(path)
if (file_exists or is_link) and not is_dir:
os.remove(path)
elif os.path.isdir(path):
shutil.rmtree(path)
def get_os() -> str:
return platform.system().lower()
def get_arch() -> str:
arch = platform.machine().lower()
if arch == 'amd64':
arch = 'x86_64'
return arch

BIN
iconsrc/icon-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
iconsrc/icon-256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
iconsrc/icon-32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -16,6 +16,7 @@ add_executable(
settingsdata.cpp settingsdata.cpp
settingsdialog.cpp settingsdialog.cpp
slideview.cpp slideview.cpp
sc9k.rc
) )
target_link_libraries( target_link_libraries(

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -8,8 +8,8 @@
#include <QNetworkReply> #include <QNetworkReply>
#include <QSettings> #include <QSettings>
#include <string_view>
#include "consts.hpp"
#include "settingsdata.hpp" #include "settingsdata.hpp"
#include "cameraclient.hpp" #include "cameraclient.hpp"
@ -43,6 +43,16 @@ void CameraClient::setPreset(int preset) {
} }
} }
void CameraClient::reboot() {
post("/cgi-bin/param.cgi?post_reboot");
emit pollFailed();
}
void CameraClient::setBaseUrl() {
auto const [host, port] = getCameraConnectionData();
m_baseUrl = QString("http://%1:%2").arg(host, QString::number(port));
}
void CameraClient::setBrightness(int val) { void CameraClient::setBrightness(int val) {
if (val > -1) { if (val > -1) {
get(QString("/cgi-bin/ptzctrl.cgi?post_image_value&bright&%1").arg(val)); get(QString("/cgi-bin/ptzctrl.cgi?post_image_value&bright&%1").arg(val));
@ -73,33 +83,22 @@ void CameraClient::setHue(int val) {
} }
} }
void CameraClient::reboot() {
post("/cgi-bin/param.cgi?post_reboot");
emit pollFailed();
}
void CameraClient::setBaseUrl() {
auto const [host, port] = getCameraConnectionData();
m_baseUrl = QString("http://%1:%2").arg(host, QString::number(port));
}
void CameraClient::get(QString const&urlExt) { void CameraClient::get(QString const&urlExt) {
QUrl url(QString(m_baseUrl) + urlExt); QUrl const url{QString{m_baseUrl} + urlExt};
QNetworkRequest rqst(url); QNetworkRequest rqst{url};
auto const reply = m_nam->get(rqst); auto const reply = m_nam->get(rqst);
connect(reply, &QIODevice::readyRead, reply, &QObject::deleteLater); connect(reply, &QIODevice::readyRead, reply, &QObject::deleteLater);
} }
void CameraClient::post(QString const&urlExt) { void CameraClient::post(QString const&urlExt) {
QUrl url(QString(m_baseUrl) + urlExt); QNetworkRequest const rqst{QUrl{QString{m_baseUrl} + urlExt}};
QNetworkRequest rqst(url);
auto const reply = m_nam->post(rqst, QByteArray{}); auto const reply = m_nam->post(rqst, QByteArray{});
connect(reply, &QIODevice::readyRead, reply, &QObject::deleteLater); connect(reply, &QIODevice::readyRead, reply, &QObject::deleteLater);
} }
void CameraClient::poll() { void CameraClient::poll() {
QUrl url(QString(m_baseUrl) + "/cgi-bin/param.cgi?get_device_conf"); QUrl const url{QString{m_baseUrl} + "/cgi-bin/param.cgi?get_device_conf"};
QNetworkRequest rqst(url); QNetworkRequest const rqst{url};
m_pollingNam->get(rqst); m_pollingNam->get(rqst);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -12,8 +12,6 @@
#include <QObject> #include <QObject>
#include <QTimer> #include <QTimer>
#include "consts.hpp"
class CameraClient: public QObject { class CameraClient: public QObject {
Q_OBJECT Q_OBJECT
private: private:
@ -29,6 +27,12 @@ class CameraClient: public QObject {
void setPreset(int preset); void setPreset(int preset);
void reboot();
public slots:
void setBaseUrl();
private:
void setBrightness(int val); void setBrightness(int val);
void setSaturation(int val); void setSaturation(int val);
@ -39,12 +43,6 @@ class CameraClient: public QObject {
void setHue(int val); void setHue(int val);
void reboot();
public slots:
void setBaseUrl();
private:
void get(QString const&url); void get(QString const&url);
void post(QString const&url); void post(QString const&url);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -10,4 +10,5 @@
constexpr auto MaxCameraPresets = 9; constexpr auto MaxCameraPresets = 9;
constexpr auto MaxViews = 9; constexpr auto MaxViews = 9;
constexpr auto Version = "1.0.0";

BIN
src/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -13,8 +13,12 @@
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
QSettings::setDefaultFormat(QSettings::Format::IniFormat); QSettings::setDefaultFormat(QSettings::Format::IniFormat);
#ifndef __APPLE__
QApplication::setStyle("Fusion");
#endif
QApplication a(argc, argv); QApplication a(argc, argv);
QApplication::setApplicationName(QObject::tr("Slide Controller 9000")); QApplication::setOrganizationName("DrinkingTea");
QApplication::setApplicationName("Slide Controller 9000");
MainWindow w; MainWindow w;
w.show(); w.show();
return QApplication::exec(); return QApplication::exec();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -121,18 +121,6 @@ void MainWindow::setupMenu() {
}); });
menu->addAction(cameraPresetAct); menu->addAction(cameraPresetAct);
} }
menu->addSeparator();
auto const rebootAct = new QAction(tr("&Reboot"), this);
connect(rebootAct, &QAction::triggered, &m_cameraClient, [this] {
QMessageBox confirm(this);
confirm.setText(tr("Are you sure you want to reboot the camera? This will take about 20 seconds."));
confirm.addButton(tr("&No"), QMessageBox::ButtonRole::NoRole);
confirm.addButton(tr("&Yes"), QMessageBox::ButtonRole::YesRole);
if (confirm.exec()) {
m_cameraClient.reboot();
}
});
menu->addAction(rebootAct);
} }
// help menu // help menu
{ {
@ -141,12 +129,12 @@ void MainWindow::setupMenu() {
connect(aboutAct, &QAction::triggered, &m_cameraClient, [this] { connect(aboutAct, &QAction::triggered, &m_cameraClient, [this] {
QMessageBox about(this); QMessageBox about(this);
about.setText(tr( about.setText(tr(
R"(Slide Controller 9000 - 1.0-beta3 R"(Slide Controller 9000 - %1
Build date: %1 Build date: %2
Copyright 2021 - 2023 Gary Talent (gary@drinkingtea.net) Copyright 2021 - 2025 Gary Talent (gary@drinkingtea.net)
Slide Controller 9000 is released under the MPL 2.0 Slide Controller 9000 is released under the MPL 2.0
Built on Qt library under LGPL 2.0)").arg(__DATE__)); Built on Qt library under LGPL 2.0)").arg(Version, __DATE__));
about.exec(); about.exec();
}); });
menu->addAction(aboutAct); menu->addAction(aboutAct);
@ -201,8 +189,8 @@ void MainWindow::setupViewControls(QVBoxLayout *rootLyt) {
}); });
views.emplace_back(View{ views.emplace_back(View{
.name = tr("Show"), .name = tr("Show"),
.slides = false, .slides = true,
.obsSlides = false, .obsSlides = true,
}); });
} }
setupViewControlButtons(views, viewCtlLyt); setupViewControlButtons(views, viewCtlLyt);
@ -210,7 +198,7 @@ void MainWindow::setupViewControls(QVBoxLayout *rootLyt) {
void MainWindow::openSettings() { void MainWindow::openSettings() {
SettingsDialog d(this); SettingsDialog d(this);
connect(&d, &SettingsDialog::previewPreset, &m_cameraClient, &CameraClient::setPreset); connect(&d, &SettingsDialog::previewPreset, &m_cameraClient, &CameraClient::setPresetVC);
auto const result = d.exec(); auto const result = d.exec();
if (result == QDialog::Accepted) { if (result == QDialog::Accepted) {
m_cameraClient.setBaseUrl(); m_cameraClient.setBaseUrl();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -8,8 +8,6 @@
#pragma once #pragma once
#include <cstdint>
#include <QMainWindow> #include <QMainWindow>
#include "cameraclient.hpp" #include "cameraclient.hpp"

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,11 +1,12 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
#include <QHttpPart>
#include <QJsonArray> #include <QJsonArray>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
@ -37,19 +38,19 @@ QString OpenLPClient::getNextSong() {
} }
void OpenLPClient::nextSlide() { void OpenLPClient::nextSlide() {
get("/api/controller/live/next"); post("/api/v2/controller/progress", R"({"action":"next"})");
} }
void OpenLPClient::prevSlide() { void OpenLPClient::prevSlide() {
get("/api/controller/live/previous"); post("/api/v2/controller/progress", R"({"action":"previous"})");
} }
void OpenLPClient::nextSong() { void OpenLPClient::nextSong() {
get("/api/service/next"); post("/api/v2/service/progress", R"({"action":"next"})");
} }
void OpenLPClient::prevSong() { void OpenLPClient::prevSong() {
get("/api/service/previous"); post("/api/v2/service/progress", R"({"action":"previous"})");
} }
void OpenLPClient::blankScreen() { void OpenLPClient::blankScreen() {
@ -91,6 +92,12 @@ void OpenLPClient::get(QString const&urlExt) {
m_nam->get(rqst); m_nam->get(rqst);
} }
void OpenLPClient::post(QString const&url, QString const&data) {
QNetworkRequest rqst(QUrl(m_baseUrl + url));
rqst.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
m_nam->post(rqst, data.toUtf8());
}
void OpenLPClient::requestSongList() { void OpenLPClient::requestSongList() {
QUrl url(m_baseUrl + "/api/service/list?_=1626628079579"); QUrl url(m_baseUrl + "/api/service/list?_=1626628079579");
QNetworkRequest rqst(url); QNetworkRequest rqst(url);
@ -183,12 +190,12 @@ void OpenLPClient::handleSlideListResponse(QNetworkReply *reply) {
QStringList tagList; QStringList tagList;
auto doc = QJsonDocument::fromJson(data); auto doc = QJsonDocument::fromJson(data);
auto items = doc.object()["results"].toObject()["slides"].toArray(); auto items = doc.object()["results"].toObject()["slides"].toArray();
for (auto const &item : items) { for (auto const&item : items) {
auto slide = item.toObject(); auto const slide = item.toObject();
auto text = slide["text"].toString(); auto text = slide["text"].toString();
auto tag = slide["tag"].toString(); auto tag = slide["tag"].toString();
slideList.push_back(text); slideList.push_back(std::move(text));
tagList.push_back(tag); tagList.push_back(std::move(tag));
} }
emit slideListUpdate(tagList, slideList); emit slideListUpdate(tagList, slideList);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -60,6 +60,8 @@ class OpenLPClient: public QObject {
private: private:
void get(QString const&url); void get(QString const&url);
void post(QString const&url, QString const&data);
void requestSongList(); void requestSongList();
void requestSlideList(); void requestSlideList();

BIN
src/sc9k.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

1
src/sc9k.rc Normal file
View File

@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "sc9k.ico"

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -56,7 +56,7 @@ QWidget *SettingsDialog::setupNetworkInputs(QWidget *parent) {
m_cameraHostLe->setText(c.host); m_cameraHostLe->setText(c.host);
m_cameraPortLe->setText(QString::number(c.port)); m_cameraPortLe->setText(QString::number(c.port));
m_cameraPortLe->setValidator(portValidator); m_cameraPortLe->setValidator(portValidator);
lyt->addRow(tr("C&amera Host:"), m_cameraHostLe); lyt->addRow(tr("Camera &Host:"), m_cameraHostLe);
lyt->addRow(tr("Ca&mera Port:"), m_cameraPortLe); lyt->addRow(tr("Ca&mera Port:"), m_cameraPortLe);
} }
// OpenLP settings // OpenLP settings
@ -108,7 +108,7 @@ QWidget *SettingsDialog::setupImageConfig(QWidget *parent) {
m_vidBrightness = mkSb(tr("&Brightness:")); m_vidBrightness = mkSb(tr("&Brightness:"));
m_vidSaturation = mkSb(tr("&Saturation:")); m_vidSaturation = mkSb(tr("&Saturation:"));
m_vidContrast = mkSb(tr("Con&trast:")); m_vidContrast = mkSb(tr("Con&trast:"));
m_vidSharpness = mkSb(tr("Sh&arpness:")); m_vidSharpness = mkSb(tr("Sharpn&ess:"));
m_vidHue = mkSb(tr("&Hue:")); m_vidHue = mkSb(tr("&Hue:"));
updateVidConfigPreset(0); updateVidConfigPreset(0);
} }
@ -154,7 +154,7 @@ QWidget *SettingsDialog::setupViewConfig(QWidget *parent) {
} }
{ // add/removes buttons { // add/removes buttons
auto const btnsLyt = new QHBoxLayout(btnsRoot); auto const btnsLyt = new QHBoxLayout(btnsRoot);
auto const addBtn = new QPushButton("&Add", btnsRoot); auto const addBtn = new QPushButton("A&dd", btnsRoot);
auto const rmBtn = new QPushButton("&Remove", btnsRoot); auto const rmBtn = new QPushButton("&Remove", btnsRoot);
addBtn->setFixedWidth(70); addBtn->setFixedWidth(70);
rmBtn->setFixedWidth(70); rmBtn->setFixedWidth(70);
@ -192,22 +192,25 @@ QWidget *SettingsDialog::setupButtons(QWidget *parent) {
auto const lyt = new QHBoxLayout(root); auto const lyt = new QHBoxLayout(root);
m_errLbl = new QLabel(root); m_errLbl = new QLabel(root);
auto const okBtn = new QPushButton(tr("&OK"), root); auto const okBtn = new QPushButton(tr("&OK"), root);
auto const applyBtn = new QPushButton(tr("&Apply"), root);
auto const cancelBtn = new QPushButton(tr("&Cancel"), root); auto const cancelBtn = new QPushButton(tr("&Cancel"), root);
lyt->addWidget(m_errLbl); lyt->addWidget(m_errLbl);
lyt->addSpacerItem(new QSpacerItem(1000, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); lyt->addSpacerItem(new QSpacerItem(1000, 0, QSizePolicy::Expanding, QSizePolicy::Ignored));
lyt->addWidget(okBtn); lyt->addWidget(okBtn);
lyt->addWidget(applyBtn);
lyt->addWidget(cancelBtn); lyt->addWidget(cancelBtn);
connect(okBtn, &QPushButton::clicked, this, &SettingsDialog::handleOK); connect(okBtn, &QPushButton::clicked, this, &SettingsDialog::handleOK);
connect(applyBtn, &QPushButton::clicked, this, &SettingsDialog::handleApply);
connect(cancelBtn, &QPushButton::clicked, this, &SettingsDialog::reject); connect(cancelBtn, &QPushButton::clicked, this, &SettingsDialog::reject);
return root; return root;
} }
void SettingsDialog::handleOK() { int SettingsDialog::handleApply() {
QSettings settings; QSettings settings;
QVector<View> views; QVector<View> views;
auto const viewsErr = collectViews(views); auto const viewsErr = collectViews(views);
if (viewsErr) { if (viewsErr) {
return; return -1;
} }
setViews(settings, views); setViews(settings, views);
setCameraConnectionData(settings, { setCameraConnectionData(settings, {
@ -224,7 +227,13 @@ void SettingsDialog::handleOK() {
}); });
collectVideoConfig(); collectVideoConfig();
setVideoConfig(settings, m_videoConfig); setVideoConfig(settings, m_videoConfig);
return 0;
}
void SettingsDialog::handleOK() {
if (handleApply() == 0) {
accept(); accept();
}
} }
void SettingsDialog::setupViewRow(int row, View const&view) { void SettingsDialog::setupViewRow(int row, View const&view) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -38,6 +38,8 @@ class SettingsDialog: public QDialog {
QWidget *setupViewConfig(QWidget *parent); QWidget *setupViewConfig(QWidget *parent);
QWidget *setupImageConfig(QWidget *parent); QWidget *setupImageConfig(QWidget *parent);
QWidget *setupButtons(QWidget *parent); QWidget *setupButtons(QWidget *parent);
[[nodiscard]]
int handleApply();
void handleOK(); void handleOK();
void setupViewRow(int row, View const&view = {}); void setupViewRow(int row, View const&view = {});
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -43,7 +43,7 @@ QString SlideView::getNextSong() const {
} }
void SlideView::pollUpdate(QString const&songName, int slide) { void SlideView::pollUpdate(QString const&songName, int slide) {
auto songItems = m_songSelector->findItems(songName, Qt::MatchFixedString); auto const songItems = m_songSelector->findItems(songName, Qt::MatchFixedString);
if (songItems.empty()) { if (songItems.empty()) {
return; return;
} }
@ -68,7 +68,10 @@ void SlideView::changeSong(int song) {
} }
} }
void SlideView::slideListUpdate(QStringList const&tagList, QStringList const&slideList) { void SlideView::slideListUpdate(QStringList tagList, QStringList const&slideList) {
for (auto &tag : tagList) {
tag = tag.split("").join("\n");
}
m_currentSlide = 0; m_currentSlide = 0;
m_slideTable->setRowCount(static_cast<int>(slideList.size())); m_slideTable->setRowCount(static_cast<int>(slideList.size()));
for (int i = 0; i < slideList.size(); ++i) { for (int i = 0; i < slideList.size(); ++i) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2023 gary@drinkingtea.net * Copyright 2021 - 2024 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -28,7 +28,7 @@ class SlideView: public QWidget {
void songListUpdate(QStringList const&songList); void songListUpdate(QStringList const&songList);
void slideListUpdate(QStringList const&tagList, QStringList const&songList); void slideListUpdate(QStringList tagList, QStringList const&songList);
void reset(); void reset();