4
0
mirror of https://github.com/QuasarApp/QuasarAppLib.git synced 2025-05-04 05:29:44 +00:00

Compare commits

...

75 Commits
v1.5.2 ... main

Author SHA1 Message Date
b916d4feef
Merge pull request from QuasarApp/sys_install
Sys install
2025-04-27 12:26:00 +02:00
d516530f5c
Apply suggestions from code review
Signed-off-by: Andrei Yankovich <EndrIIMail@gmail.com>
2025-04-27 13:25:16 +03:00
33b3112d58 update version 2025-04-27 12:18:01 +02:00
76c3d7a8b9 Merge branch 'main' into sys_install 2025-04-27 12:14:39 +02:00
f51b78c8d9 add install target for cmake build scripts 2025-04-27 12:13:30 +02:00
6e494a13f1
Merge pull request from QuasarApp/production_game
added constexper crc 32 hash fucntion
2025-03-16 19:30:53 +01:00
703fff317c added constexper crc 32 hash fucntion 2025-03-15 00:21:51 +01:00
4eb85b8cbb
Merge pull request from QuasarApp/loggerPath
added getter of log file path
2025-02-19 13:55:10 +01:00
0ce9053539 added getter of log file path 2025-02-19 13:53:52 +01:00
5d020006bb
Merge pull request from QuasarApp/production_game
the "Productions" game fixes
2025-02-19 13:34:40 +01:00
7e84073393 ixes of the loger and settings classes 2025-02-18 14:12:54 +01:00
9c6c6d257c uppdate docs 2025-02-17 14:13:47 +01:00
1e61c3578b
Merge pull request from QuasarApp/fix_log_initialisation
fix log initialisation
2025-02-07 15:44:40 +01:00
ebdd860531 fix logs 2025-02-07 15:41:00 +01:00
37a1f76ba1
Merge pull request from QuasarApp/fix_log_handler
Fix log handler
2025-02-07 12:14:38 +01:00
961e6608d9 update docs 2025-02-07 12:13:03 +01:00
86c9036f13 fix standart path location 2025-02-07 12:11:26 +01:00
6b8bb9f2cd update docs 2025-02-07 12:00:00 +01:00
945da5be9d fix logger 2025-02-07 11:56:30 +01:00
8b710eaa67
Merge pull request from QuasarApp/update_cmake
update cmake
2025-01-22 19:20:20 +01:00
580a4ce1bd update cmake 2025-01-22 19:16:48 +01:00
5302846051
Merge pull request from QuasarApp/update_copyright
update copyright to 2025
2024-12-30 22:40:57 +01:00
7f24b57b41 update copyright to 2025 2024-12-30 22:39:49 +01:00
88414ce06f
Merge pull request from Snegovoy98/fix_macos_apppath
Fix for MacOS application path params
2024-08-02 15:34:10 +03:00
Alex
d61ef581ce There was added check os type for header include 2024-08-02 15:06:04 +03:00
Alex
5218f2094c There were change logic for get applicationPath 2024-08-02 12:37:38 +03:00
Alex
06b71bd9aa There was fixed merge conflict 2024-08-01 12:33:03 +03:00
Alex
f06e675631 There was fixed macos apppath fro params 2024-08-01 07:05:11 +03:00
65a467054a
Merge pull request from QuasarApp/qt_logger
update readme
2024-06-24 13:35:34 +02:00
ccd47b8be3 update readme 2024-06-24 13:35:09 +02:00
e59bc728b3
Merge pull request from QuasarApp/qt_logger
remove deprecated macrosses
2024-06-24 13:34:28 +02:00
97260fea2d remove deprecated macrosses 2024-06-24 13:33:53 +02:00
a21c8d38ed
Merge pull request from QuasarApp/qt_logger
move to qt logger system
2024-06-24 13:30:20 +02:00
f82a69db36 update docs 2024-06-24 13:27:03 +02:00
ee0f7fb2ee move to qt logger system 2024-06-24 13:23:40 +02:00
ad939ab45e update cmake 2024-03-19 18:12:21 +01:00
f3fabf4f64 update qasecretservice handler functions 2024-02-05 15:40:00 +01:00
78ceff0f09 fix ios build 2024-01-21 18:33:48 +01:00
53c73c2913 update getSecret methods 2024-01-21 17:12:36 +01:00
c17c20e51f update get functionsx 2024-01-21 17:03:46 +01:00
08c27ec560 added qasecret support 2024-01-21 16:44:23 +01:00
10d0361ae1
Merge pull request from QuasarApp/platformutils
added support snap platform
2024-01-21 11:03:51 +01:00
b7b0f330c6 try to fix ios build 2024-01-21 10:58:07 +01:00
ad27b38b10 fix build on android and ios 2024-01-21 10:47:50 +01:00
00b80d9454 added support snap platform 2024-01-21 10:42:50 +01:00
0551a56944 update cmake 2024-01-20 20:34:06 +01:00
0e8a402e9a
Merge pull request from QuasarApp/new_year2024
update copyright
2023-12-31 10:08:36 +01:00
8b5fce889f update cmake 2023-12-31 09:35:19 +01:00
37fe8a069b update copyright 2023-12-31 09:23:23 +01:00
5ab1c66525 update cmake 2023-11-05 17:33:36 +01:00
3b797f9a78 added new option for desable logs 2023-11-05 11:24:09 +01:00
334e209ff4 fix qt 6.6 warnings 2023-10-28 21:31:17 +02:00
4d445ef7fc
Merge pull request from QuasarApp/customtranslations
added tr method for custom translations
2023-10-01 12:49:02 +03:00
90a4284c56 added tr method for custom translations 2023-10-01 11:27:35 +02:00
a23bbe9268 increment version 2023-08-16 13:35:53 +02:00
d4a3e7dff2 fix qaservice (autoInstance method) 2023-08-16 13:34:40 +02:00
53a67709ff update cmake 2023-07-21 20:01:03 +02:00
fb8c76feb6 update cmake 2023-06-12 12:47:07 +02:00
62c9d4e7c2 update cmake 2023-06-09 17:49:12 +02:00
c427dd9349 fix load sub languages 2023-04-15 21:35:09 +02:00
21b07bfdb0 update cmake 2023-04-15 14:41:34 +02:00
b3d577165d update cmake 2023-04-15 13:54:10 +02:00
d2c1e7819c fix xcode cccache 2023-04-15 13:48:14 +02:00
cb9dc9d3d2 update cmake 2023-04-15 13:23:28 +02:00
11588289c0 update cmake 2023-04-15 12:25:24 +02:00
f3519b341a try fix android behavior 2023-04-07 15:01:10 +02:00
c462f44e6b try fix services on android 2023-04-07 13:52:17 +02:00
d7b9ccef40 try create universaly service class 2023-04-06 21:44:47 +02:00
c29c9edc52 fix work service class on the android and windows apps for the shared applications 2023-04-06 14:48:23 +02:00
7737b28258 fix work with languages 2023-04-01 12:59:51 +02:00
7b4c10be77 fix random generator 2023-02-24 20:53:06 +01:00
9fcdeb42dd update cmake 2022-12-31 11:25:02 +03:00
38e609e128 fix documentation style 2022-12-28 00:50:03 +03:00
07943dfc37 update copyright 2022-12-28 00:45:09 +03:00
edd7176e56 remove ruddiments 2022-12-28 00:43:01 +03:00
40 changed files with 827 additions and 859 deletions

2
CMake

@ -1 +1 @@
Subproject commit fe0a37271a65cb136f7c1ae049636476cb772deb
Subproject commit 76d88f13235574890fa72e9a811c6ff524d6abaa

