Compare commits

..

No commits in common. "master" and "release-1.0.0-beta3" have entirely different histories.

35 changed files with 240 additions and 369 deletions

1
.gitignore vendored
View File

@ -2,7 +2,6 @@
.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 Normal file
View File

@ -0,0 +1,7 @@
<?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 Normal file
View File

@ -0,0 +1,6 @@
<?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 - 2024 gary@drinkingtea.net Copyright 2021 - 2023 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,10 +14,6 @@ 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 ($(BC_VAR_OS),darwin) ifeq ($(OS),darwin)
PROJECT_EXECUTABLE=./build/${BC_VAR_CURRENT_BUILD}/bin/${PROJECT_NAME}.app/Contents/MacOS/SlideController PROJECT_EXECUTABLE=./dist/${CURRENT_BUILD}/${PROJECT_NAME}.app/Contents/MacOS/SlideController
else else
PROJECT_EXECUTABLE=./build/${BC_VAR_CURRENT_BUILD}/bin/${PROJECT_NAME} PROJECT_EXECUTABLE=./dist/${CURRENT_BUILD}/bin/SlideController
endif endif
.PHONY: run .PHONY: run
run: build run: install
${ENV_RUN} ${PROJECT_EXECUTABLE} ${ENV_RUN} ${PROJECT_EXECUTABLE}
.PHONY: debug .PHONY: debug
debug: build debug: install
${DEBUGGER} ${PROJECT_EXECUTABLE} ${DEBUGGER} ${PROJECT_EXECUTABLE}

View File

@ -14,6 +14,7 @@ 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)

194
deps/buildcore/base.mk vendored
View File

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

View File

