Compare commits

..

No commits in common. "main" and "v1.1.3" have entirely different histories.
main ... v1.1.3

44 changed files with 790 additions and 5493 deletions

16
.gitignore vendored
View File

@ -44,19 +44,3 @@ CMakeLists.txt.user*
build/*
*.user*
#cmake
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
*_autogen
docs/html

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "CMake"]
path = CMake
url = https://github.com/QuasarApp/CMake.git

1
CMake

@ -1 +0,0 @@
Subproject commit 76d88f13235574890fa72e9a811c6ff524d6abaa

View File

@ -1,70 +0,0 @@
#
# 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.
#
if(DEFINED QUASARAPP_LIBRARY)
return()
else()
set(QUASARAPP_LIBRARY 1)
add_definitions(-DQUASARAPP_LIBRARY)
endif()
project(QuasarApp)
if(TARGET ${PROJECT_NAME})
message("The ${PROJECT_NAME} arledy included in main Project")
return()
endif()
cmake_minimum_required(VERSION 3.1)
include(CMake/QuasarApp.cmake)
include(CMake/Version.cmake)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
option(BUILD_SHARED_LIBS "Enable or disable shared libraryes" OFF)
if (NOT QT_VERSION_MAJOR)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
endif()
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
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_DISABLE_LOG)
add_definitions(-DQA_DISABLE_LOG)
endif()
if (QA_ALLOW_NOT_SUPPORTED_OPTIONS)
add_definitions(-DQA_ALLOW_NOT_SUPPORTED_OPTIONS)
endif()
file(GLOB SOURCE_CPP
"*.cpp" "*.h"
)
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 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})

View File

@ -0,0 +1,33 @@
#
# 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.
#
!isEmpty(INSTALL_REFIX_PRI_INCLUDED):error("install_prefix.pri already included")
INSTALL_REFIX_PRI_INCLUDED = 1
unix:libfiletype=*.so*
win32:libfiletype=*.dll
unix:runfiletype=*
win32:runfiletype=*.exe
isEmpty(PREFIX) {
message(install target not complited if you want added install rules use PREFIX)
} else {
message(install target (use install_data): $$PREFIX)
install_data.path = $$PREFIX
# install_data.CONFIG += no_check_exist
INSTALLS += install_data
}

33
Etalons/qmake/locales.pri Executable file
View File

@ -0,0 +1,33 @@
#
# Copyright (C) 2018 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")
}

View File

@ -0,0 +1,442 @@
#!/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 "$@"

55
QuasarApp.pro Normal file
View File

@ -0,0 +1,55 @@
#
# 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 -= gui
TARGET = QuasarApp
TEMPLATE = lib
DEFINES += QUASARAAPP_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
} else {
DESTDIR = $$PWD/build/debug
}
SOURCES += \
quasarapp.cpp \
params.cpp \
locales.cpp \
settings.cpp
HEADERS += \
quasarapp.h \
quasarapp_global.h \
params.h \
locales.h \
settings.h
DISTFILES += \
QuasarLib.pri \
qmakeEtalons/locales.pri
RESOURCES += \
res.qrc
VERSION = 1.1.3

24
QuasarLib.pri Normal file
View File

@ -0,0 +1,24 @@
#
# 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.
#
!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/"

101
README.md
View File

@ -1,68 +1,63 @@
# QuasarAppLib
Global functions used in applications QuasarApp.
This lib include include next modules:
Global function for quasar app.
This lib include base functions for the all applications of QuasarApp group.
All methods of the Quasar AppUtils is static
* Locales - This module use for parse local files. This module allows you to work with translations.
* Params - This module use for parese app params and create log.
* Settings - This is a module that allows you to work with application settings.
* Global - This module contains other global functions.
* parseParams - parase input data of started application
* argc - count of arguments
* argv - arrat of arguments
* return true if all arguments read else false
------------------------
* getStrArg - get string value of key
* key
* return string value of argument
## Build
------------------------
* getArg - get string value of key
* key
* return string value of argument
------------------------
* git clone https://github.com/QuasarApp/QuasarAppLib.git
* git submodule update --init --recursive
* cd QuasarAppLib
* cmake -DCMAKE_PREFIX_PATH=Yuor/Qt/Dir/Path .
* make -j8
* make test #(for testing)
* isEndable - check if enable argument of key
* key
* return true if argument enabled
------------------------
* initLocale init translation of applictaion
* locale - string value of locale. example (en)
* app - app core of qt
* translator - translator core of qt
* return return true if locale funded
### Available build options:
# QuasarAppLib
Глобальная функция для приложений quasar.
Эта библиотека включает базовые функции для всех приложений группы QuasarApp.
Все методы Quasar AppUtils являются статическими
```cmake
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)
* parseParams - парсит входные данные запускаемого приложения
* argc - количество аргументов
* argv - аргумент аргументов
* вернет true, если все аргументы прочитаны верно иначе false
```
------------------------
* getStrArg - получить строковое значение ключа
* возвращаемое строковое значение аргумента
## Include
------------------------
#### The cmake build do not required Qt libraries.
* cd yourRepo
* git submodule add https://github.com/QuasarApp/QuasarAppLib.git # add the repository of QtBigInt into your repo like submodule
* git submodule update --init --recursive
* Include in your CMakeLists.txt file the main CMakeLists.txt file of QuasarAppLib library
>> add_subdirectory(QuasarAppLib)
* Rebuild yuor project
* getArg - получить строковое значение ключа
* возвращаемое строковое значение аргумента
```cmake
add_subdirectory(QuasarAppLib)
target_link_libraries(MyBinary PUBLIC QuasarApp)
```
------------------------
### Note
* isEndable - проверить, разрешен ли аргумент ключа
* вернет true, если аргумент включен
By Default QuasarAppLib makes as a static library. If you want to create a shared library just add the BUILD_SHARED_LIBS into your main CMakeLists.txt file.
Example :
```cmake
set(BUILD_SHARED_LIBS ON)
add_subdirectory(QuasarAppLib)
target_link_libraries(MyBinary PUBLIC QuasarApp)
```
# Usage
```cpp
#include <quasarapp.h>
if (!QuasarAppUtils::Params::parseParams(argc, argv)) {
QuasarAppUtils::Params::log("Warning message", QuasarAppUtils::Warning);
QuasarAppUtils::Params::showHelp();
exit(0);
}
```
------------------------
* initLocale инициализирует перевод приложения
* locale - строковое значение locale. пример (en)
* app - ядро приложения qt
* translator - ядро переводчика qt
* вернет true, если все аргументы прочитаны верно иначе false

View File

@ -1,83 +0,0 @@
/*
* 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

2
deploy.pri Executable file
View File

@ -0,0 +1,2 @@
DESTDIR=$$PWD/build

File diff suppressed because it is too large Load Diff

View File

@ -1,108 +0,0 @@
/*
* 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 "helpdata.h"
#include <iostream>
#ifdef Q_OS_WIN32
#include <windows.h>
#else
#include <sys/ioctl.h>
#include <unistd.h>
#endif
namespace QuasarAppUtils {
namespace Help {
static int MAX_LENGTH = -1;
static int SectionMargin = 2;
#define EXPANDER(COUNT, ITEM) QString(COUNT, ITEM).toStdString()
#define SPACES(X) EXPANDER(X, ' ')
#define SECTION_MARGIN SPACES(SectionMargin)
#define WIDTH ((MAX_LENGTH > 10)? MAX_LENGTH: width())
/*
* @brief print This method prints the one line of the help.
* @param key This is Option name.
* @param value This is Description of option.
* @param keyLength This is length of the current line.
* This is private method of the QuasarAppLibrary.
*/
void print(const QString& key, const QString& value, int keyLength) {
auto diffExpander = QString(keyLength - key.size(), ' ');
std::cout << SECTION_MARGIN << key.toStdString() << diffExpander.toStdString() << ":";
QString expander(keyLength + SectionMargin, ' ');
auto words = value.split(" ");
int currentLength = std::max(keyLength, static_cast<int>(key.size()));
for (const auto& word : words) {
if (currentLength + 2 + word.size() < WIDTH) {
std::cout << " " << word.toStdString();
currentLength += 2 + word.size();
} else {
std::cout << std::endl << expander.toStdString() << ":";
currentLength = keyLength;
std::cout << " " << word.toStdString();
currentLength += 2 + word.size();
}
}
}
void print(const QuasarAppUtils::Help::Options &oprionsList) {
int maxLength = 0;
for (auto line = oprionsList.begin(); line != oprionsList.end(); ++line) {
if (line.key().size() > maxLength)
maxLength = line.key().size();
}
maxLength = std::min(WIDTH / 3, maxLength);
for (auto line = oprionsList.begin(); line != oprionsList.end(); ++line) {
print(line.key(), line.value(), maxLength + SectionMargin);
std::cout << std::endl;
}
}
void print(const Section &help) {
for (auto line = help.begin(); line != help.end(); ++line) {
QString expander(WIDTH, '-');
std::cout << line.key().toStdString() << std::endl;
std::cout << expander.toStdString() << std::endl;
print(line.value());
std::cout << std::endl << expander.toStdString() << std::endl;
}
}
void setLineLength(int newLength) {
MAX_LENGTH = newLength;
}
int width() {
#ifdef Q_OS_WIN32
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
return csbi.srWindow.Right - csbi.srWindow.Left + 1;
#else
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
return w.ws_col;
#endif
}
}
}