@ -1,5 +1,5 @@
#
# Copyright (C) 2018-2022 QuasarApp.
# Copyright (C) 2018-2025 QuasarApp.
# Distributed under the lgplv3 software license, see the accompanying
# Everyone is permitted to copy and distribute verbatim copies
# of this license document, but changing it is not allowed.
@ -38,16 +38,11 @@ endif()
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
option(QA_ASSERT_ON_WARN "Enable for add assert to every warning message" OFF)
option(QA_ASSERT_ON_ERROR "Enable for add assert to every error message" OFF)
option(QA_ALLOW_NOT_SUPPORTED_OPTIONS "Enable for allow any command line options" ON)
option(QA_DISABLE_LOG "Disabled all logs (force sets verbose to 0)" OFF)
if (QA_ASSERT_ON_WARN)
add_definitions(-DQA_ASSERT_ON_WARN)
endif()
if (QA_ASSERT_ON_ERROR)
add_definitions(-DQA_ASSERT_ON_ERROR)
if (QA_DISABLE_LOG)
add_definitions(-DQA_DISABLE_LOG)
endif()
if (QA_ALLOW_NOT_SUPPORTED_OPTIONS)
@ -62,9 +57,14 @@ add_library(${PROJECT_NAME} ${SOURCE_CPP})
target_link_libraries(${PROJECT_NAME} PUBLIC Qt${QT_VERSION_MAJOR}::Core)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
setVersion(1 5 2)
setVersion(1 6 0)
initAll()
make_directory("${CMAKE_CURRENT_SOURCE_DIR}/Distro")
addDoc(${PROJECT_NAME}Docs ${CMAKE_CURRENT_SOURCE_DIR}/doxygen.conf)
install(TARGETS ${PROJECT_NAME}
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

@ -1,22 +0,0 @@
#
# Copyright (C) 2018-2022 QuasarApp.
# Distributed under the lgplv3 software license, see the accompanying
# Everyone is permitted to copy and distribute verbatim copies
# of this license document, but changing it is not allowed.
#
!isEmpty(CCACHE_INCLUDE):error("ccache.pri already included")
CCACHE_INCLUDE = 1
contains(QMAKE_HOST.os, Linux):{
BIN = $$system(which ccache)
!isEmpty(BIN) {
message(ccache detected in $$BIN)
QMAKE_CXX='$$BIN $$QMAKE_CXX'
}
}

@ -1,33 +0,0 @@
#
# Copyright (C) 2018-2019 QuasarApp.
# Distributed under the lgplv3 software license, see the accompanying
# Everyone is permitted to copy and distribute verbatim copies
# of this license document, but changing it is not allowed.
#
QT_DIR = $$dirname(QMAKE_QMAKE)
LUPDATE = $$QT_DIR/lupdate
LRELEASE = $$QT_DIR/lrelease
win32 {
LUPDATE = $${LUPDATE}.exe
LRELEASE = $${LRELEASE}.exe
}
PRO_FILES = $$files(*.pro, true)
for(PRO, PRO_FILES) {
commands += "$$LUPDATE $$PRO"
}
TS_FILES = $$files(*.ts, true)
for(TS, TS_FILES) {
commands += "$$LRELEASE $$TS"
}
for(command, commands) {
system($$command)|error("Failed to run: $$command")
}

@ -1,442 +0,0 @@
#!/bin/bash
#################
# Launcher init #
#################
START=$(date +%s.%N)
# On Fedora $SNAP is under /var and there is some magic to map it to /snap.
# # We need to handle that case and reset $SNAP
SNAP=`echo $SNAP | sed -e "s|/var/lib/snapd||g"`
needs_update=true
. $SNAP_USER_DATA/.last_revision 2>/dev/null || true
if [ "$SNAP_DESKTOP_LAST_REVISION" = "$SNAP_REVISION" ]; then
needs_update=false
fi
# Set $REALHOME to the users real home directory
REALHOME=`getent passwd $UID | cut -d ':' -f 6`
# If the user has modified their user-dirs settings, force an update
if [[ -f $HOME/.config/user-dirs.dirs.md5sum && -f $HOME/.config/user-dirs.locale.md5sum ]]; then
if [[ "$(md5sum < $REALHOME/.config/user-dirs.dirs)" != "$(cat $HOME/.config/user-dirs.dirs.md5sum)" ||
"$(md5sum < $REALHOME/.config/user-dirs.locale)" != "$(cat $HOME/.config/user-dirs.locale.md5sum)" ]]; then
needs_update=true
fi
fi
if [ "$SNAP_ARCH" == "amd64" ]; then
ARCH="x86_64-linux-gnu"
elif [ "$SNAP_ARCH" == "armhf" ]; then
ARCH="arm-linux-gnueabihf"
elif [ "$SNAP_ARCH" == "arm64" ]; then
ARCH="aarch64-linux-gnu"
else
ARCH="$SNAP_ARCH-linux-gnu"
fi
export SNAP_LAUNCHER_ARCH_TRIPLET=$ARCH
# Don't LD_PRELOAD bindtextdomain for classic snaps
if ! grep -qs "^\s*confinement:\s*classic\s*" $SNAP/meta/snap.yaml; then
if [ -f $SNAP/lib/bindtextdomain.so ]; then
export LD_PRELOAD=$LD_PRELOAD:$SNAP/lib/bindtextdomain.so
fi
fi
###############################################
# Launcher common exports for any desktop app #
###############################################
function prepend_dir() {
local var="$1"
local dir="$2"
if [ -d "$dir" ]; then
eval "export $var=\"\$dir\${$var:+:\$$var}\""
fi
}
function append_dir() {
local var="$1"
local dir="$2"
if [ -d "$dir" ]; then
eval "export $var=\"\${$var:+\$$var:}\$dir\""
fi
}
function can_open_file() {
return `head -c0 "$1" &> /dev/null`;
}
WITH_RUNTIME=no
if [ -z "$RUNTIME" ]; then
RUNTIME=$SNAP
else
# add general paths not added by snapcraft due to runtime snap
append_dir LD_LIBRARY_PATH $RUNTIME/lib/$ARCH
append_dir LD_LIBRARY_PATH $RUNTIME/usr/lib/$ARCH
append_dir PATH $RUNTIME/usr/bin
WITH_RUNTIME=yes
fi
# XKB config
export XKB_CONFIG_ROOT=$RUNTIME/usr/share/X11/xkb
# Give XOpenIM a chance to locate locale data.
# This is required for text input to work in SDL2 games.
export XLOCALEDIR=$RUNTIME/usr/share/X11/locale
# Set XCursors path
export XCURSOR_PATH=$RUNTIME/usr/share/icons
# Mesa Libs for OpenGL support
append_dir LD_LIBRARY_PATH $RUNTIME/usr/lib/$ARCH/mesa
append_dir LD_LIBRARY_PATH $RUNTIME/usr/lib/$ARCH/mesa-egl
# Tell libGL where to find the drivers
export LIBGL_DRIVERS_PATH=$RUNTIME/usr/lib/$ARCH/dri
append_dir LD_LIBRARY_PATH $LIBGL_DRIVERS_PATH
# Workaround in snapd for proprietary nVidia drivers mounts the drivers in
# /var/lib/snapd/lib/gl that needs to be in LD_LIBRARY_PATH
# Without that OpenGL using apps do not work with the nVidia drivers.
# Ref.: https://bugs.launchpad.net/snappy/+bug/1588192
append_dir LD_LIBRARY_PATH /var/lib/snapd/lib/gl
# Unity7 export (workaround for https://launchpad.net/bugs/1638405)
append_dir LD_LIBRARY_PATH $RUNTIME/usr/lib/$ARCH/libunity
# Pulseaudio export
append_dir LD_LIBRARY_PATH $RUNTIME/usr/lib/$ARCH/pulseaudio
# EGL vendor files on glvnd enabled systems
[ -d /var/lib/snapd/lib/glvnd/egl_vendor.d ] && \
append_dir __EGL_VENDOR_LIBRARY_DIRS /var/lib/snapd/lib/glvnd/egl_vendor.d
# Tell GStreamer where to find its plugins
export GST_PLUGIN_PATH=$SNAP/usr/lib/$ARCH/gstreamer-1.0
export GST_PLUGIN_SYSTEM_PATH=$RUNTIME/usr/lib/$ARCH/gstreamer-1.0
# gst plugin scanner doesn't install in the correct path: https://github.com/ubuntu/snapcraft-desktop-helpers/issues/43
export GST_PLUGIN_SCANNER=$RUNTIME/usr/lib/$ARCH/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner
# XDG Config
[ "$WITH_RUNTIME" = yes ] && prepend_dir XDG_CONFIG_DIRS $RUNTIME/etc/xdg
prepend_dir XDG_CONFIG_DIRS $SNAP/etc/xdg
# Define snaps' own data dir
[ "$WITH_RUNTIME" = yes ] && prepend_dir XDG_DATA_DIRS $RUNTIME/usr/share
prepend_dir XDG_DATA_DIRS $SNAP/usr/share
prepend_dir XDG_DATA_DIRS $SNAP/share
prepend_dir XDG_DATA_DIRS $SNAP/data-dir
prepend_dir XDG_DATA_DIRS $SNAP_USER_DATA
# Set XDG_DATA_HOME to local path
export XDG_DATA_HOME=$SNAP_USER_DATA/.local/share
mkdir -p $XDG_DATA_HOME
# Workaround for GLib < 2.53.2 not searching for schemas in $XDG_DATA_HOME:
# https://bugzilla.gnome.org/show_bug.cgi?id=741335
prepend_dir XDG_DATA_DIRS $XDG_DATA_HOME
# Set cache folder to local path
export XDG_CACHE_HOME=$SNAP_USER_COMMON/.cache
if [[ -d $SNAP_USER_DATA/.cache && ! -e $XDG_CACHE_HOME ]]; then
# the .cache directory used to be stored under $SNAP_USER_DATA, migrate it
mv $SNAP_USER_DATA/.cache $SNAP_USER_COMMON/
fi
mkdir -p $XDG_CACHE_HOME
# Set config folder to local path
export XDG_CONFIG_HOME=$SNAP_USER_DATA/.config
mkdir -p $XDG_CONFIG_HOME
# Create $XDG_RUNTIME_DIR if not exists (to be removed when LP: #1656340 is fixed)
[ -n "$XDG_RUNTIME_DIR" ] && mkdir -p $XDG_RUNTIME_DIR -m 700
# Ensure the app finds locale definitions (requires locales-all to be installed)
append_dir LOCPATH $RUNTIME/usr/lib/locale
# If any, keep track of where XDG dirs were so we can potentially migrate the content later
test -f ${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs && . ${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs
for d in DOCUMENTS DESKTOP DOWNLOAD MUSIC PICTURES VIDEOS PUBLICSHARE TEMPLATES; do
eval $(echo "OLD_XDG_${d}_DIR")=`eval "$(echo "echo \\$XDG_${d}_DIR")"`
done
# Setup user-dirs.* or run xdg-user-dirs-update if needed
needs_xdg_update=false
needs_xdg_links=false
if can_open_file "$REALHOME/.config/user-dirs.dirs" && can_open_file "$REALHOME/.config/user-dirs.locale"; then
mkdir -p $HOME/.config -m 700
sed /^#/!s#\$HOME#${REALHOME}#g $REALHOME/.config/user-dirs.dirs > $HOME/.config/user-dirs.dirs
cp -a $REALHOME/.config/user-dirs.locale $HOME/.config/
for f in user-dirs.dirs user-dirs.locale; do
md5sum < $REALHOME/.config/$f > $HOME/.config/$f.md5sum
done
else
needs_xdg_update=true
needs_xdg_links=true
fi
# Check if we can actually read the contents of each xdg dir
test -f ${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs && . ${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs
XDG_SPECIAL_DIRS=($XDG_DOCUMENTS_DIR $XDG_DESKTOP_DIR $XDG_DOWNLOAD_DIR $XDG_MUSIC_DIR $XDG_PICTURES_DIR $XDG_VIDEOS_DIR $XDG_PUBLIC_DIR $XDG_TEMPLATES_DIR)
for d in ${XDG_SPECIAL_DIRS[@]}; do
if ! can_open_file $d; then
needs_xdg_update=true
fi
done
# If needs XDG update and xdg-user-dirs-update exists in $PATH, run it
if [ $needs_xdg_update = true ] && command -v xdg-user-dirs-update >/dev/null; then
xdg-user-dirs-update
fi
# Create links for user-dirs.dirs
if [ $needs_xdg_links = true ]; then
test -f ${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs && . ${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs
XDG_SPECIAL_DIRS=($XDG_DOCUMENTS_DIR $XDG_DESKTOP_DIR $XDG_DOWNLOAD_DIR $XDG_MUSIC_DIR $XDG_PICTURES_DIR $XDG_VIDEOS_DIR $XDG_PUBLIC_DIR $XDG_TEMPLATES_DIR)
for d in ${XDG_SPECIAL_DIRS[@]}; do
b=$(realpath "$d" --relative-to="$REALHOME")
if [ -e $REALHOME/$b ] && [ ! -e $HOME/$b ]; then
ln -s $REALHOME/$b $HOME/$b
fi
done
else
# If we aren't creating new links, check if we have content saved in old locations and move it
for d in DOCUMENTS DESKTOP DOWNLOAD MUSIC PICTURES VIDEOS PUBLICSHARE TEMPLATES; do
old=`eval "$(echo "echo \\$OLD_XDG_${d}_DIR")"`
new=`eval "$(echo "echo \\$XDG_${d}_DIR")"`
if [ -L "$old" ] && [ -d "$new" ] && [ `readlink "$old"` != "$new" ]; then
mv "$old"/* "$new"/ 2>/dev/null
elif [ -d "$old" ] && [ -d "$new" ] && [ "$old" != "$new" ]; then
mv "$old"/* "$new"/ 2>/dev/null
fi
done
fi
# If detect wayland server socket, then set environment so applications prefer
# wayland, and setup compat symlink (until we use user mounts. Remember,
# XDG_RUNTIME_DIR is /run/user/<uid>/snap.$SNAP so look in the parent directory
# for the socket. For details:
# https://forum.snapcraft.io/t/wayland-dconf-and-xdg-runtime-dir/186/10
# Applications that don't support wayland natively may define DISABLE_WAYLAND
# (to any non-empty value) to skip that logic entirely.
wayland_available=false
if [[ -n "$XDG_RUNTIME_DIR" && -z "$DISABLE_WAYLAND" ]]; then
wdisplay="wayland-0"
if [ -n "$WAYLAND_DISPLAY" ]; then
wdisplay="$WAYLAND_DISPLAY"
fi
wayland_sockpath="$XDG_RUNTIME_DIR/../$wdisplay"
wayland_snappath="$XDG_RUNTIME_DIR/$wdisplay"
if [ -S "$wayland_sockpath" ]; then
# if running under wayland, use it
#export WAYLAND_DEBUG=1
wayland_available=true
# create the compat symlink for now
if [ ! -e "$wayland_snappath" ]; then
ln -s "$wayland_sockpath" "$wayland_snappath"
fi
fi
fi
# Make PulseAudio socket available inside the snap-specific $XDG_RUNTIME_DIR
if [ -n "$XDG_RUNTIME_DIR" ]; then
pulsenative="pulse/native"
pulseaudio_sockpath="$XDG_RUNTIME_DIR/../$pulsenative"
if [ -S "$pulseaudio_sockpath" ]; then
export PULSE_SERVER="unix:${pulseaudio_sockpath}"
fi
fi
# GI repository
[ "$WITH_RUNTIME" = yes ] && prepend_dir GI_TYPELIB_PATH $RUNTIME/usr/lib/$ARCH/girepository-1.0
[ "$WITH_RUNTIME" = yes ] && prepend_dir GI_TYPELIB_PATH $RUNTIME/usr/lib/girepository-1.0
prepend_dir GI_TYPELIB_PATH $SNAP/usr/lib/$ARCH/girepository-1.0
prepend_dir GI_TYPELIB_PATH $SNAP/usr/lib/girepository-1.0
prepend_dir GI_TYPELIB_PATH $SNAP/usr/lib/gjs/girepository-1.0
# Keep an array of data dirs, for looping through them
IFS=':' read -r -a data_dirs_array <<< "$XDG_DATA_DIRS"
# Font Config and themes
export FONTCONFIG_PATH=$RUNTIME/etc/fonts
export FONTCONFIG_FILE=$RUNTIME/etc/fonts/fonts.conf
function make_user_fontconfig {
echo "<fontconfig>"
if [ -d $REALHOME/.local/share/fonts ]; then
echo " <dir>$REALHOME/.local/share/fonts</dir>"
fi
if [ -d $REALHOME/.fonts ]; then
echo " <dir>$REALHOME/.fonts</dir>"
fi
for d in "${data_dirs_array[@]}"; do
if [ -d "$d/fonts" ]; then
echo " <dir>$d/fonts</dir>"
fi
done
echo ' <include ignore_missing="yes">conf.d</include>'
# We need to include this default cachedir first so that caching
# works: without it, fontconfig will try to write to the real user home
# cachedir and be blocked by AppArmor.
echo ' <cachedir prefix="xdg">fontconfig</cachedir>'
if [ -d $REALHOME/.cache/fontconfig ]; then
echo " <cachedir>$REALHOME/.cache/fontconfig</cachedir>"
fi
echo "</fontconfig>"
}
if [ $needs_update = true ]; then
rm -rf $XDG_DATA_HOME/{fontconfig,fonts,fonts-*,themes,.themes}
# This fontconfig fragment is installed in a location that is
# included by the system fontconfig configuration: namely the
# etc/fonts/conf.d/50-user.conf file.
mkdir -p $XDG_CONFIG_HOME/fontconfig
make_user_fontconfig > $XDG_CONFIG_HOME/fontconfig/fonts.conf
# the themes symlink are needed for GTK 3.18 when the prefix isn't changed
# GTK 3.20 looks into XDG_DATA_DIR which has connected themes.
ln -sf $RUNTIME/usr/share/themes $XDG_DATA_HOME
ln -sfn $RUNTIME/usr/share/themes $SNAP_USER_DATA/.themes
fi
# Build mime.cache
# needed for gtk and qt icon
if [ $needs_update = true ]; then
rm -rf $XDG_DATA_HOME/mime
if [ ! -f $RUNTIME/usr/share/mime/mime.cache ]; then
if command -v update-mime-database >/dev/null; then
cp --preserve=timestamps -dR $RUNTIME/usr/share/mime $XDG_DATA_HOME
update-mime-database $XDG_DATA_HOME/mime
fi
fi
fi
# Gio modules and cache (including gsettings module)
export GIO_MODULE_DIR=$XDG_CACHE_HOME/gio-modules
function compile_giomodules {
if [ -f $1/glib-2.0/gio-querymodules ]; then
rm -rf $GIO_MODULE_DIR
mkdir -p $GIO_MODULE_DIR
ln -s $1/gio/modules/*.so $GIO_MODULE_DIR
$1/glib-2.0/gio-querymodules $GIO_MODULE_DIR
fi
}
if [ $needs_update = true ]; then
compile_giomodules $RUNTIME/usr/lib/$ARCH
fi
# Setup compiled gsettings schema
GS_SCHEMA_DIR=$XDG_DATA_HOME/glib-2.0/schemas
function compile_schemas {
if [ -f "$1" ]; then
rm -rf $GS_SCHEMA_DIR
mkdir -p $GS_SCHEMA_DIR
for d in "${data_dirs_array[@]}"; do
schema_dir=$d/glib-2.0/schemas
if [ -f "$schema_dir/gschemas.compiled" ]; then
# This directory already has compiled schemas
continue
fi
if [ -n "$(ls -A $schema_dir/*.xml 2>/dev/null)" ]; then
ln -s $schema_dir/*.xml $GS_SCHEMA_DIR
fi
if [ -n "$(ls -A $schema_dir/*.override 2>/dev/null)" ]; then
ln -s $schema_dir/*.override $GS_SCHEMA_DIR
fi
done
# Only compile schemas if we copied anyting
if [ -n "$(ls -A $GS_SCHEMA_DIR/*.xml $GS_SCHEMA_DIR/*.override 2>/dev/null)" ]; then
"$1" $GS_SCHEMA_DIR
fi
fi
}
if [ $needs_update = true ]; then
compile_schemas $RUNTIME/usr/lib/$ARCH/glib-2.0/glib-compile-schemas
fi
# Enable gsettings user changes
# symlink the dconf file if home plug is connected for read
DCONF_DEST_USER_DIR=$SNAP_USER_DATA/.config/dconf
if [ ! -f $DCONF_DEST_USER_DIR/user ]; then
if [ -f $REALHOME/.config/dconf/user ]; then
mkdir -p $DCONF_DEST_USER_DIR
ln -s $REALHOME/.config/dconf/user $DCONF_DEST_USER_DIR
fi
fi
# Testability support
append_dir LD_LIBRARY_PATH $SNAP/testability
append_dir LD_LIBRARY_PATH $SNAP/testability/$ARCH
append_dir LD_LIBRARY_PATH $SNAP/testability/$ARCH/mesa
# Gdk-pixbuf loaders
export GDK_PIXBUF_MODULE_FILE=$XDG_CACHE_HOME/gdk-pixbuf-loaders.cache
export GDK_PIXBUF_MODULEDIR=$RUNTIME/usr/lib/$ARCH/gdk-pixbuf-2.0/2.10.0/loaders
if [ $needs_update = true ]; then
rm -f $GDK_PIXBUF_MODULE_FILE
if [ -f $RUNTIME/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders ]; then
$RUNTIME/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders > $GDK_PIXBUF_MODULE_FILE
fi
fi
# Icon themes cache
if [ $needs_update = true ]; then
rm -rf $XDG_DATA_HOME/icons
mkdir -p $XDG_DATA_HOME/icons
for d in "${data_dirs_array[@]}"; do
for i in $d/icons/*; do
if [ -f "$i/index.theme" -a ! -f "$i/icon-theme.cache" ]; then
theme_dir=$XDG_DATA_HOME/icons/$(basename "$i")
if [ ! -d "$theme_dir" ]; then
mkdir -p "$theme_dir"
ln -s $i/* "$theme_dir"
if [ -f $RUNTIME/usr/sbin/update-icon-caches ]; then
$RUNTIME/usr/sbin/update-icon-caches "$theme_dir"
elif [ -f $RUNTIME/usr/sbin/update-icon-cache.gtk2 ]; then
$RUNTIME/usr/sbin/update-icon-cache.gtk2 "$theme_dir"
fi
fi
fi
done
done
fi
# GTK theme and behavior modifier
# Those can impact the theme engine used by Qt as well
gtk_configs=(.config/gtk-3.0/settings.ini .config/gtk-3.0/bookmarks .config/gtk-2.0/gtkfilechooser.ini)
for f in ${gtk_configs[@]}; do
dest="$SNAP_USER_DATA/$f"
if [ ! -L "$dest" ]
then
mkdir -p `dirname $dest`
ln -s $REALHOME/$f $dest
fi
done
# create symbolic link to ibus socket path for ibus to look up its socket files
# (see comments #3 and #6 on https://launchpad.net/bugs/1580463)
IBUS_CONFIG_PATH=$XDG_CONFIG_HOME/ibus
mkdir -p $IBUS_CONFIG_PATH
[ -d $IBUS_CONFIG_PATH/bus ] && rm -rf $IBUS_CONFIG_PATH/bus
ln -sfn $REALHOME/.config/ibus/bus $IBUS_CONFIG_PATH
##############################
# Glib minimum specific part #
##############################
###############################
# Mark update and exec binary #
###############################
[ $needs_update = true ] && echo "SNAP_DESKTOP_LAST_REVISION=$SNAP_REVISION" > $SNAP_USER_DATA/.last_revision
if [ -n "$SNAP_DESKTOP_DEBUG" ]; then
echo "desktop-launch elapsed time: " $(date +%s.%N --date="$START seconds ago")
echo "Now running: exec $@"
fi
exec "$@"

@ -1,71 +0,0 @@
#
# Copyright (C) 2018-2022 QuasarApp.
# Distributed under the lgplv3 software license, see the accompanying
# Everyone is permitted to copy and distribute verbatim copies
# of this license document, but changing it is not allowed.
#
QT -= gui
CONFIG += c++17
TARGET = QuasarApp
TEMPLATE = lib
DEFINES += QUASARAPP_LIBRARY
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG(release, debug|release): {
DESTDIR = $$PWD/build/release
DEFINES += RELEASE_BUILD
} else {
DESTDIR = $$PWD/build/debug
}
SOURCES += \
helpdata.cpp \
optiondata.cpp \
quasarapp.cpp \
params.cpp \
locales.cpp \
settings.cpp \
isettings.cpp
HEADERS += \
helpdata.h \
optiondata.h \
quasarapp.h \
quasarapp_global.h \
params.h \
locales.h \
settings.h \
isettings.h \
qaglobalutils.h
DISTFILES += \
QuasarLib.pri \
qmakeEtalons/locales.pri
RESOURCES += \
res.qrc
include(Etalons/qmake/ccache.pri)
VERSION = 1.5.1
# Add empty target for CI system
QMAKE_EXTRA_TARGETS += \
test \
deploy

@ -1,26 +0,0 @@
#
# Copyright (C) 2018-2022 QuasarApp.
# Distributed under the lgplv3 software license, see the accompanying
# Everyone is permitted to copy and distribute verbatim copies
# of this license document, but changing it is not allowed.
#
!isEmpty(QUASARAPP_LIB):error("QuasarLib.pri already included")
QUASARAPP_LIB = 1
#DEPENDS
CONFIG(release, debug|release): {
QUASARAPP_LIB_OUTPUT_DIR="$$PWD/build/release"
} else {
QUASARAPP_LIB_OUTPUT_DIR="$$PWD/build/debug"
}
unix:LIBS += -L$$QUASARAPP_LIB_OUTPUT_DIR -lQuasarApp
win32:LIBS += -L$$QUASARAPP_LIB_OUTPUT_DIR -lQuasarApp1
INCLUDEPATH += "$$PWD/"
include(Etalons/qmake/ccache.pri);

@ -22,9 +22,9 @@ This lib include include next modules:
### Available build options:
```cmake
option(QA_ASSERT_ON_WARN "Enable for add assert to every warning message" OFF)
option(QA_ASSERT_ON_ERROR "Enable for add assert to every error message" OFF)
option(QA_ALLOW_NOT_SUPPORTED_OPTIONS "Enable for allow any command line options" ON)
option(QA_DISABLE_LOG "Disabled all logs (force sets verbose to 0)" OFF)
```
## Include

83
crc32constexper.h Normal file

@ -0,0 +1,83 @@
/*
* Copyright (C) 2025-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef CRC32CONSTEXPER_H
#define CRC32CONSTEXPER_H
#include <array>
#include <cstddef>
#include <cstdint>
namespace QuasarAppUtils {
/**
* @brief generateCrc32Table This method generate crc32 table for fast calculate crc32 hash.
* @param polynomial This is polynomial for crc32 hash.
* @return return table for fast calculate crc32 hash.
* @note This method is constexpr and available in compile time.
*/
constexpr std::array<uint32_t, 256> generateCrc32Table(uint32_t polynomial = 0xEDB88320) {
std::array<uint32_t, 256> table{};
for (uint32_t i = 0; i < 256; ++i) {
uint32_t crc = i;
for (int j = 0; j < 8; ++j) {
crc = (crc >> 1) ^ (-(crc & 1) & polynomial);
}
table[i] = crc;
}
return table;
}
/**
* @brief crc32Table This is crc32 table for fast calculate crc32 hash.
* @note This table is used for fast calculate crc32 hash.
*/
constexpr std::array<uint32_t, 256> crc32Table = generateCrc32Table();
/**
* @brief calculateCrc32 This method calculate crc32 hash for data.
* @param data This is data for calculate crc32 hash.
* @param size This is size of data.
* @param initialCrc This is initial crc value.
* @return return crc32 hash for data.
* @note This method is constexpr and available in compile time.
*/
constexpr uint32_t calculateCrc32(const char* data, size_t size, uint32_t initialCrc = 0xFFFFFFFF) {
uint32_t crc = initialCrc;
for (size_t i = 0; i < size; ++i) {
crc = crc32Table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8);
}
return crc ^ 0xFFFFFFFF;
}
/**
* @brief calculateCrc16 This method calculate crc16 hash for data.
* @param data This is data for calculate crc16 hash.
* @param size This is size of data.
* @param initialCrc This is initial crc value.
* @return return crc16 hash for data.
* @note This method is constexpr and available in compile time.
*/
constexpr uint16_t calculateCrc16(const char* data, size_t size, uint32_t initialCrc = 0xFFFFFFFF) {
return calculateCrc32(data, size, initialCrc) % 0xFFFF;
}
/**
* @brief calculateCrc8 This method calculate crc8 hash for data.
* @param data This is data for calculate crc8 hash.
* @param size This is size of data.
* @param initialCrc This is initial crc value.
* @return return crc8 hash for data.
* @note This method is constexpr and available in compile time.
*/
constexpr uint16_t calculateCrc8(const char* data, size_t size, uint32_t initialCrc = 0xFFFFFFFF) {
return calculateCrc32(data, size, initialCrc) % 0xFF;
}
}
#endif // CRC32CONSTEXPER_H

@ -703,7 +703,7 @@ FILE_VERSION_FILTER =
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
LAYOUT_FILE = CMake/DoxyStyle/DoxygenLayout.xml
LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
@ -1193,7 +1193,7 @@ HTML_STYLESHEET =
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET = CMake/DoxyStyle/doxygenStyles.css
HTML_EXTRA_STYLESHEET =
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
@ -1214,7 +1214,7 @@ HTML_EXTRA_FILES =
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_HUE = 202
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use grayscales only. A
@ -1222,7 +1222,7 @@ HTML_COLORSTYLE_HUE = 220
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_SAT = 212
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
# luminance component of the colors in the HTML output. Values below 100
@ -1233,7 +1233,8 @@ HTML_COLORSTYLE_SAT = 100
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_GAMMA = 80
HTML_COLORSTYLE_GAMMA = 59
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
@ -1605,7 +1606,7 @@ SEARCHENGINE = YES
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
SERVER_BASED_SEARCH = NO
SERVER_BASED_SEARCH = YES
# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -12,7 +12,6 @@
#include <windows.h>
#else
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
#endif

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2022-2022 QuasarApp.
//# Copyright (C) 2022-2025 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2022-2022 QuasarApp.
//# Copyright (C) 2022-2025 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -40,6 +40,14 @@ void ISettings::setMode(const SettingsSaveMode &mode) {
_mode = mode;
}
ISettings *ISettings::instance() {
return Service<ISettings>::instance();
}
bool ISettings::initService(std::unique_ptr<ISettings> obj) {
return Service<ISettings>::initService(std::move(obj));
}
QVariant ISettings::getValue(const QString &key, const QVariant &def) {
debug_assert(key.size(), "You can't use the empty key value!");

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -47,6 +47,7 @@ class QUASARAPPSHARED_EXPORT ISettings : public QObject, public Service<ISetting
Q_OBJECT
public:
~ISettings() override;
/**
* @brief getValue This method return the value of the settings.
@ -103,6 +104,24 @@ public:
*/
void setMode(const SettingsSaveMode &mode);
/**
* @brief instance This method returns pointer to current settings object.
* @return pointer to current settings object.
* @see Service::instance
*/
static ISettings* instance();
/**
* @brief initService This method initialize the global settings object.
* @param obj This is prepared settings object. You should create a your object monyaly, and add to initialization
* @code{cpp}
* bool result = initService(std::make_unique<MySettings>());
* @endcode
* @return true if initialization finished successful else false.
* @see Service::initService
*/
static bool initService(std::unique_ptr<ISettings> obj);
public slots:
/**
* @brief setValue This slot sets new value for a @a key setting
@ -137,13 +156,12 @@ signals:
protected:
explicit ISettings(SettingsSaveMode mode = SettingsSaveMode::Auto);
~ISettings() override;
/**
* @brief defaultSettings This method must be return default map of the settings and them values. If the default value argument in a getValue method will be skipped, then settings model try find a default value in this map.
* @return The default settings map.
* @see ISettings::getValue
* @example example of implementation of this method:
* **example:** example of implementation of this method:
*
* @code{cpp}
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -13,33 +13,32 @@
#include <QLocale>
#include <QLibraryInfo>
#include <QRegularExpression>
#include "params.h"
#include <QLocale>
#include <QMap>
using namespace QuasarAppUtils;
bool QuasarAppUtils::Locales::findQmPrivate(const QString &prefix,
QList<QTranslator*> &qmFiles) {
for (const auto &location: qAsConst(_locations)) {
for (const auto &location: std::as_const(_locations)) {
const auto availableFiles = QDir(location).entryInfoList(
{"*" + prefix + "*.qm"}, QDir::Files);
{prefix + ".qm"}, QDir::Files);
for (const auto &file : availableFiles) {
auto qmFile = new QTranslator();
if(!qmFile->load(file.absoluteFilePath())) {
QuasarAppUtils::Params::log("Failed to load translation file : "
+ file.absoluteFilePath(),
QuasarAppUtils::Warning);
qWarning() << "Failed to load translation file : "
+ file.absoluteFilePath();
delete qmFile;
continue;
}
if (qmFile->isEmpty()) {
QuasarAppUtils::Params::log("Translation file is Empty: " +
file.absoluteFilePath(),
QuasarAppUtils::Debug);
qDebug() << "Translation file is Empty: " +
file.absoluteFilePath();
delete qmFile;
continue;
}
@ -49,7 +48,7 @@ bool QuasarAppUtils::Locales::findQmPrivate(const QString &prefix,
auto message = QString("The target language (%0) and a choosed qm file (%1) "
"is different, Loading will be skiped: ").
arg(language, file.absoluteFilePath());
QuasarAppUtils::Params::log(message, QuasarAppUtils::Debug);
qDebug() << message;
delete qmFile;
continue;
@ -61,7 +60,7 @@ bool QuasarAppUtils::Locales::findQmPrivate(const QString &prefix,
return qmFiles.size();
}
bool QuasarAppUtils::Locales::findQm(const QString &localePrefix,
bool QuasarAppUtils::Locales::findQm(QString localePrefix,
QList<QTranslator *> &qmFiles) {
if (localePrefix.size() < 2) {
@ -71,47 +70,73 @@ bool QuasarAppUtils::Locales::findQm(const QString &localePrefix,
}
return false;
} else if (localePrefix.size() >= 4) {
return findQmPrivate(localePrefix.replace('-', '_'), qmFiles);
}
static QRegularExpression regexp("[_-]");
const auto prefixes = localePrefix.split(regexp);
auto prefixIt = prefixes.begin();
return findQmPrivate((*prefixIt).toLower(), qmFiles);
return findQmPrivate(localePrefix, qmFiles);
}
bool Locales::setLocalePrivate(const QLocale &locale) {
removeOldTranslation();
const auto list = locale.uiLanguages();
QList<QTranslator *> qmFiles;
auto it = list.begin();
while (it != list.end() && !findQm(*it, qmFiles)) {
it++;
}
if (qmFiles.isEmpty())
return false;
for (const auto & translator: qAsConst(qmFiles)) {
void QuasarAppUtils::Locales::installTranslations( QList<QTranslator *> &qmFiles)
{
for (const auto & translator: std::as_const(qmFiles)) {
if (!QCoreApplication::installTranslator(translator)) {
QuasarAppUtils::Params::log("Failed to install translation file : " + translator->filePath(),
QuasarAppUtils::Warning);
qWarning() << "Failed to install translation file : " + translator->filePath();
delete translator;
// we use a link of qmFiles so remove all invalid translations.
qmFiles.removeAll(translator);
continue;
}
}
}
_translations.push_back(translator);
QString Locales::translatePrivate(const char *source, const QLocale &locale) {
auto translations = _translations.value(locale);
for (const auto& tr : translations) {
auto result = tr->translate("QuasarAppUtils::Locales", source);
if (result.size()) {
return result;
}
}
return source;
}
bool Locales::setLocalePrivate(const QLocale &locale, bool force, bool install) {
if (force) {
clearCache(locale);
}
removeOldTranslation(_currentLocate);
// take a link to list of translations.
QList<QTranslator *> &qmFiles = _translations[locale];
if (qmFiles.isEmpty()) {
// fill list of translations
const auto list = locale.uiLanguages();
auto it = list.rbegin();
while (qmFiles.isEmpty() && it != list.rend() && !findQm(*it, qmFiles)) {
it++;
}
if (qmFiles.isEmpty())
return false;
}
if (install)
installTranslations(qmFiles);
emit sigTranslationChanged();
_currentLocate = locale;
return _translations.size();
return _translations[locale].size();
}
const QLocale &Locales::currentLocate() {
@ -119,9 +144,19 @@ const QLocale &Locales::currentLocate() {
return obj->currentLocatePrivate();
}
bool Locales::setLocale(const QLocale &locale) {
QString Locales::tr(const char *source, const QLocale &locale) {
auto obj = instance();
return obj->setLocalePrivate(locale);
return obj->translatePrivate(source, locale);
}
bool Locales::setLocale(const QLocale &locale, bool force) {
auto obj = instance();
return obj->setLocalePrivate(locale, force);
}
bool Locales::init(const QList<QLocale> &locales, const QSet<QString> &location) {
auto obj = instance();
return obj->initPrivate(locales, location);
}
bool Locales::init(const QLocale &locale, const QSet<QString> & location) {
@ -144,17 +179,51 @@ bool Locales::initPrivate(const QLocale &locale, const QSet<QString> & locations
return setLocalePrivate(locale);
}
bool Locales::initPrivate(const QList<QLocale> &locales, const QSet<QString> &locations) {
#if QT_VERSION <= QT_VERSION_CHECK(6, 0, 0)
auto defaultTr = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
#else
auto defaultTr = QLibraryInfo::path(QLibraryInfo::TranslationsPath);
#endif
_locations = locations;
if (!_locations.contains(defaultTr)) {
_locations += defaultTr;
}
for (const auto& locale: locales) {
if (!setLocalePrivate(locale, false, false)) {
return false;
}
}
return true;
}
void Locales::clearCache(const QLocale &locale) {
for (const auto & tr :std::as_const(_translations[locale])) {
QCoreApplication::removeTranslator(tr);
delete tr;
}
_translations[locale].clear();
}
void Locales::clearCache() {
for (auto it = _translations.keyBegin(); it != _translations.keyEnd(); it = std::next(it)) {
clearCache(*it);
}
_translations.clear();
}
Locales *Locales::instance() {
static auto instance = new Locales();
return instance;
}
void Locales::removeOldTranslation() {
for (const auto & tr :qAsConst(_translations)) {
void Locales::removeOldTranslation(const QLocale &locale) {
for (const auto & tr :std::as_const(_translations[locale])) {
QCoreApplication::removeTranslator(tr);
delete tr;
}
_translations.clear();
}
void Locales::addLocationPrivate(const QString &location) {
@ -171,5 +240,5 @@ void Locales::addLocation(const QString &location) {
}
Locales::~Locales() {
removeOldTranslation();
clearCache();
}

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -46,7 +46,16 @@ public:
* @param locale This is new locale.
* @return true if the all ltranstations files loaded successful.
*/
static bool setLocale(const QLocale &locale);
static bool setLocale(const QLocale &locale, bool force = false);
/**
* @brief init This method initialize translations of applictaion.
* @param locales This is list of locales that you want to locad to application cache. See info about QLocale.
* @param location Path to folder with qm files. example (:/tr).
* @return return true if locale set for application.
*/
static bool init(const QList<QLocale> & locales,
const QSet<QString> & location = {});
/**
* @brief init This method initialize translation of applictaion.
@ -75,6 +84,15 @@ public:
*/
static const QLocale &currentLocate();
/**
* @brief tr This method will translate single string to choosed language.
* @param source This is source string of translations.
* @param locale This is choosed language.
* @return translated string value.
* @note use instant QOBject::tr, This method must be read by the lupdate utility
*/
static QString tr(const char *source, const QLocale& locale);
signals:
/**
* @brief sigTranslationChanged Emited when set new locale for application.
@ -85,22 +103,33 @@ private:
Locales() = default;
~Locales();
bool setLocalePrivate(const QLocale &locale = QLocale::system());
bool setLocalePrivate(const QLocale &locale = QLocale::system(), bool force = false, bool install = true);
bool initPrivate(const QLocale &locale = QLocale::system(),
const QSet<QString> &location = {});
void removeOldTranslation();
bool initPrivate(const QList<QLocale> &locales,
const QSet<QString> &location = {});
void clearCache(const QLocale& locale);
void clearCache();
void removeOldTranslation(const QLocale& locale);
void addLocationPrivate(const QString& location);
const QLocale &currentLocatePrivate() const;
bool findQm(const QString &localePrefix,
bool findQm(QString localePrefix,
QList<QTranslator *> &result);
bool findQmPrivate(const QString &prefix,
QList<QTranslator *> &qmFiles);
void installTranslations(QList<QTranslator *> &qmFiles);
QString translatePrivate(const char *source, const QLocale& locale);
QLocale _currentLocate;
QSet<QString> _locations;
QList<QTranslator *> _translations;
QHash<QLocale, QList<QTranslator *>> _translations;
};
}

@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Copyright (C) 2021-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -7,7 +7,6 @@
#include "optiondata.h"
#include "qaglobalutils.h"
namespace QuasarAppUtils{

@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Copyright (C) 2021-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -9,16 +9,19 @@
#include <QVariantMap>
#include <QDebug>
#include <QFileInfo>
#include <iostream>
#include <QDateTime>
#include <QCoreApplication>
#include "qaglobalutils.h"
#include <QtLogging>
#ifdef Q_OS_DARWIN
#include <mach-o/dyld.h>
#endif
#ifdef Q_OS_WIN
#include "windows.h"
#else
#include <unistd.h>
#include <limits.h>
#endif
using namespace QuasarAppUtils;
@ -35,66 +38,27 @@ bool Params::isEndable(const QString& key) {
void Params::log(const QString &log, VerboseLvl vLvl) {
writeLoginFile(log, vLvl);
auto lvl = getVerboseLvl();
if (vLvl <= lvl) {
switch (vLvl) {
case VerboseLvl::Error:
#ifdef Q_OS_WIN32
std::cerr << QString{lvlToString(vLvl) + ": " + log}.toStdString() << std::endl;
#else
qCritical().noquote() << lvlToString(vLvl) + ": " + log;
#endif
#ifdef QA_ASSERT_ON_ERROR
#ifdef __GNUC__
__builtin_trap();
#else
debug_assert(false, "You requested to throw assert in every error message."
" See The ASSERT_ON_ERROR option in cmake config.");
#endif
#endif
qCritical().noquote() << log;
break;
case VerboseLvl::Warning: {
#ifdef Q_OS_WIN32
std::cerr << QString{lvlToString(vLvl) + ": " + log}.toStdString() << std::endl;
#else
qWarning().noquote() << lvlToString(vLvl) + ": " + log;
#endif
#ifdef QA_ASSERT_ON_WARN
#ifdef __GNUC__
__builtin_trap();
#else
debug_assert(false, "You requested to throw assert in every warning message."
" See The ASSERT_ON_ERROR option in cmake config.");
#endif
#endif
qWarning().noquote() << log;
break;
}
case VerboseLvl::Debug: {
#ifdef Q_OS_WIN32
std::cout << QString{lvlToString(vLvl) + ": " + log}.toStdString() << std::endl;
#else
qDebug().noquote() << lvlToString(vLvl) + ": " + log;
#endif
qDebug().noquote() << log;
break;
}
case VerboseLvl::Info:
default: {
#ifdef Q_OS_WIN32
std::cout << QString{lvlToString(vLvl) + ": " + log}.toStdString() << std::endl;
#else
qInfo().noquote() << lvlToString(vLvl) + ": " + log;
#endif
qInfo().noquote() << log;
break;
}
@ -140,7 +104,7 @@ Help::Section Params::getHelpOfInputOptions() {
}
Help::Options help;
for (const auto &optionData: qAsConst(inputOptions) ) {
for (const auto &optionData: std::as_const(inputOptions) ) {
help.unite(optionData.toHelp());
}
@ -191,63 +155,6 @@ int Params::size() {
return params.size();
}
QString Params::timeString() {
return QDateTime::currentDateTime().toString();
}
QString Params::lvlToString(VerboseLvl vLvl) {
switch (vLvl) {
case VerboseLvl::Error: {
return "Error";
}
case VerboseLvl::Warning: {
return "Warning";
}
case VerboseLvl::Info: {
return "Info";
}
case VerboseLvl::Debug: {
return "Verbose log";
}
default: return "";
}
return "";
}
bool Params::writeLoginFile(const QString &log, VerboseLvl vLvl) {
if (isEndable("fileLog")) {
QString path = getCurrentExecutable() + ".log";
auto file = getArg("fileLog");
if (file.size()) {
path = file;
}
QFile logFile(path);
if (logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
QTextStream stream(&logFile);
#if QT_VERSION > QT_VERSION_CHECK(5, 14, 0)
stream << timeString() <<"| " << lvlToString(vLvl) + ": " + log << Qt::endl;
#else
stream << timeString() <<"| " << lvlToString(vLvl) + ": " + log << endl;
#endif
logFile.close();
} else {
return false;
}
}
return true;
}
bool Params::optionsForEach(const QStringList &paramsArray,
const OptionsDataList& availableOptions) {
@ -272,8 +179,7 @@ bool Params::optionsForEach(const QStringList &paramsArray,
params[paramsArray[i].mid(1)] = paramsArray[i + 1];
i++;
} else {
QuasarAppUtils::Params::log("Missing argument for " + paramsArray[i],
QuasarAppUtils::Error);
qCritical() << "Missing argument for " + paramsArray[i];
return false;
}
} else {
@ -320,8 +226,7 @@ bool Params::parseParams(const QStringList &paramsArray, const OptionsDataList &
memset(path, 0, sizeof path);
if (readlink("/proc/self/exe", path, 2048) < 0) {
QuasarAppUtils::Params::log("parseParams can't get self path!",
QuasarAppUtils::Error);
qCritical() << "parseParams can't get self path!";
return false;
}
appPath = QFileInfo(path).absolutePath();
@ -329,7 +234,15 @@ bool Params::parseParams(const QStringList &paramsArray, const OptionsDataList &
#endif
#ifdef Q_OS_DARWIN
appPath = QCoreApplication::applicationDirPath();
uint32_t size = 0;
_NSGetExecutablePath(nullptr, &size); // request to buffer size
std::vector<char> buffer(size);
if (_NSGetExecutablePath(buffer.data(), &size) == 0) {
appPath = QString::fromUtf8(buffer.data());
} else {
appPath = QString();
}
appName = QCoreApplication::applicationName();
#endif
@ -347,8 +260,7 @@ bool Params::parseParams(const QStringList &paramsArray, const OptionsDataList &
}
void Params::printWorkingOptions() {
QuasarAppUtils::Params::log("--- Working options table start ---",
QuasarAppUtils::Debug);
qDebug() << "--- Working options table start ---";
QMap<QString, QString>::const_iterator iter = params.constBegin();
while (iter != params.constEnd()) {
@ -360,23 +272,24 @@ void Params::printWorkingOptions() {
row += QString{": %1"}.arg(value);
}
QuasarAppUtils::Params::log(row, QuasarAppUtils::Debug);
qDebug() << row;
++iter;
}
QuasarAppUtils::Params::log("--- Working options table end ---",
QuasarAppUtils::Debug);
qDebug() << "--- Working options table end ---";
}
bool Params::checkOption(const OptionData& optionData, const QString& rawOptionName) {
#ifndef QA_ALLOW_NOT_SUPPORTED_OPTIONS
if (!optionData.isValid()) {
QuasarAppUtils::Params::log(QString("The '%0' option not exists!"
" You use wrong option name, please check the help before run your commnad.").arg(
rawOptionName),
QuasarAppUtils::Error);
qCritical() << QString("The '%0' option not exists!"
" You use wrong option name,"
" please check the help before run your commnad.").
arg(rawOptionName);
return false;
}
#else
@ -388,19 +301,17 @@ bool Params::checkOption(const OptionData& optionData, const QString& rawOptionN
if (optionData.isRemoved()) {
QuasarAppUtils::Params::log(optionData.depricatedMsg(),
QuasarAppUtils::Error);
qCritical() << optionData.depricatedMsg();
return false;
}
QuasarAppUtils::Params::log(QString("The %0 option(s) marked as deprecated! "
"And most likely will be removed in next release.").
arg(optionData.names().join("/")),
QuasarAppUtils::Warning);
qWarning() << QString("The %0 option(s) marked as deprecated! "
"And most likely will be removed in next release.").
arg(optionData.names().join("/"));
qWarning() << QString("Option message: %0").arg(optionData.depricatedMsg());
QuasarAppUtils::Params::log(QString("Option message: %0").arg(optionData.depricatedMsg()),
QuasarAppUtils::Warning);
}
return true;
@ -419,7 +330,7 @@ void Params::parseAvailableOptions(const OptionsDataList &availableOptionsListIn
for (auto it = availableOptionsListIn.begin(); it != availableOptionsListIn.end(); ++it) {
if (availableOptionsListOut) {
for (const auto &name : qAsConst(it.value().names())) {
for (const auto &name : std::as_const(it.value().names())) {
availableOptionsListOut->insert(name, it.value());
}
}

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -31,12 +31,15 @@ enum VerboseLvl {
Debug = 0x3,
};
#ifdef QA_DISABLE_LOG
#define DEFAULT_VERBOSE_LVL "0"
#else
#ifdef QT_DEBUG
#define DEFAULT_VERBOSE_LVL "3"
#else
#define DEFAULT_VERBOSE_LVL "2"
#endif
#endif
/**
* @brief The Params class Contains fonctions for working with input arguments and logs.
@ -128,6 +131,7 @@ public:
* @note All messages will be printed according to the current verbose setting.
* @note The verbose level sets by verbose option on console.
*/
[[deprecated("Use QALogger and qt debug functions(qDebug, qInfo, qError...)")]]
static void log(const QString& log, VerboseLvl vLvl = VerboseLvl::Debug);
/**
@ -146,6 +150,7 @@ public:
* @brief isDebugBuild This method return true if the library buildet in debug mode.
* @return true if this library buildet in debug mode.
*/
[[deprecated("Use Qt MACROSSSES")]]
static bool isDebugBuild();
/**
@ -214,10 +219,6 @@ public:
static OptionsDataList availableArguments();
private:
static QString timeString();
static QString lvlToString(VerboseLvl vLvl);
static bool writeLoginFile(const QString& log, VerboseLvl vLvl = VerboseLvl::Debug);
static bool optionsForEach(const QStringList& paramsArray,
const OptionsDataList &availableOptions);

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -10,7 +10,7 @@
template<class NUM>
void gen(int size, QByteArray &result) {
for (; size >= 0; size -= sizeof(NUM)) {
for (; size > 0; size -= sizeof(NUM)) {
NUM random = (rand() * rand()) % std::numeric_limits<NUM>::max();
result.insert(0, reinterpret_cast<char*>(&random), sizeof(random));
}

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -8,14 +8,11 @@
#ifndef QU_GLOBAL_UTILS_H
#define QU_GLOBAL_UTILS_H
#include <cstdlib>
#include <type_traits>
#include <string>
#include <typeinfo>
#include <QByteArray>
#include "QtGlobal"
#include "params.h"
#include "quasarapp_global.h"
template <typename T>
constexpr inline T operator | (T lhs, T rhs)
@ -150,18 +147,7 @@ uint8_t static_type_hash_8(T& object) noexcept {
#define H_32 static_type_hash_32
#ifndef QT_DEBUG
// The debug_assert it is assert that abort application only in debug mode.
// In the release mode This assert prin Error message only.
#define debug_assert(condition, msg) \
if (!condition) \
QuasarAppUtils::Params::log(msg, QuasarAppUtils::Error);
#else
// The debug_assert it is assert that abort application only in debug mode.
// In the release mode This assert prin Error message only.
#define debug_assert(condition, msg) assert(condition && msg)
#endif
#define debug_assert(C, M) Q_ASSERT(C && M)
/**
* @brief randomArray This function return random arrat with size @a size

114
qalogger.cpp Normal file

@ -0,0 +1,114 @@
/*
* Copyright (C) 2024-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "qalogger.h"
#include "params.h"
#include <iostream>
#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QStandardPaths>
namespace QuasarAppUtils {
Q_GLOBAL_STATIC(QString, _logFile)
static bool _toFile = false;
static VerboseLvl _verboseLevel = Debug;
#define MESSAGE_PATTERN \
"[%{time MM-dd h:mm:ss.zzz} %{threadid} " \
"%{if-debug}Debug%{endif}%{if-info}Info%{endif}%{if-warning}Warning%{endif}%{if-critical}Error%{endif}%{if-fatal}Fatal%{endif}] " \
"%{message}"
QALogger::QALogger() {
}
QALogger::~QALogger() {
}
bool checkLogType(QtMsgType type, VerboseLvl lvl) {
switch (type) {
case QtDebugMsg: return lvl >= Debug;
case QtInfoMsg: return lvl >= Info;
case QtWarningMsg: return lvl >= Warning;
case QtCriticalMsg:
case QtFatalMsg:
return true;
}
return true;
}
void messageHandler(QtMsgType type, const QMessageLogContext & context, const QString &msg) {
if (checkLogType(type, _verboseLevel)) {
if (_toFile && _logFile->size()) {
QFile logFile(*_logFile);
if (logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
QTextStream stream(&logFile);
stream << qFormatLogMessage(type, context, msg) << Qt::endl;
}
}
switch (type) {
case QtMsgType::QtFatalMsg:
case QtMsgType::QtCriticalMsg:
case QtMsgType::QtWarningMsg: {
std::cerr << qFormatLogMessage(type, context, msg).toStdString() << std::endl;
break;
}
case QtMsgType::QtDebugMsg:
case QtMsgType::QtInfoMsg:
default: {
std::cout << qFormatLogMessage(type, context, msg).toStdString() << std::endl;
break;
}
}
}
}
void QALogger::init() {
qSetMessagePattern(MESSAGE_PATTERN);
qInstallMessageHandler(messageHandler);
_verboseLevel = Params::getVerboseLvl();
if (Params::isEndable("fileLog")) {
_toFile = true;
QString path = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
QString filePath = path + "/" + QCoreApplication::applicationName() +
" " + QDate::currentDate().toString(Qt::DateFormat::ISODate) + ".log";
auto file = Params::getArg("fileLog");
if (file.size()) {
filePath = file;
}
QDir().mkpath(path);
*_logFile = filePath;
}
}
QString QALogger::getLogFilePath() {
return *_logFile;
}
}

66
qalogger.h Normal file

@ -0,0 +1,66 @@
/*
* Copyright (C) 2024-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef QALOGGER_H
#define QALOGGER_H
#include "quasarapp_global.h"
#include <QFile>
#include <QList>
namespace QuasarAppUtils {
/**
* @brief The QALogger class is logger handler for app.
* This class allow to log all message from app to file.
*
* Example:
* @code
* #include <qalogger.h>
*
* QuasarAppUtils::QALogger logger;
*
* QuasarAppUtils::Params::setEnable("fileLog", true); //force enable file writing using efault file location - located in localApplication data.
*
* QuasarAppUtils::Params::parseParams(argc, argv);
*
* logger.init();
* @endcode
*
*
* Standart file log locations per platforms :
* - Windows: %APPDATA%/OrganisationName/YourAppName/YourAppName.log
* - Linux: $HOME/.config/OrganisationName/YourAppName/YourAppName.log
* - Mac: $HOME/Library/Application Support/OrganisationName/YourAppName/YourAppName.log
* - Android: /data/data/com.organisationName.yourAppName/files/YourAppName.log
* - iOS: /var/mobile/Applications/Data/YourAppName/YourAppName.log
*
* you can overiwite this location by setting "fileLog" option in Params.
*/
class QUASARAPPSHARED_EXPORT QALogger
{
public:
QALogger();
~QALogger();
/**
* @brief init This method initialize logging of all qt message into file.
* @note This function should be invokae after parsing arguments.
* if you invoke this before parsing arguments, verbose level of logs will not created correct.
*/
void init();
/**
* @brief setVerboseLevel This method set verbose level of the logger.
* @param lvl This is new verbose level.
*/
static QString getLogFilePath();
};
}
#endif // QALOGGER_H

53
qaplatformutils.h Normal file

@ -0,0 +1,53 @@
/*
* Copyright (C) 2024-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef PLATFORMUTILS_H
#define PLATFORMUTILS_H
#include <QString>
#include "quasarapp_global.h"
namespace QuasarAppUtils {
/**
* @brief The iPlatformUtils class bas interface for get access platform dependet functions and constants.
*/
class QUASARAPPSHARED_EXPORT PlatformUtils
{
public:
PlatformUtils();
/**
* @brief isSnap This method check destribution type. true if the application packed as a snap.
* @return true if the application packaged as a snap else false.
*/
static bool isSnap();
/**
* @brief snapRootFS returns root file system of main OS (available read only)
* @return path ro main os root.
*/
static QString snapRootFS();
/**
* @brief transportPathToSnapRoot change path to snap avaialble.
* @param path source path of main OS.
* @return readable path location for snap pacakge.
* @note this method is not a fast, so not invoke it too offten.
*/
static QString transportPathToSnapRoot(const QString &path);
/**
* @brief checkSystemBakupSnapInterface This method check access to bakcup permision of snap pacakge.
* This permision required to get access to rootfs of main OS.
* @return true if the app have this accesss.
*/
static bool checkSystemBakupSnapInterface();
};
}
#endif // IPLATFORMUTILS_H

99
qaplatformutils_linux.cpp Normal file

@ -0,0 +1,99 @@
/*
* Copyright (C) 2024-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "qaplatformutils.h"
#if defined(Q_OS_LINUX)
#include <QDir>
#include <QFileInfo>
#include <QProcessEnvironment>
#elif defined(Q_OS_ANDROID)
#elif defined(Q_OS_WIN32)
#elif defined(Q_OS_MACOS)
#elif defined(Q_OS_IOS)
#endif
namespace QuasarAppUtils {
#if defined(Q_OS_LINUX)
bool PlatformUtils::isSnap() {
return QProcessEnvironment::systemEnvironment().value("SNAP").size();
}
QString PlatformUtils::snapRootFS() {
return "/var/lib/snapd/hostfs";
}
QString PlatformUtils::transportPathToSnapRoot(const QString &path) {
if (isSnap() && checkSystemBakupSnapInterface()) {
if(QFileInfo(path).isWritable()) {
return path;
}
if (path.size() && path[0] != QString("/")) {
auto absalutPath = QProcessEnvironment::systemEnvironment().value("PWD") + "/" + path;
if (!absalutPath.contains(snapRootFS())) {
return snapRootFS() + "/" + absalutPath;
}
}
if (!path.contains(snapRootFS())) {
return snapRootFS() + "/" + path;
}
}
return path;
}
bool PlatformUtils::checkSystemBakupSnapInterface() {
return QDir(snapRootFS()).entryList(QDir::AllEntries | QDir::NoDotAndDotDot).size();
}
#elif defined(Q_OS_ANDROID)
bool PlatformUtils::isSnap() { return false;}
QString PlatformUtils::snapRootFS() { return "";}
QString PlatformUtils::transportPathToSnapRoot(const QString &path) { return path; }
bool PlatformUtils::checkSystemBakupSnapInterface() { return false; }
#elif defined(Q_OS_WIN32)
bool PlatformUtils::isSnap() { return false;}
QString PlatformUtils::snapRootFS() { return "";}
QString PlatformUtils::transportPathToSnapRoot(const QString &path) { return path; }
bool PlatformUtils::checkSystemBakupSnapInterface() { return false; }
#elif defined(Q_OS_MACOS)
bool PlatformUtils::isSnap() { return false;}
QString PlatformUtils::snapRootFS() { return "";}
QString PlatformUtils::transportPathToSnapRoot(const QString &path) { return path; }
bool PlatformUtils::checkSystemBakupSnapInterface() { return false; }
#elif defined(Q_OS_IOS)
bool PlatformUtils::isSnap() { return false;}
QString PlatformUtils::snapRootFS() { return "";}
QString PlatformUtils::transportPathToSnapRoot(const QString &path) { return path; }
bool PlatformUtils::checkSystemBakupSnapInterface() { return false; }
#endif
}

48
qasecretservice.cpp Normal file

@ -0,0 +1,48 @@
#include "qasecretservice.h"
#ifdef Q_OS_LINUX
#include <QProcess>
QByteArray QuasarAppUtils::QASecretService::getByAlias(const QString &alias) {
QProcess proc;
proc.setProgram("qasecretservice");
proc.setArguments(QStringList() << "get" << "-alias" << alias);
proc.start();
if (!proc.waitForFinished(2000)) {
return "";
}
if (proc.exitCode()) {
return "";
}
QByteArray result = proc.readAllStandardOutput();
// drop \n
return result.left(result.size() - 1);
}
QByteArray QuasarAppUtils::QASecretService::getByHash(const QByteArray &hash)
{
QProcess proc;
proc.setProgram("qasecretservice");
proc.setArguments(QStringList() << "get" << "-hash" << hash);
proc.start();
if (!proc.waitForFinished(2000)) {
return "";
}
if (proc.exitCode()) {
return "";
}
QByteArray result = proc.readAllStandardOutput();
// drop \n
return result.left(result.size() - 1);
}
#endif

35
qasecretservice.h Normal file

@ -0,0 +1,35 @@
/*
* Copyright (C) 2024-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef QASECRETSERVICE_H
#define QASECRETSERVICE_H
#include <QByteArray>
namespace QuasarAppUtils {
/**
* @brief The qasecretservice class This is a simeple provider of QASecretService tool
* See https://github.com/QuasarApp/SecretService
* @note Before use this class please install QASecretService to your runtime mashine.
*
*/
class QASecretService
{
public:
QASecretService();
#ifdef Q_OS_LINUX
static QByteArray getByAlias(const QString& alias);
static QByteArray getByHash(const QByteArray& hash);
#endif
};
}
#endif // QASECRETSERVICE_H

@ -1,8 +1,7 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "qaservice.h"

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -8,6 +8,7 @@
#ifndef QASERVICE_H
#define QASERVICE_H
#include <memory>
#include <utility>
namespace QuasarAppUtils {
@ -65,6 +66,7 @@ namespace QuasarAppUtils {
template<class Base>
class Service
{
public:
Service() {};
@ -76,16 +78,32 @@ public:
* @see deinitService
* @see autoInstance
*/
template<class BaseClass = Base, class... Args>
static Base* initService(Args&&... args) {
Service<Base>* instanceObj = privateInstance();
if(!instanceObj->_data) {
instanceObj->_data = new BaseClass(std::forward<Args>(args)...);
static inline std::unique_ptr<Base>& initService() {
auto& val = instancePrivat();
if(!val) {
val.reset(new Base());
}
return instanceObj->_data;
return val;
}
/**
* @brief initService This is overrided static method of initialization cross libraryes object.
* @note If you want to create your own implementation of the settings object - you need to use this method for initioalisation instant qaservice::initService - template method.
* Becouse Some OS has every shared libraryes has itself isolation address space (for example Android).
* If you initialize instance of your settings model on one libarary the this instance will be available only on your library or upper.
* Bot not on the QuasarApp lib so SettingsListner will not work.
* @param obj This is inited settings object.
* @return true if the @a obj service was saved as a service object else false.
*/
static bool initService(std::unique_ptr<Base> obj) {
auto& val = instancePrivat();
if(!val) {
val = std::move(obj);
return true;
}
return false;
};
/**
* @brief instance This method return pointerer to current service object.
* @note If object was not initialized, then return false.
@ -95,7 +113,7 @@ public:
* @see autoInstance
*/
static Base* instance() {
return privateInstance()->_data;
return instancePrivat().get();
}
/**
@ -104,12 +122,13 @@ public:
* @see instance
*/
static Base* autoInstance() {
auto& val = instancePrivat();
if (!privateInstance()->_data) {
if (!val) {
initService();
}
return privateInstance()->_data;
return val.get();
}
/**
@ -120,20 +139,18 @@ public:
* @see autoInstance
*/
static void deinitService() {
Service<Base>* instanceObj = privateInstance();
if(instanceObj->_data) {
delete instanceObj->_data;
instanceObj->_data = nullptr;
auto& val = instancePrivat();
if(val) {
val.release();
}
}
private:
static Service<Base>* privateInstance() {
static Service<Base>* privateObject = new Service<Base>;
return privateObject;
};
Base* _data = nullptr;
static inline std::unique_ptr<Base>& instancePrivat() {
static std::unique_ptr<Base> instance = nullptr;
return instance;
}
};

@ -1,11 +1,10 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "quasarapp.h"

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -11,6 +11,7 @@
#include "params.h"
#include "locales.h"
#include "settings.h"
#include "qaplatformutils.h"
/**
* @brief The QuasaraAppUtils class

@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Copyright (C) 2021-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -65,4 +65,17 @@ void Settings::setBoolOptions(const QSet<QString> &newBoolOptions)
_boolOptions = newBoolOptions;
}
bool Settings::initService() {
return ISettings::initService(std::make_unique<Settings>());
}
ISettings *Settings::autoInstance() {
if (auto result = instance()) {
return result;
}
Settings::initService();
return ISettings::instance();
}
}

@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Copyright (C) 2021-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
@ -61,6 +61,20 @@ public:
*/
void setBoolOptions(const QSet<QString> &newBoolOptions);
/**
* @brief initService This method initialize default object of the QuasarAppUtils::Settings type.
* @return true if initialization finished successfull else false.
* @see ISettings::initService
*/
static bool initService();
/**
* @brief deinitService This method destroy default object of the QuasarAppUtils::Settings type.
* @see ISettings::deinitService
*/
static ISettings *autoInstance();
protected:
void syncImplementation() override;

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2022-2022 QuasarApp.
//# Copyright (C) 2022-2025 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2022-2022 QuasarApp.
//# Copyright (C) 2022-2025 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.