@ -1,28 +0,0 @@
#! /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 - 2021 gary@drinkingtea.net # Copyright 2016 - 2023 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,20 +18,18 @@ 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)
def mkdir(path: str) -> int: # this exists because Windows is utterly incapable of providing a proper rm -rf
try: def rm(path: str):
util.mkdir_p(path) if (os.path.exists(path) or os.path.islink(path)) and not os.path.isdir(path):
except Exception: os.remove(path)
return 1 elif os.path.isdir(path):
return 0 shutil.rmtree(path)
def rm_multi(paths: List[str]):
for path in paths:
util.rm(path)
def ctest_all() -> int: def ctest_all() -> int:
@ -72,13 +70,16 @@ def conan() -> int:
err = 0 err = 0
try: try:
mkdir(conan_dir) mkdir(conan_dir)
except Exception: except:
return 1 return 1
if err != 0: if err != 0:
return err return err
args = ['conan', 'install', '../', '--build=missing', '-pr', project_name] args = ['conan', 'install', '../', '-of', '.', '--build=missing', '-pr', project_name]
os.chdir(conan_dir) os.chdir(conan_dir)
return subprocess.run(args).returncode err = subprocess.run(args).returncode
if err != 0:
return err
return 0
def cat(paths: List[str]) -> int: def cat(paths: List[str]) -> int:
@ -86,70 +87,48 @@ def cat(paths: List[str]) -> int:
try: try:
with open(path) as f: with open(path) as f:
data = f.read() data = f.read()
print(data) sys.stdout.write(data)
except FileNotFoundError: except FileNotFoundError:
sys.stderr.write(f'cat: {path}: no such file or directory\n') sys.stderr.write('cat: {}: no such file or directory\n'.format(path))
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
print(os.environ[var_name]) sys.stdout.write(os.environ[var_name])
return 0 return 0
def hostname() -> int: def hostname() -> int:
print(platform.node()) sys.stdout.write(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':
err = mkdir(sys.argv[2]) try:
mkdir(sys.argv[2])
except:
err = 1
elif sys.argv[1] == 'rm': elif sys.argv[1] == 'rm':
rm_multi(sys.argv[2:]) for i in range(2, len(sys.argv)):
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], clarg(3)) err = cmake_build(sys.argv[2], sys.argv[3] if len(sys.argv) > 3 else None)
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 - 2021 gary@drinkingtea.net # Copyright 2016 - 2023 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,35 +15,20 @@ import shutil
import subprocess import subprocess
import sys import sys
import util from pybb import mkdir, rm
os_name = os.uname().sysname.lower()
def main() -> int: def main() -> int:
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument( parser.add_argument('--target', help='Platform target',
'--target', default='{:s}-{:s}'.format(os_name, platform.machine()))
help='Platform target', parser.add_argument('--build_type', help='Build type (asan,debug,release)', default='release')
default=f'{util.get_os()}-{util.get_arch()}') parser.add_argument('--build_tool', help='Build tool (default,xcode)', default='')
parser.add_argument( parser.add_argument('--build_root', help='Path to the root of build directories (must be in project dir)', default='build')
'--build_type', parser.add_argument('--toolchain', help='Path to CMake toolchain file', default='')
help='Build type (asan,debug,release)', parser.add_argument('--current_build', help='Indicates whether or not to make this the active build', default=1)
default='release') parser.add_argument('--use_conan', help='Indicates whether or not should use .conanbuild/conan_toolchain.cmake', default='0')
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':
@ -81,10 +66,10 @@ def main() -> int:
return 1 return 1
project_dir = os.getcwd() project_dir = os.getcwd()
build_dir = f'{project_dir}/{args.build_root}/{build_config}' build_dir = '{:s}/{:s}/{:s}'.format(project_dir, args.build_root, build_config)
util.rm(build_dir) rm(build_dir)
cmake_cmd = [ cmake_cmd = [
'cmake', '-S', project_dir, '-B', build_dir, 'cmake', '-S', project_dir, '-B', build_dir, build_tool,
'-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),
@ -92,27 +77,24 @@ 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 build_tool != '': if args.use_conan != '0':
cmake_cmd.append(build_tool) cmake_cmd.append('-DCMAKE_TOOLCHAIN_FILE={:s}'.format('.conanbuild/conan_toolchain.cmake'))
if qt_path != '': if qt_path != '':
cmake_cmd.append(qt_path) cmake_cmd.append(qt_path)
if platform.system() == 'Windows' and platform.system() == 'AMD64': if platform.system() == 'Windows':
cmake_cmd.append('-A x64') cmake_cmd.append('-A x64')
cmake_err = subprocess.run(cmake_cmd).returncode subprocess.run(cmake_cmd)
if cmake_err != 0:
return cmake_err
util.mkdir_p('dist') mkdir('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()
util.rm('compile_commands.json') rm('compile_commands.json')
if platform.system() != 'Windows': if platform.system() != 'Windows':
os.symlink(f'{build_dir}/compile_commands.json', os.symlink('{:s}/compile_commands.json'.format(build_dir), 'compile_commands.json')
'compile_commands.json')
return 0 return 0

View File

@ -1,38 +0,0 @@
#
# 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -16,7 +16,6 @@ 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 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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,16 +43,6 @@ 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));
@ -83,22 +73,33 @@ 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 const url{QString{m_baseUrl} + urlExt}; QUrl 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) {
QNetworkRequest const rqst{QUrl{QString{m_baseUrl} + urlExt}}; QUrl url(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 const url{QString{m_baseUrl} + "/cgi-bin/param.cgi?get_device_conf"}; QUrl url(QString(m_baseUrl) + "/cgi-bin/param.cgi?get_device_conf");
QNetworkRequest const rqst{url}; QNetworkRequest rqst(url);
m_pollingNam->get(rqst); m_pollingNam->get(rqst);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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,6 +12,8 @@
#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:
@ -27,12 +29,6 @@ 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);
@ -43,6 +39,12 @@ 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 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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,5 +10,4 @@
constexpr auto MaxCameraPresets = 9; constexpr auto MaxCameraPresets = 9;
constexpr auto MaxViews = 9; constexpr auto MaxViews = 9;
constexpr auto Version = "1.0.0";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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,12 +13,8 @@
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::setOrganizationName("DrinkingTea"); QApplication::setApplicationName(QObject::tr("Slide Controller 9000"));
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 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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,6 +121,18 @@ 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
{ {
@ -129,12 +141,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 R"(Slide Controller 9000 - 1.0-beta3
Build date: %2 Build date: %1
Copyright 2021 - 2025 Gary Talent (gary@drinkingtea.net) Copyright 2021 - 2023 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(Version, __DATE__)); Built on Qt library under LGPL 2.0)").arg(__DATE__));
about.exec(); about.exec();
}); });
menu->addAction(aboutAct); menu->addAction(aboutAct);
@ -189,8 +201,8 @@ void MainWindow::setupViewControls(QVBoxLayout *rootLyt) {
}); });
views.emplace_back(View{ views.emplace_back(View{
.name = tr("Show"), .name = tr("Show"),
.slides = true, .slides = false,
.obsSlides = true, .obsSlides = false,
}); });
} }
setupViewControlButtons(views, viewCtlLyt); setupViewControlButtons(views, viewCtlLyt);
@ -198,7 +210,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::setPresetVC); connect(&d, &SettingsDialog::previewPreset, &m_cameraClient, &CameraClient::setPreset);
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 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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,6 +8,8 @@
#pragma once #pragma once
#include <cstdint>
#include <QMainWindow> #include <QMainWindow>
#include "cameraclient.hpp" #include "cameraclient.hpp"

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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,12 +1,11 @@
/* /*
* Copyright 2021 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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>
@ -38,19 +37,19 @@ QString OpenLPClient::getNextSong() {
} }
void OpenLPClient::nextSlide() { void OpenLPClient::nextSlide() {
post("/api/v2/controller/progress", R"({"action":"next"})"); get("/api/controller/live/next");
} }
void OpenLPClient::prevSlide() { void OpenLPClient::prevSlide() {
post("/api/v2/controller/progress", R"({"action":"previous"})"); get("/api/controller/live/previous");
} }
void OpenLPClient::nextSong() { void OpenLPClient::nextSong() {
post("/api/v2/service/progress", R"({"action":"next"})"); get("/api/service/next");
} }
void OpenLPClient::prevSong() { void OpenLPClient::prevSong() {
post("/api/v2/service/progress", R"({"action":"previous"})"); get("/api/service/previous");
} }
void OpenLPClient::blankScreen() { void OpenLPClient::blankScreen() {
@ -92,12 +91,6 @@ 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);
@ -191,11 +184,11 @@ void OpenLPClient::handleSlideListResponse(QNetworkReply *reply) {
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 const slide = item.toObject(); auto 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(std::move(text)); slideList.push_back(text);
tagList.push_back(std::move(tag)); tagList.push_back(tag);
} }
emit slideListUpdate(tagList, slideList); emit slideListUpdate(tagList, slideList);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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,8 +60,6 @@ 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();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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("Camera &Host:"), m_cameraHostLe); lyt->addRow(tr("C&amera 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("Sharpn&ess:")); m_vidSharpness = mkSb(tr("Sh&arpness:"));
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("A&dd", btnsRoot); auto const addBtn = new QPushButton("&Add", 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,25 +192,22 @@ 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;
} }
int SettingsDialog::handleApply() { void SettingsDialog::handleOK() {
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 -1; return;
} }
setViews(settings, views); setViews(settings, views);
setCameraConnectionData(settings, { setCameraConnectionData(settings, {
@ -227,14 +224,8 @@ int SettingsDialog::handleApply() {
}); });
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) {
// name // name

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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,8 +38,6 @@ 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 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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 const songItems = m_songSelector->findItems(songName, Qt::MatchFixedString); auto songItems = m_songSelector->findItems(songName, Qt::MatchFixedString);
if (songItems.empty()) { if (songItems.empty()) {
return; return;
} }
@ -68,10 +68,7 @@ void SlideView::changeSong(int song) {
} }
} }
void SlideView::slideListUpdate(QStringList tagList, QStringList const&slideList) { void SlideView::slideListUpdate(QStringList const&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 - 2024 gary@drinkingtea.net * Copyright 2021 - 2023 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 tagList, QStringList const&songList); void slideListUpdate(QStringList const&tagList, QStringList const&songList);
void reset(); void reset();