View File

@ -1,80 +0,0 @@
/*
* 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.
*/
#ifndef HELPDATA_H
#define HELPDATA_H
#include <QMap>
#include "quasarapp_global.h"
namespace QuasarAppUtils{
/**
* @brief Help namespace contains functions for printing help in to console. All Print fucntions automaticly calc width of the console and aligns the text to fit the window.
*/
namespace Help {
/**
* @brief Options this is list of **key-descriptions** pairs of help.
* The **key** is name of the available argument and **description** is description of the available argument.
*
* **Example**:
*
* @code{cpp}
* Options myOptionsList = {{"argument1", "This is test argumetn1 of my application."},
* {"argument2", "This is test argumetn2 of my application."}};
*
* @endcode
*/
typedef QMultiMap<QString, QString> Options;
/**
* @brief Section This is list of the help Sections. The one section it is Title of the section and Help::Options list.
*
* **Example:**
* @code{cpp}
* Options myOptionsList = {{"argument1", "This is test argumetn1 of my application."},
* {"argument2", "This is test argumetn2 of my application."}};
* Section mySections = {{"This Is main section of the help", myOptionsList}};
* QuasarAppUtils::Help::print(mySections);
* @endcode
*/
typedef QMultiMap<QString, Options> Section;
/**
* @brief Charters is wraper of the Section type.
* @warning This type is depricated. Use the Help:Section type.
*/
typedef Section Charters;
/**
* @brief width This method return current width of the cosole window.
* @return width in pxels of the cosole window.
*/
int width();
/**
* @brief print This method print a one options list.
* @param oprionsList This is options list.
*/
void QUASARAPPSHARED_EXPORT print(const Options& oprionsList);
/**
* @brief print This method print all sections of the help.
* @note This is main method for printing helps.
* @param help This is sections list.
*/
void QUASARAPPSHARED_EXPORT print(const Section& help);
/**
* @brief setLineLength sets new length of the help line (width of the console window). If you set this into -1 then the window width will be selected automatically.
* @param newLength This is a new size of the console window.
*/
void QUASARAPPSHARED_EXPORT setLineLength(int newLength);
}
}
#endif // HELPDATA_H

View File

@ -1,18 +0,0 @@
//#
//# 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.
//#
#include "humanreadableobject.h"
namespace QuasarAppUtils{
HumanReadableObject::HumanReadableObject()
{
}
}

View File

@ -1,39 +0,0 @@
//#
//# 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.
//#
#ifndef HUMANREADABLEOBJECT_H
#define HUMANREADABLEOBJECT_H
#include <QString>
#include "quasarapp_global.h"
namespace QuasarAppUtils {
/**
* @brief The HumanReadableObject interface This is simple class that add one virtula method toString.
* All childs object should be override this method.
*/
class QUASARAPPSHARED_EXPORT HumanReadableObject
{
public:
/**
* @brief toString This method convert this object to human readable string.
* @return human readable string of this object.
*/
virtual QString toString() const = 0;
protected:
HumanReadableObject();
};
/**
* @brief iHRO This is short abriviature of the HumanReadableObject class.
*/
typedef HumanReadableObject iHRO;
}
#endif // HUMANREADABLEOBJECT_H

View File

@ -1,128 +0,0 @@
/*
* 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 "isettings.h"
#include <QSettings>
#include <QCoreApplication>
#include "qaglobalutils.h"
namespace QuasarAppUtils {
ISettings::ISettings(SettingsSaveMode mode) {
_mode = mode;
}
ISettings::~ISettings() {
if (_defaultConfig)
delete _defaultConfig;
}
void ISettings::clearCache() {
_cache.clear();
}
QHash<QString, QVariant> &ISettings::settingsMap() {
if (!_defaultConfig)
_defaultConfig = new QHash<QString, QVariant>(defaultSettings());
return *_defaultConfig;
}
SettingsSaveMode ISettings::getMode() const {
return _mode;
}
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!");
if (!_cache.contains(key)) {
QVariant defVal = def;
if (defVal.isNull()) {
defVal = settingsMap().value(key);
}
_cache[key] = getValueImplementation(key, def);
}
return _cache[key];
}
QString ISettings::getStrValue(const QString &key, const QString &def) {
if (def.isEmpty()) {
return getValue(key).toString();
}
return getValue(key, QVariant(def)).toString();
}
void ISettings::resetToDefault() {
auto &defaultConfig = settingsMap();
for (auto it = defaultConfig.begin(); it != defaultConfig.end(); ++it) {
if (!ignoreToRest(it.key()))
setValue(it.key(), defaultConfig.value(it.key()));
}
}
bool ISettings::ignoreToRest(const QString &) const {
return false;
}
void ISettings::sync() {
for (auto it = _cache.begin(); it != _cache.end(); ++it) {
setValueImplementation(it.key(), it.value());
}
return syncImplementation();
}
void ISettings::forceReloadCache() {
auto &defaultConfig = settingsMap();
for (auto it = defaultConfig.begin(); it != defaultConfig.end(); ++it) {
setValue(it.key(), getValueImplementation(it.key(), it.value()));
}
}
void ISettings::setValue(const QString &key, const QVariant &value) {
debug_assert(key.size(), "You can't use the empty key value!");
if (_cache.contains(key) && _cache.value(key) == value) {
return;
}
_cache[key] = value;
emit valueChanged(key, value);
emit valueStrChanged(key, value.toString());
if (_mode == SettingsSaveMode::Auto) {
setValueImplementation(key, value);
}
}
void ISettings::setStrValue(const QString &key, const QString &value) {
setValue(key, value);
}
}

View File

@ -1,230 +0,0 @@
/*
* 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.
*/
#ifndef ISETTINGS_H
#define ISETTINGS_H
#include "qaservice.h"
#include "quasarapp_global.h"
#include <QObject>
#include <QVariant>
class QSettings;
namespace QuasarAppUtils {
/**
* @brief The SettingsSaveMode enum
*/
enum class SettingsSaveMode: quint64 {
/// a settings will be saved on hard disk when called the Settings::setValue method.
Auto,
/// a settings will be saved on hard disk when called the Settings::Sync method.
Manual
};
/**
* @brief The Settings class base interface for implementation settings backends.
* Available implementations:
* Setting (based on QSettings backend)
* @note This is singleton object.
*
* @note The all child classes should be initialized before used.
*
* @code{cpp}
* auto settingsInstance = Setting::initService<Setting>();
* @endcode
*
* @see ISettings::init method.
*
*/
class QUASARAPPSHARED_EXPORT ISettings : public QObject, public Service<ISettings>
{
Q_OBJECT
public:
~ISettings() override;
/**
* @brief getValue This method return the value of the settings.
* @param key This is name of the required settings value.
* @param def This is default value if a value is not finded. If this params will be skipped, then The Settngs model try find default value in the defaultSettings map.
* @return value of a @a key
* @see ISettings::defaultSettings
*/
Q_INVOKABLE QVariant getValue(const QString &key, const QVariant& def = {});
/**
* @brief getStrValue some as getValue but convert result object to QString type.
* @param key This is name of the required settings value.
* @param def This is default value if a value is not finded. If this params will be skipped, then The Settngs model try find default value in the defaultSettings map.
* @return value of a @a key
* @see ISettings::defaultSettings
* @warning If you set a def arguments to empty string then this method will return default value from the defaultSettings map.
*/
Q_INVOKABLE QString getStrValue(const QString &key, const QString& def = {});
/**
* @brief resetToDefault This method reset all settings to default values.
*/
Q_INVOKABLE void resetToDefault();
/**
* @brief ignoreToRest This method should be returns true if the @a key setting is not be reset on the resetToDefault method.
* @param key This is keuy value.
* @return true if the @a key option can't be reset to default.
* The default implementaion alwayes return false.
*/
virtual bool ignoreToRest(const QString& key) const;
/**
* @brief sync This method save all setings data on a hard disk;
*/
void sync();
/**
* @brief forceReloadCache This method force reload settings data from disk.
* @note Cache will be refreshed
*/
void forceReloadCache();
/**
* @brief getMode This method return the current mode of the settings.
* @return the current mode of the settings.
*/
SettingsSaveMode getMode() const;
/**
* @brief setMode This method sets a new value of the settings mode.
* @param mode This is a new value of the settings mode.
*/
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
* @param key This is name of the changed setting.
* @param value This is a new value of the setting
*/
void setValue(const QString &key, const QVariant& value);
/**
* @brief setStrValue This is some as setValue but working with the QString type.
* @param key This is name of the changed setting.
* @param value This is a new value of the setting
*/
void setStrValue(const QString& key, const QString& value);
signals:
/**
* @brief valueChanged This signal when value of the @a key settings changed
* @param key This is name of change setting.
* @param value This is a new value of @a key.
*/
void valueChanged(QString key, QVariant value);
/**
* @brief valueStrChanged some as valueChanged(QString key, QVariant value) but value has ben converted to the QString type.
* @param key This is name of change setting.
* @param value This is a new value of @a key.
*/
void valueStrChanged(QString key, QString value);
protected:
explicit ISettings(SettingsSaveMode mode = SettingsSaveMode::Auto);
/**
* @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:
*
* @code{cpp}
*
QHash<QString, QVariant> SettingsModel::defaultSettings() {
QHash<QString, QVariant> settings;
settings["colorTheme"] = "#ff6b01";
settings["shareName"] = true;
settings["devSettingEnable"] = false;
settings["host"] = "";
settings["APIVersion"] = 2;
return settings;
}
* @endcode
*/
virtual QHash<QString, QVariant> defaultSettings() = 0;
/**
* @brief syncImplementation This method should save all configuration data to the hard drive;
*/
virtual void syncImplementation() = 0;
/**
* @brief getValueImplementation This method will return the value of the settings.
* @param key This is name of the required settings value.
* @param def This is default value if a value is not finded.
* @return value of a @a key
*/
virtual QVariant getValueImplementation(const QString &key, const QVariant& def) = 0;
/**
* @brief setValueImplementation This slot will set a new value for the @a key parameter.
* @param key This is name of the changed setting.
* @param value This is a new value of the setting
*/
virtual void setValueImplementation(const QString key, const QVariant& value) = 0;
/**
* @brief clearCache This method clear all data from cache.
*/
void clearCache();
/**
* @brief settingsMap This method returns initialized settings map.
* Settings map contains pairs with settings key and default value.
* @return initialized settings map.
* @see ISettings::defaultSettings method
*/
QHash<QString, QVariant>& settingsMap();
private:
SettingsSaveMode _mode = SettingsSaveMode::Auto;
QHash<QString, QVariant> _cache;
QHash<QString, QVariant> *_defaultConfig = nullptr;
friend class Service<ISettings>;
};
};
#endif // ISETTINGS_H

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2025 QuasarApp.
* 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.
@ -11,234 +11,22 @@
#include <QCoreApplication>
#include <QTranslator>
#include <QLocale>
#include <QLibraryInfo>
#include <QRegularExpression>
#include <QLocale>
#include <QMap>
using namespace QuasarAppUtils;
bool QuasarAppUtils::Locales::findQmPrivate(const QString &prefix,
QList<QTranslator*> &qmFiles) {
for (const auto &location: std::as_const(_locations)) {
bool Locales::initLocale(const QString& prefix, const QString &locale, QCoreApplication *app, QTranslator *translator){
const auto availableFiles = QDir(location).entryInfoList(
{prefix + ".qm"}, QDir::Files);
QString defaultLocale = QLocale::system().name();
defaultLocale.truncate(defaultLocale.lastIndexOf('_'));
for (const auto &file : availableFiles) {
auto qmFile = new QTranslator();
if(!qmFile->load(file.absoluteFilePath())) {
qWarning() << "Failed to load translation file : "
+ file.absoluteFilePath();
delete qmFile;
continue;
}
if (qmFile->isEmpty()) {
qDebug() << "Translation file is Empty: " +
file.absoluteFilePath();
delete qmFile;
continue;
}
auto language = qmFile->language();
if (language.size() && !language.contains(prefix, Qt::CaseInsensitive)) {
auto message = QString("The target language (%0) and a choosed qm file (%1) "
"is different, Loading will be skiped: ").
arg(language, file.absoluteFilePath());
qDebug() << message;
delete qmFile;
continue;
}
qmFiles += qmFile;
}
if(!locale.isEmpty() && translator->load(QString("%0/%1").arg(prefix, locale))) {
return app->installTranslator(translator);
}
return qmFiles.size();
}
bool QuasarAppUtils::Locales::findQm(QString localePrefix,
QList<QTranslator *> &qmFiles) {
if (localePrefix.size() < 2) {
if (localePrefix.compare('c', Qt::CaseInsensitive) == 0) {
return findQmPrivate("en", qmFiles);
}
if(!translator->load(QString("%0/%1").arg(prefix, defaultLocale))) {
return false;
} else if (localePrefix.size() >= 4) {
return findQmPrivate(localePrefix.replace('-', '_'), qmFiles);
}
return findQmPrivate(localePrefix, qmFiles);
}
void QuasarAppUtils::Locales::installTranslations( QList<QTranslator *> &qmFiles)
{
for (const auto & translator: std::as_const(qmFiles)) {
if (!QCoreApplication::installTranslator(translator)) {
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;
}
}
}
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[locale].size();
}
const QLocale &Locales::currentLocate() {
auto obj = instance();
return obj->currentLocatePrivate();
}
QString Locales::tr(const char *source, const QLocale &locale) {
auto obj = instance();
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) {
auto obj = instance();
return obj->initPrivate(locale, location);
}
bool Locales::initPrivate(const QLocale &locale, 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;
}
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(const QLocale &locale) {
for (const auto & tr :std::as_const(_translations[locale])) {
QCoreApplication::removeTranslator(tr);
}
}
void Locales::addLocationPrivate(const QString &location) {
_locations += location;
}
const QLocale &Locales::currentLocatePrivate() const {
return _currentLocate;
}
void Locales::addLocation(const QString &location) {
auto obj = instance();
obj->addLocationPrivate(location);
}
Locales::~Locales() {
clearCache();
return app->installTranslator(translator);
}

117
locales.h
View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2025 QuasarApp.
* 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.
@ -11,11 +11,6 @@
#include "quasarapp_global.h"
#include <QLocale>
#include <QSet>
#include <QString>
#include <QDir>
class QCoreApplication;
class QTranslator;
@ -23,113 +18,21 @@ namespace QuasarAppUtils {
/**
* @brief The Locales class for parese local files
* **Example :**
* @code{cpp}
* QuasarAppUtils::Locales::init();
* @endcode
*
* @note If you want to add you own location of the qm files then add this into seccond arguments of the Locales::init method.
*
* @code{cpp}
* QuasarAppUtils::Locales::init(QLocale::system(), "myPath");
* @endcode
*
* @note All translations qm files should be named with lower case example : en.qm
*/
class QUASARAPPSHARED_EXPORT Locales : public QObject
class QUASARAPPSHARED_EXPORT Locales
{
Q_OBJECT
public:
Locales() = delete;
/**
* @brief setLocale This method sets locale for application and loaded all translations for this locale.
* @param locale This is new locale.
* @return true if the all ltranstations files loaded successful.
* @brief initLocale init translation of applictaion
* @param prefix - path to folder with qm files. example (/home)
* @param locale - string value of locale. example (en)
* @param app - app core of qt
* @param translator - translator core of qt
* @return return true if locale funded
*/
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.
* @param locale 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 QLocale &locale = QLocale::system(),
const QSet<QString> & location = {});
/**
* @brief addLocation This method add location for qm files. Use This method if you create a own library with translations supports.
* @param location This is a new location of the qm files.
*/
static void addLocation(const QString& location);
/**
* @brief instance This method return pointer to the Locales service.
* @return return pointer to the Locales static object
*/
static Locales *instance();
/**
* @brief currentLocate This method return current locate of applicatuon.
* @return current or last sets locate of applciation.
*/
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.
*/
void sigTranslationChanged();
private:
Locales() = default;
~Locales();
bool setLocalePrivate(const QLocale &locale = QLocale::system(), bool force = false, bool install = true);
bool initPrivate(const QLocale &locale = QLocale::system(),
const QSet<QString> &location = {});
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(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;
QHash<QLocale, QList<QTranslator *>> _translations;
static bool initLocale(const QString& prefix ,const QString &locale, QCoreApplication* app, QTranslator *translator);
};
}

View File

@ -1,90 +0,0 @@
/*
* 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.
*/
#include "optiondata.h"
namespace QuasarAppUtils{
OptionData::OptionData(const QStringList& name,
const QString& arguments,
const QString& description,
const QString& example,
const QString& depricatedMsg,
bool removed) {
setNames(name);
setArguments(arguments);
setDescription(description);
setExample(example);
setDepricatedMsg(depricatedMsg);
_removed = removed;
}
const QStringList &OptionData::names() const {
return _name;
}
void OptionData::setNames(const QStringList &newName) {
_name = newName;
}
const QString &OptionData::description() const {
return _description;
}
void OptionData::setDescription(const QString &newDescription) {
_description = newDescription;
}
const QString &OptionData::example() const {
return _example;
}
void OptionData::setExample(const QString &newExample) {
_example = newExample;
}
const QString &OptionData::arguments() const {
return _arguments;
}
void OptionData::setArguments(const QString &newArguments) {
_arguments = newArguments;
}
const QString &OptionData::depricatedMsg() const {
return _depricatedMsg;
}
void OptionData::setDepricatedMsg(const QString &newDepricatedMsg) {
_depricatedMsg = newDepricatedMsg;
}
bool OptionData::isRemoved() const {
return _removed;
}
bool OptionData::isDepricated() const {
return depricatedMsg().size();
}
Help::Options OptionData::toHelp() const {
QString left = names().join(" / ") + " " + arguments();
QString right = description();
if (example().size()) {
right += " Example: " + example();
}
return {{left, {right}}};
}
bool OptionData::isValid() const {
return names().size();
}
}

View File

@ -1,152 +0,0 @@
/*
* 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.
*/
#ifndef OPTIONDATA_H
#define OPTIONDATA_H
#include "quasarapp_global.h"
#include "helpdata.h"
namespace QuasarAppUtils{
/**
* @brief The OptionData class contains information about one option.
*/
class QUASARAPPSHARED_EXPORT OptionData
{
public:
/**
* @brief OptionData This is main constructor
* @param names This is names list of the option. It is a required argument and cannot be empty.
* @param arguments This is input arguments of this option or help meesage about arguments.
* @param description This is description message of this option.
* @param example This is example of use string.
* @param depricatedMsg This is a message that will be printed as a warning if user will use this option. If you set this argument to empty value then warning message will be ignored and option not be marked asa a depricated. An option will be marked as a depricated when this arguments will not equal empty string.
* @param removed This option show depricatedMsg as a error and force the parseParams method return false. This option will be ignored if the depricatedMsg will be empty.
*/
OptionData(const QStringList& names,
const QString& arguments = "",
const QString& description = "",
const QString& example = "",
const QString& depricatedMsg = "",
bool removed = false);
/**
* @brief name This is name of the option. It is a required argument and cannot be empty.
* @return return name of this option.
*/
const QStringList &names() const;
/**
* @brief description This is description message of this option.
* @return return description of this option.
*/
const QString &description() const;
/**
* @brief example This is example of use string.
* @return return example if use of this option.
*/
const QString &example() const;
/**
* @brief arguments This is input arguments of this option or help meesage about arguments.
* @return return arguments of this option.
*/
const QString &arguments() const;
/**
* @brief depricatedWarning This is a message that will be printed as a warning if user will use this option. If you set this argument to empty value then warning message will be ignored and option not be marked asa a depricated. An option will be marked as a depricated when this arguments will not equal empty string.
* @note if this value is empty the option are not depricated.
* @return warning meessage of the depricated options.
*/
const QString &depricatedMsg() const;
/**
* @brief toHelp This method convert this option into help line.
* The help line have next structure :
*
* Key: {name [arguments]}
* Value: {description examples}
* @return The Help::Options set with one line.
*/
Help::Options toHelp() const;
/**
* @brief isValid This method return true if the option is valid. If option do not contain a name then it is invalid.
* @return true if the option valid else false.
*/
bool isValid() const;
/**
* @brief isRemoved This method return true if the option is removed.
* @return true if option is removed else false.
*/
bool isRemoved() const;
/**
* @brief isDepricated This method return true if this option is depricated.
* @return true if options is depricated else false
*/
bool isDepricated() const;
protected:
/**
* @brief setNames This method sets new value of the option name.
* @param newNames This is a new value of the options name.
* @note see the OptionData::name method.
*/
void setNames(const QStringList &newNames);
/**
* @brief setDescription This method sets new description of this options.
* @param newDescription This is new value of optons description
* @note See the OptionData::description method.
*/
void setDescription(const QString &newDescription);
/**
* @brief setExample This method sets a new example value of this option
* @param newExample This is a new value of the options example.
* @note See the OptionData::example method.
*/
void setExample(const QString &newExample);
/**
* @brief setArguments This method sets new value of the options arguments
* @param newArguments new value of the options arguments
* @note See the OptionData::arguments method.
*/
void setArguments(const QString &newArguments);
/**
* @brief setDepricatedMsg This method sets new value of the depricated warnning message of this option.
* @param newDepricatedMsg This is new value of the depricated message.
* @note See the OptionData::depricatedMsg method.
*/
void setDepricatedMsg(const QString &newDepricatedMsg);
private:
QStringList _name;
QString _description;
QString _example;
QString _arguments;
QString _depricatedMsg;
bool _removed;
};
/**
* @brief OptionsList is Hash map of the OptionData items. Where the key it is group name and value it is option data.
*/
typedef QMultiHash<QString, OptionData> OptionsDataList;
}
#endif // OPTIONDATA_H

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2025 QuasarApp.
* 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.
@ -9,354 +9,65 @@
#include <QVariantMap>
#include <QDebug>
#include <QFileInfo>
#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;
QMap<QString, QString> Params::params = QMap<QString, QString>();
QString Params::appPath = "";
QString Params::appName = "";
Help::Section Params::userHelp = {};
OptionsDataList Params::inputOptions = {};
static QVariantMap params = QVariantMap();
bool Params::isEndable(const QString& key) {
return params.contains(key);
}
void Params::log(const QString &log, VerboseLvl vLvl) {
auto lvl = getVerboseLvl();
if (vLvl <= lvl) {
switch (vLvl) {
case VerboseLvl::Error:
qCritical().noquote() << log;
break;
case VerboseLvl::Warning: {
qWarning().noquote() << log;
break;
}
case VerboseLvl::Debug: {
qDebug().noquote() << log;
break;
}
case VerboseLvl::Info:
default: {
qInfo().noquote() << log;
break;
}
}
void Params::verboseLog(const QString &log) {
if (isEndable("verbose")) {
qDebug() << "verbose log: " + log ;
}
}
VerboseLvl Params::getVerboseLvl() {
return static_cast<VerboseLvl>(getArg("verbose", DEFAULT_VERBOSE_LVL).toInt());
}
bool Params::isDebug() {
return getVerboseLvl() >= VerboseLvl::Debug;
}
bool Params::isDebugBuild() {
#ifdef QT_DEBUG
return true;
#else
return false;
#endif
}
void Params::showHelp() {
if (inputOptions.size() > 1) {
showHelpForInputOptions();
} else {
Help::print(userHelp);
}
}
void Params::showHelpForInputOptions() {
Help::print(getHelpOfInputOptions());
}
Help::Section Params::getHelpOfInputOptions() {
if (inputOptions.size() <= 1 ) {
return {};
}
Help::Options help;
for (const auto &optionData: std::as_const(inputOptions) ) {
help.unite(optionData.toHelp());
}
return Help::Section{{"Information about using options", help}};
}
const Help::Section &Params::getHelp() {
return userHelp;
}
const QMap<QString, QString>& Params::getUserParamsMap() {
return params;
}
void Params::clearParsedData() {
bool Params::parseParams(int argc, char *argv[]) {
params.clear();
appPath = "";
appName = "";
}
QString Params::getCurrentExecutable() {
return getCurrentExecutableDir() + "/" + appName;
}
QString Params::getCurrentExecutableDir() {
return appPath;
}
OptionsDataList Params::availableArguments() {
return OptionsDataList{
{
"Base Options",
OptionData{
{"-verbose"}, "(level 1 - 3)", "Shows debug log"
}
},
{
"Base Options",
OptionData{
{"-fileLog"}, "(path to file)", "Sets path of log file. Default it is path to executable file with suffix '.log'"
}
}
};
}
int Params::size() {
return params.size();
}
bool Params::optionsForEach(const QStringList &paramsArray,
const OptionsDataList& availableOptions) {
for (int i = 0 ; i < paramsArray.size(); ++i) {
QStringList virtualOptionsList = paramsArray[i].split('=');
if (virtualOptionsList.size() > 1) {
return optionsForEach(virtualOptionsList, availableOptions);
}
auto optionData = availableOptions.value(paramsArray[i], {{}});
if (!checkOption(optionData, paramsArray[i])) {
return false;
}
inputOptions.insert(paramsArray[i], optionData);
if (paramsArray[i][0] == '-') {
if (i < (paramsArray.size() - 1) && paramsArray[i + 1][0] != '-') {
params[paramsArray[i].mid(1)] = paramsArray[i + 1];
i++;
} else {
qCritical() << "Missing argument for " + paramsArray[i];
return false;
}
} else {
params[paramsArray[i]] = "";
}
}
return true;
}
bool Params::parseParams(const int argc, const char *argv[], const OptionsDataList& options) {
QStringList params;
for (int i = 1; i < argc; i++) {
params.push_back(argv[i]);
}
return parseParams(params, options);
}
bool Params::parseParams(int argc, char *argv[], const OptionsDataList& options) {
return parseParams(argc, const_cast<const char**>(argv), options);
}
bool Params::parseParams(const QStringList &paramsArray, const OptionsDataList &options) {
params.clear();
OptionsDataList availableOptions;
parseAvailableOptions(OptionsDataList{}.unite(options).unite(availableArguments()),
&availableOptions,
&userHelp);
#ifdef Q_OS_WIN
char buffer[MAX_PATH];
memset(buffer, 0, sizeof buffer);
GetModuleFileNameA(nullptr, buffer, MAX_PATH);
appPath = QFileInfo(buffer).absolutePath();
appName = QFileInfo(buffer).fileName();
#endif
#ifdef Q_OS_LINUX
char path[2048];
memset(path, 0, sizeof path);
if (readlink("/proc/self/exe", path, 2048) < 0) {
qCritical() << "parseParams can't get self path!";
return false;
}
appPath = QFileInfo(path).absolutePath();
appName = QFileInfo(path).fileName();
#endif
#ifdef Q_OS_DARWIN
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
if (!appPath.size()) {
return false;
}
if (!optionsForEach(paramsArray, availableOptions)) {
return false;
}
printWorkingOptions();
return true;
}
void Params::printWorkingOptions() {
qDebug() << "--- Working options table start ---";
QMap<QString, QString>::const_iterator iter = params.constBegin();
while (iter != params.constEnd()) {
QString row = QString{"Option[%0]"}.arg(iter.key());
QString value = iter.value();
if (!value.isEmpty()) {
row += QString{": %1"}.arg(value);
}
qDebug() << row;
++iter;
}
qDebug() << "--- Working options table end ---";
}
bool Params::checkOption(const OptionData& optionData, const QString& rawOptionName) {
#ifndef QA_ALLOW_NOT_SUPPORTED_OPTIONS
if (!optionData.isValid()) {
qCritical() << QString("The '%0' option not exists!"
" You use wrong option name,"
" please check the help before run your commnad.").
arg(rawOptionName);
return false;
}
params ["appPath"] = QFileInfo(buffer).absolutePath();
#else
Q_UNUSED(rawOptionName);
char path[2048];
readlink("/proc/self/exe", path, 2048);
params ["appPath"] = QFileInfo(path).absolutePath();
#endif
if (optionData.isDepricated()) {
if (!getStrArg("appPath").size()) {
return false;
}
if (optionData.isRemoved()) {
qCritical() << optionData.depricatedMsg();
return false;
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '-' && i ) {
if (i < (argc - 1) && argv[i + 1][0] != '-') {
params[&(argv[i][1])] = argv[i + 1];
i++;
} else {
qWarning() << "Missing argument for " + QString(argv[i]) ;
}
} else {
params[argv[i]] = "";
}
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());
}
return true;
}
void Params::parseAvailableOptions(const OptionsDataList &availableOptionsListIn,
OptionsDataList *availableOptionsListOut,
Help::Section *helpOut) {
if (!(availableOptionsListOut && helpOut))
return;
helpOut->clear();
QHash<QString, Help::Options> options;
for (auto it = availableOptionsListIn.begin(); it != availableOptionsListIn.end(); ++it) {
if (availableOptionsListOut) {
for (const auto &name : std::as_const(it.value().names())) {
availableOptionsListOut->insert(name, it.value());
}
}
if (helpOut) {
options[it.key()].unite(it.value().toHelp());
}
}
for (auto it = options.begin(); it != options.end(); ++it) {
helpOut->insert(it.key(), it.value());
}
QString Params::getStrArg(const QString& key) {
return params.value(key, "").toString();
}
QString Params::getArg(const QString& key,const QString& def) {
return params.value(key, def);
}
void Params::setArg(const QString &key, const QString &val) {
params.insert(key, val);
}
void Params::setEnable(const QString &key, bool enable) {
if (enable) {
params.insert(key, "");
} else {
params.remove(key);
}
QVariant Params::getArg(const QString& key) {
return params.value(key, "");
}

242
params.h
View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2025 QuasarApp.
* 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.
@ -8,253 +8,55 @@
#ifndef PARAMS_H
#define PARAMS_H
#include <QMap>
#include <QVariant>
#include "quasarapp_global.h"
#include "helpdata.h"
#include "optiondata.h"
namespace QuasarAppUtils {
/**
* @brief The VerboseLvl enum uses for sets log level.
* @brief The Params class for parese app params
*/
enum VerboseLvl {
/// Error message. This logs will marked as a **Error** and printing if the verbose lvl >= 0
Error = 0x0,
/// Warning message. This logs will marked as a **Warning** and printing if the verbose lvl >= 1
Warning = 0x1,
/// General information. This logs will marked as a **Info** and and printing if the verbose lvl >= 2.
Info = 0x2,
/// Debug message. This logs will marked as a **Debug** and printing if the verbose lvl >= 3
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.
* This Class support next comandline arguments.
* * **-verbose** (level 1 - 3) Shows debug log
* * **-fileLog** (path to file) Sets path of log file. Default it is path to executable file with suffix '.log'
*
* ### Usage
*
* ```cpp
#include <quasarapp.h>
if (!QuasarAppUtils::Params::parseParams(argc, argv)) {
QuasarAppUtils::Params::log("Warning message", QuasarAppUtils::Warning);
QuasarAppUtils::Params::showHelp();
exit(0);
}
```
*/
class QUASARAPPSHARED_EXPORT Params
{
public:
Params() = delete;
/**
* @brief parseParams Parse input data of started application.
* @param argc Count of arguments.
* @param argv Array of arguments.
* @param options This is list of the available options for parse. See the OptionData class for more inforamtion.
* If you skip thi argument then QuasarAppLib will not check input options.
* @return true if all arguments read successful else false.
* @brief parseParams - parase input data of started application
* @param argc - count of arguments
* @param argv - arrat of arguments
* @return true if all arguments read else false
*/
static bool parseParams(const int argc, const char *argv[], const OptionsDataList& options = {});
static bool parseParams(int argc, char *argv[]);
/**
* @brief parseParams Parse input data of started application.
* @param argc Count of arguments.
* @param argv Array of arguments.
* @param options This is list of the available options for parse. See the OptionData class for more inforamtion.
* If you skip thi argument then QuasarAppLib will not check input options.
* @return true if all arguments read successful else false.
* @brief getStrArg - get string value of key
* @param key
* @return string value of argument
*/
static bool parseParams(int argc, char *argv[], const OptionsDataList& options = {});
static QString getStrArg(const QString& key);
/**
* @brief parseParams Parse input data of started application.
* @param paramsArray Arguments.
* @param options This is list of the available options for parse. See the OptionData class for more inforamtion.
* If you skip thi argument then QuasarAppLib will not check input options.
* @return true if all arguments read successful else false.
* @brief getArg - get string value of key
* @param key
* @return string value of argument
*/
static bool parseParams(const QStringList& paramsArray, const OptionsDataList& options = {});
static QVariant getArg(const QString& key);
/**
* @brief getArg return string value of a @a key if key is exits else return a @a def value.
* If a @a def value not defined retunr empty string.
* @param key This is key of a console argument.
* @param def This is Default value. If key not exits This function will return a default value.
* @return a string value of argument.
*/
static QString getArg(const QString& key, const QString &def = {});
/**
* @brief setArg sets a new value of a @a key.
* @param key This is a name of sets option.
* @param val This is a new value of the @a key.
*/
static void setArg(const QString& key, const QString& val);
/**
* @brief setArg This method sets boolean value of key.
* @param key This is name of the console option.
* @param enable New value of key.
* @note For check is enable @a key argument use the Params::isEndable method.
*/
static void setEnable(const QString& key, bool enable);
/**
* @brief isEndable This method check if enable a @a key argument.
* @param key This is name of the validate arguments
* @return true if argument enabled.
* @brief isEndable - check if enable argument of key
* @param key
* @return true if argument enabled
*/
static bool isEndable(const QString& key);
/**
* @brief log This method print @a log text on console.
* @param log This is printed text message.
* @param vLvl This is verbose level of message, for get more information see the QuasarAppUtils::VerboseLvl enum.
* @note All messages will be printed according to the current verbose setting.
* @note The verbose level sets by verbose option on console.
* @brief verboseLog - print text on console if the flag "vergose" is enabled
* @param log - printed text
*/
[[deprecated("Use QALogger and qt debug functions(qDebug, qInfo, qError...)")]]
static void log(const QString& log, VerboseLvl vLvl = VerboseLvl::Debug);
/**
* @brief getVerboseLvl This method return the verbose log level.
* @return verbose log lvl.
*/
static VerboseLvl getVerboseLvl();
/**
* @brief isDebug This method return true if the application verbose level >= VerboseLvl::Debug.
* @return true if a verbose level >= VerboseLvl::Debug
*/
static bool isDebug();
/**
* @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();
/**
* @brief size This method return count of the all input arguments.
* @return size of all params array.
*/
static int size();
/**
* @brief showHelp This method shows all help message.
*/
static void showHelp();
/**
* @brief showHelpForInputOptions This method show help for each input option.
* @note Befor using of this method invoke the parseParams method. This is needed for generate the help message.
*
* **Example:**
*
* ```bash
* myTool help option1 -option2 argumets
* ```
*/
static void showHelpForInputOptions();
/**
* @brief getHelpOfInputOptions This method return help abut input options only. Exept help and h options.
* @return help abut input options only. Exept help and h options.
*/
static Help::Section getHelpOfInputOptions();
/**
* @brief getHelp This method return options help page.
* @note Befor using of this method invoke the parseParams method. This is needed for generate the help message.
* @return help of available options.
*/
static const Help::Section& getHelp();
/**
* @brief getUserParamsMap This method return const reference to the parsed arguments map.
* @return A map object with parsed arguments.
*/
static const QMap<QString, QString> &getUserParamsMap();
/**
* @brief clearParsedData This method clear all parsed data.
*/
static void clearParsedData();
/**
* @brief getCurrentExecutable This method return path to the current executable.
* @return path to current executable.
*/
static QString getCurrentExecutable();
/**
* @brief getCurrentExecutableDir This method return a path to a folder with the current executable.
* @return path of the folder with current executable.
*/
static QString getCurrentExecutableDir();
/**
* @brief availableArguments This method return list of the available arguments of QuasarAppLibrary
* @return list of the available arguments
*/
static OptionsDataList availableArguments();
private:
static bool optionsForEach(const QStringList& paramsArray,
const OptionsDataList &availableOptions);
/**
* @brief Traverse @a params and output its content (all the working
* options) to stdout in the form of option-value groups at the
* debug verbose level (-verbose 3).
*/
static void printWorkingOptions();
/**
* @brief checkOption return tru if the option is supported
* @param option checked option
* @return true if option is supported
*/
static bool checkOption(const OptionData &option, const QString &rawOptionName);
/**
* @brief parseAvailableOptions This is private method for parsing availabel options.
* @param availableOptionsListIn input data of the available options.
* @param availableOptionsListOut hash of available options wher key it options name and value it is options data
* @param helpOut This is help object that generated from the
*/
static void parseAvailableOptions(const OptionsDataList& availableOptionsListIn,
OptionsDataList* availableOptionsListOut,
Help::Section* helpOut);
static QMap<QString, QString> params;
static OptionsDataList inputOptions;
static Help::Section userHelp;
static QString appPath;
static QString appName;
static void verboseLog(const QString& log);
};
}

View File

@ -1,29 +0,0 @@
/*
* 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 "qaglobalutils.h"
#include <limits>
template<class NUM>
void gen(int size, QByteArray &result) {
for (; size > 0; size -= sizeof(NUM)) {
NUM random = (rand() * rand()) % std::numeric_limits<NUM>::max();
result.insert(0, reinterpret_cast<char*>(&random), sizeof(random));
}
}
// to do. The random function should generate 4 bit numbers anywhere except last number
void randomArray(int size, QByteArray &result) {
if (size % sizeof(unsigned long long) == 0) {
gen<unsigned long long>(size, result);
} else if (size % sizeof(unsigned int) == 0) {
gen<unsigned int>(size, result);
} else if (size % sizeof(unsigned short) == 0) {
gen<unsigned short>(size, result);
} else {
gen<unsigned char>(size, result);
}
}

View File

@ -1,159 +0,0 @@
/*
* 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.
*/
#ifndef QU_GLOBAL_UTILS_H
#define QU_GLOBAL_UTILS_H
#include <type_traits>
#include <typeinfo>
#include <QByteArray>
#include "QtGlobal"
#include "quasarapp_global.h"
template <typename T>
constexpr inline T operator | (T lhs, T rhs)
{
static_assert(std::is_enum<T>::value,
"template parameter is not an enum type");
return static_cast<T>(static_cast<int>(lhs) | static_cast<int>(rhs));
}
template <typename T>
constexpr inline T operator & (T lhs, T rhs)
{
static_assert(std::is_enum<T>::value,
"template parameter is not an enum type");
return static_cast<T>(static_cast<int>(lhs) & static_cast<int>(rhs));
}
template <typename T>
constexpr inline T operator >> (T lhs, T rhs)
{
static_assert(std::is_enum<T>::value,
"template parameter is not an enum type");
return static_cast<T>(static_cast<int>(lhs) >> static_cast<int>(rhs));
}
template <typename T>
constexpr inline T operator << (T lhs, T rhs)
{
static_assert(std::is_enum<T>::value,
"template parameter is not an enum type");
return static_cast<T>(static_cast<int>(lhs) << static_cast<int>(rhs));
}
template <typename T>
constexpr inline T operator ~ (T lhs)
{
static_assert(std::is_enum<T>::value,
"template parameter is not an enum type");
return static_cast<T>(~static_cast<int>(lhs));
}
template <typename T>
constexpr inline T operator ^ (T lhs, T rhs)
{
static_assert(std::is_enum<T>::value,
"template parameter is not an enum type");
return static_cast<T>(static_cast<int>(lhs) ^ static_cast<int>(rhs));
}
template<class T>
/**
* @brief static_type_hash_32 This function return hash code of the class T.
* For get more information see the std [documentation](https://en.cppreference.com/w/cpp/types/type_info/hash_code).
* @note This method will create a T object on stack, so if you have a alredy created object use the static_type_hash_32(const T&) function.
* @return uint32_t hash code of the class T
*/
uint32_t static_type_hash_32() noexcept {
return typeid (T).hash_code();
};
template<class T>
/**
* @brief static_type_hash_16 This function return hash code of the class T.
* For get more information see the std [documentation](https://en.cppreference.com/w/cpp/types/type_info/hash_code).
* @note This method will create a T object on stack, so if you have a alredy created object use the static_type_hash_16(const T&) function.
* @return uint16_t hash code of the class T
*/
uint16_t static_type_hash_16() noexcept {
return typeid (T).hash_code() % 0xFFFF;
};
template<class T>
/**
* @brief static_type_hash_8 This function return hash code of the class T.
* For get more information see the std [documentation](https://en.cppreference.com/w/cpp/types/type_info/hash_code).
* @note This method will create a T object on stack, so if you have a alredy created object use the static_type_hash_8(const T&) function.
* @return uint8_t hash code of the class T
*/
uint8_t static_type_hash_8() noexcept {
return typeid (T).hash_code() % 0xFF;
};
template<class T>
/**
* @brief static_type_hash_32 This function return hash code of a T type using @a object.
* @param object This is object of the T type using for generate hash.
* @return uint32_t hash code of the class T
*/
uint32_t static_type_hash_32(T& object) noexcept {
return typeid (object).hash_code();
};
template<class T>
/**
* @brief static_type_hash_16 This function return hash code of a T type using @a object.
* @param object This is object of the T type using for generate hash.
* @return uint16_t hash code of the class T
*/
uint16_t static_type_hash_16(T& object) noexcept {
return typeid (object).hash_code() % 0xFFFF;
};
template<class T>
/**
* @brief static_type_hash_8 This function return hash code of a T type using @a object.
* @param object This is object of the T type using for generate hash.
* @return uint8_t hash code of the class T
*/
uint8_t static_type_hash_8(T& object) noexcept {
return typeid (object).hash_code() % 0xFF;
};
/// @brief H_8 This is short wraper of the static_type_hash_8 fucntion.
#define H_8 static_type_hash_8
/// @brief H_16 This is short wraper of the static_type_hash_16 fucntion.
#define H_16 static_type_hash_16
/// @brief H_32 This is short wraper of the static_type_hash_32 fucntion.
#define H_32 static_type_hash_32
#define debug_assert(C, M) Q_ASSERT(C && M)
/**
* @brief randomArray This function return random arrat with size @a size
* @param size This is size of needed array.
* @param result This is result value of generated array.
*/
void QUASARAPPSHARED_EXPORT randomArray(int size, QByteArray &result);
#endif // GLOBAL_H

View File

@ -1,114 +0,0 @@
/*
* 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;
}
}

View File

@ -1,66 +0,0 @@
/*
* 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

View File

@ -1,53 +0,0 @@
/*
* 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

View File

@ -1,99 +0,0 @@
/*
* 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
}

View File

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

View File

@ -1,35 +0,0 @@
/*
* 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

View File

@ -1,7 +0,0 @@
/*
* 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.
*/

View File

@ -1,159 +0,0 @@
/*
* 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.
*/
#ifndef QASERVICE_H
#define QASERVICE_H
#include <memory>
#include <utility>
namespace QuasarAppUtils {
/**
* @brief The Service class is a template class for creating a singleton services objects.
* This is manual control wrapper. You should be manually initializing your service object and manually deinitializing.
* If you don't destroy your service, then service object will be automatically destroyed when application will be closed.
* @warning If service was destroyed automatically, then destructor of your base class will be not invoked. Use The deinit method for this.
* @todo Remove the template Base class. Instead, it needs to use a general inherit paradigm
*
* **Examples**
*
* **Create a service class**
*
* @code{cpp}
*
* #include <qaservice.h>
*
* class MyService: public QuasarAppUtils::Service<MyService> {\
* // some implementation
* };
*
* @endcode
*
* **Initialise a service object**
*
* @code{cpp}
*
* #include <MyService.h>
*
* // initialise service
* MyService* serviceInstance = MyService::initService();
*
* // get service instance.
* serviceInstance = MyService::instance();
*
* // remove service instance object.
* MyService::deinitService();
*
* @endcode
*
*
* Or you can use the autoInstance method for initialize instance object if not exists.
* @note This method try initialize base instance object use default construct.
*
* @code{cpp}
*
* #include <MyService.h>
*
* // initialise service
* MyService* serviceInstance = MyService::autoInstance();
*
* @endcode
*/
template<class Base>
class Service
{
public:
Service() {};
/**
* @brief initService This method initialize the @a Base object as a service.
* @param args This is argumets of a constructo of the @a Base class.
* @return instance pointer. If the service alredy initialized then return pointer to current service object.
* @see instance
* @see deinitService
* @see autoInstance
*/
static inline std::unique_ptr<Base>& initService() {
auto& val = instancePrivat();
if(!val) {
val.reset(new Base());
}
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.
* @return pointerer to current service object if service initialized else nullptr.
* @see initService
* @see deinitService
* @see autoInstance
*/
static Base* instance() {
return instancePrivat().get();
}
/**
* @brief autoInstance This method return pointerer to current service object and if it is not inited try to initialize it use default constructor.
* @return pointerer to current service object if service initialized else nullptr.
* @see instance
*/
static Base* autoInstance() {
auto& val = instancePrivat();
if (!val) {
initService();
}
return val.get();
}
/**
* @brief deinitService This is distructor method for the service.
* @note do nothink if this object alredy distroyed.
* @see instance
* @see initService
* @see autoInstance
*/
static void deinitService() {
auto& val = instancePrivat();
if(val) {
val.release();
}
}
private:
static inline std::unique_ptr<Base>& instancePrivat() {
static std::unique_ptr<Base> instance = nullptr;
return instance;
}
};
}
#endif // QASERVICE_H

View File

@ -1,10 +1,11 @@
/*
* Copyright (C) 2018-2025 QuasarApp.
* 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.
*/
#include "quasarapp.h"

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2025 QuasarApp.
* 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.
@ -11,12 +11,11 @@
#include "params.h"
#include "locales.h"
#include "settings.h"
#include "qaplatformutils.h"
/**
* @brief The QuasaraAppUtils class
* This lib include base functions for the all applications of QuasarApp group.
* All methods of the Quasar AppUtils is static.
* this lib include base functions for the all applications of QuasarApp group.
* all methods of the Quasar AppUtils is static
*/
namespace QuasarAppUtils{

View File

@ -3,7 +3,7 @@
#include <QtCore/qglobal.h>
#if defined(QUASARAPP_LIBRARY)
#if defined(QUASARAAPP_LIBRARY)
# define QUASARAPPSHARED_EXPORT Q_DECL_EXPORT
#else
# define QUASARAPPSHARED_EXPORT Q_DECL_IMPORT

View File

@ -1,81 +1,45 @@
/*
* Copyright (C) 2021-2025 QuasarApp.
* 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.
*/
#include "settings.h"
#include <QSettings>
#include <QCoreApplication>
#include <QDebug>
namespace QuasarAppUtils {
using namespace QuasarAppUtils;
Settings::Settings() {
auto name = QCoreApplication::applicationName();
auto company = QCoreApplication::organizationName();
if (name.isEmpty()) {
name = "QuasarAppUtils";
}
if (company.isEmpty()) {
company = "QuasarApp";
}
_settings = new QSettings(QSettings::NativeFormat, QSettings::Scope::UserScope, company, name);
_settings = new QSettings();
}
void Settings::syncImplementation() {
return _settings->sync();
Settings *Settings::get() {
static Settings* res = new Settings();
return res;
}
QVariant Settings::getValueImplementation(const QString &key, const QVariant &def) {
if (isBool(key)) {
return _settings->value(key, def).toBool();
}
const Settings *Settings::getConst() {
static Settings* res = new Settings();
return res;
}
QVariant Settings::getValue(const QString &key, const QVariant &def) {
return _settings->value(key, def);
}
void Settings::setValueImplementation(const QString key, const QVariant &value) {
return _settings->setValue(key, value);
QString Settings::getStrValue(const QString &key, const QString &def) {
return getValue(key, QVariant(def)).toString();
}
bool Settings::ignoreToRest(const QString &) const {
return false;
}
void Settings::setValue(const QString key, const QVariant &value) {
_settings->setValue(key, value);
QHash<QString, QVariant> Settings::defaultSettings() {
return {};
}
bool Settings::isBool(const QString &) const {
return false;
}
const QSet<QString> &Settings::boolOptions() const
{
return _boolOptions;
}
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();
}
emit valueChanged(key, value);
emit valueStrChanged(key, value.toString());
}
void Settings::setStrValue(const QString &key, const QString &value) {
setValue(key, value);
}

View File

@ -1,106 +1,78 @@
/*
* Copyright (C) 2021-2025 QuasarApp.
* 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.
*/
#ifndef SETTINGS_H
#define SETTINGS_H
#include "quasarapp_global.h"
#include "isettings.h"
#include <QSet>
#include <QObject>
#include <QVariant>
class QSettings;
namespace QuasarAppUtils {
/**
* @brief The Settings class This is wraper of the QSettings object.
*
* Example of initialisation :
*
* @code{cpp}
* auto settingsInstance = QuasarAppUtils::Setting::initService();
*
* // on any another site you can use the instance method for get settings instance object.
* auto settingsInstance = QuasarAppUtils::Setting::instance();
*
* // and you can destroy setting object if they are not needed anymore
* QuasarAppUtils::Setting::deinitService();
* @endcode
*
* **Or** you can use the Settings::autoInstance method.
*
* @code{cpp}
* auto settingsInstance = QuasarAppUtils::Setting::autoInstance();
* @endcode
*
* @see Settings::init
* @brief The Settings class - singleton for QSettings
*/
class QUASARAPPSHARED_EXPORT Settings: public ISettings
class QUASARAPPSHARED_EXPORT Settings : public QObject
{
Q_OBJECT
public:
Settings();
// ISettings interface
/**
* @brief boolOptions returns current map with keys that has a bool type.
* @return current map with keys that has a bool type
* @see Settings::setBoolOptions
* @see Settings::isBool
*/
const QSet<QString> &boolOptions() const;
/**
* @brief setBoolOptions This method sets new map of the boolean options.
* @param newBoolOptions This is new map of the boolean options.
* @see Settings::boolOptions
* @see Settings::isBool
*/
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;
QVariant getValueImplementation(const QString &key, const QVariant &def) override;
void setValueImplementation(const QString key, const QVariant &value) override;
bool ignoreToRest(const QString &) const override;
QHash<QString, QVariant> defaultSettings() override;
/**
* @brief isBool This method should be return true if the key's type is bool.
* This is needed because QVariant will be converted alvays to true value in a qml code.
* @param key This is key of checks setting.
* @return true if the key is boolean variable.
* The default implementation check key in the inner map.
*
* @see Settings::setBoolOptions
* @see Settings::boolOptions
*/
virtual bool isBool(const QString& key) const;
void setGroup(const QString&);
private:
QSettings *_settings = nullptr;
QSet<QString> _boolOptions;
};
explicit Settings();
QSettings *_settings;
public:
/**
* @brief get
* @return object of all settings app;
*/
static Settings* get();
/**
* @brief get
* @return const object of all settings app;
*/
static const Settings* getConst();
/**
* @brief getValue
* @param key - key of value
* @param def - default value if is value not finded
* @return value of key
*/
QVariant getValue(const QString &key, const QVariant& def);
/**
* @brief getStrValue some as getValue but work with QString
*/
QString getStrValue(const QString &key, const QString& def);
public slots:
/**
* @brief setValue - set new value of key
* @param key - key pf settings
* @param value - new value
*/
void setValue(const QString key, const QVariant& value);
/**
* @brief setStrValue - some as setValue< but use QString
*/
void setStrValue(const QString& key, const QString& value);
signals:
void valueChanged(QString key, QVariant value);
void valueStrChanged(QString key, QString value);
};
} ;
}
#endif // SETTINGS_H

View File

@ -1,32 +0,0 @@
/*
* 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 "isettings.h"
#include "settingslistner.h"
namespace QuasarAppUtils {
SettingsListner::SettingsListner() {
auto settings = ISettings::instance();
if (settings) {
auto listner = [this](QString key, QVariant val){
this->handleSettingsChanged(key, val);
};
_listnerConnection = QObject::connect(settings,
&ISettings::valueChanged,
listner);
}
}
SettingsListner::~SettingsListner() {
QObject::disconnect(_listnerConnection);
}
}

View File

@ -1,59 +0,0 @@
/*
* 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.
*/
#ifndef SETTINGSLISTNER_H
#define SETTINGSLISTNER_H
#include <QString>
#include <QVariant>
#include "quasarapp_global.h"
namespace QuasarAppUtils {
/**
* @brief The SettingsListner class is listner of the ISettings global object.
* The SettingsListner class is abstrct class and contains only one method for hendling settings changes.
*
*
* ### Example of use :
*
* @code{cpp}
* class MyClass : protected QuasarAppUtils::SettingsListner {
* protected:
* void handleSettingsChanged(const QString& key, const QVariant& value) override {
*
* if (key == "shareName") {
setSessinon(static_cast<long long >(rand()) * rand());
}
* }
*
* };
* @endcode
* @see ISettings
*/
class QUASARAPPSHARED_EXPORT SettingsListner
{
public:
SettingsListner();
virtual ~SettingsListner();
protected:
/**
* @brief handleSettingsChanged This method will be invoked when settings of application has bean changed.
* @param key This is key of a changed settings.
* @param value This is a new value of a changed settings.
*/
virtual void handleSettingsChanged(const QString& key,
const QVariant& value) = 0;
private:
QMetaObject::Connection _listnerConnection;
};
}
#endif // SETTINGSLISTNER_H

View File

@ -1,18 +0,0 @@
//#
//# 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.
//#
#include "validableobject.h"
namespace QuasarAppUtils{
ValidableObject::ValidableObject()
{
}
}

View File

@ -1,35 +0,0 @@
//#
//# 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.
//#
#ifndef VALIDABLEOBJECT_H
#define VALIDABLEOBJECT_H
namespace QuasarAppUtils{
/**
* @brief The ValidableObject class is Base interface for all object that can be checked to valid.
*/
class ValidableObject
{
public:
ValidableObject();
/**
* @brief isValid This method return true if the object is valid else false.
* @return true if the object is valid else false.
*/
virtual bool isValid() const = 0;
};
/**
* @brief iVO This is short abriviature of the ValidableObject class.
*/
typedef ValidableObject iVO;
}
#endif // VALIDABLEOBJECT_H