mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-22 06:08:07 +00:00
Compare commits
8 commits
master
...
6.0.0-Call
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de99f1f69a | ||
|
|
6b02ebed39 | ||
|
|
490f5cdca1 | ||
|
|
fb786c2a9d | ||
|
|
23e32d1953 | ||
|
|
d025aaaeec | ||
|
|
faeed359fb | ||
|
|
1e82f48839 |
3871 changed files with 14328 additions and 175183 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
|
@ -52,12 +52,3 @@ linphone.spec
|
||||||
# VSCode
|
# VSCode
|
||||||
linphone60*.log
|
linphone60*.log
|
||||||
linphone61*.log
|
linphone61*.log
|
||||||
linphone62*.log
|
|
||||||
|
|
||||||
# QT Creator
|
|
||||||
*.cflags
|
|
||||||
*.config
|
|
||||||
*.creator
|
|
||||||
*.cxxflags
|
|
||||||
*.files
|
|
||||||
*.includes
|
|
||||||
171
.gitlab-ci-files/linux-desktop-ubuntu-2004.yml
Normal file
171
.gitlab-ci-files/linux-desktop-ubuntu-2004.yml
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
.factorize_ubuntu2004: &docker_image_platform_and_runner_tag
|
||||||
|
tags: [ "docker" ]
|
||||||
|
image: gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-ubuntu-20-04-lts:$UBUNTU_2004_IMAGE_VERSION
|
||||||
|
|
||||||
|
ubuntu2004-ninja-gcc:
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $DOCKER_UPDATE == null && $SKIP_LINUX == null
|
||||||
|
variables:
|
||||||
|
CMAKE_GENERATOR: Ninja
|
||||||
|
CMAKE_OPTIONS: -DENABLE_PQCRYPTO=ON
|
||||||
|
CC: gcc
|
||||||
|
CXX: g++
|
||||||
|
extends: .linux-desktop
|
||||||
|
<<: *docker_image_platform_and_runner_tag
|
||||||
|
|
||||||
|
|
||||||
|
#################################################
|
||||||
|
# Nightly
|
||||||
|
#################################################
|
||||||
|
|
||||||
|
ubuntu2004-makefile-gcc:
|
||||||
|
rules:
|
||||||
|
- !reference [.rules-merge-request-manual, rules]
|
||||||
|
- if: $NIGHTLY_MASTER
|
||||||
|
variables:
|
||||||
|
CMAKE_GENERATOR: Unix Makefiles
|
||||||
|
CMAKE_OPTIONS: -DENABLE_PQCRYPTO=ON
|
||||||
|
CC: gcc
|
||||||
|
CXX: g++
|
||||||
|
ADDITIONAL_BUILD_OPTIONS: -j$MAKEFILE_JOBS
|
||||||
|
extends: .linux-desktop
|
||||||
|
<<: *docker_image_platform_and_runner_tag
|
||||||
|
|
||||||
|
ubuntu2004-ninja-clang:
|
||||||
|
rules:
|
||||||
|
- !reference [.rules-merge-request-manual, rules]
|
||||||
|
- if: $NIGHTLY_MASTER
|
||||||
|
variables:
|
||||||
|
CMAKE_OPTIONS: -DENABLE_DOC=ON -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=ON
|
||||||
|
CMAKE_GENERATOR: Ninja
|
||||||
|
CC: clang
|
||||||
|
CXX: clang++
|
||||||
|
extends: .linux-desktop
|
||||||
|
allow_failure: true
|
||||||
|
<<: *docker_image_platform_and_runner_tag
|
||||||
|
|
||||||
|
ubuntu2004-ninja-clang-small:
|
||||||
|
rules:
|
||||||
|
- !reference [.rules-merge-request-manual, rules]
|
||||||
|
- if: $NIGHTLY_MASTER
|
||||||
|
variables:
|
||||||
|
CMAKE_OPTIONS: -DENABLE_VIDEO=NO -DENABLE_ADVANCED_IM=NO -DENABLE_DB_STORAGE=NO -DENABLE_PQCRYPTO=OFF
|
||||||
|
allow_failure: true
|
||||||
|
extends: ubuntu2004-ninja-clang
|
||||||
|
|
||||||
|
ubuntu2004-makefile-gcc:
|
||||||
|
rules:
|
||||||
|
- !reference [.rules-merge-request-manual, rules]
|
||||||
|
- if: $NIGHTLY_MASTER
|
||||||
|
- if: $DEPLOY_PLUGINS
|
||||||
|
variables:
|
||||||
|
CMAKE_OPTIONS: -DLINPHONE_BUILDER_SIGNING_IDENTITY=$GPG_SIGNING_KEYID -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=ON
|
||||||
|
CMAKE_GENERATOR: Unix Makefiles
|
||||||
|
CC: gcc
|
||||||
|
CXX: g++
|
||||||
|
ADDITIONAL_BUILD_OPTIONS: -j$MAKEFILE_JOBS
|
||||||
|
APPIMAGETOOL_SIGN_PASSPHRASE: $GPG_SIGNING_PASS
|
||||||
|
script:
|
||||||
|
- echo "$GPG_SIGNING_PUB" > file.key && sed -i 's/\r /\n/g' file.key && chmod 600 file.key
|
||||||
|
- gpg --import file.key
|
||||||
|
- rm -f file.key
|
||||||
|
- echo "$GPG_SIGNING_KEY" > file.key && sed -i 's/\r /\n/g' file.key && chmod 600 file.key
|
||||||
|
- base64 -w 0 file.key | base64 -d | gpg --import --no-tty --batch --yes
|
||||||
|
- rm -f file.key
|
||||||
|
- cmake --version
|
||||||
|
- export CC=$CC
|
||||||
|
- export CXX=$CXX
|
||||||
|
- mkdir -p build/OUTPUT
|
||||||
|
- echo $CI_BUILD_TYPE
|
||||||
|
- echo $CMAKE_GENERATOR
|
||||||
|
- echo $DEFAULT_LINUX_CMAKE_OPTIONS
|
||||||
|
- echo $CMAKE_SANITIZER_OPTIONS
|
||||||
|
- eval "$(qtchooser -qt=$QT_LINUX_VER -print-env)"
|
||||||
|
- export PATH=${QTTOOLDIR}:$PATH
|
||||||
|
- export Qt6_DIR=${QTLIBDIR}/cmake/Qt6
|
||||||
|
- echo "Using Qt $QT_LINUX_VER at ${QTLIBDIR}"
|
||||||
|
- cd build
|
||||||
|
- cmake .. -G "$CMAKE_GENERATOR" -DCMAKE_VERBOSE_MAKEFILE=ON -DLINPHONESDK_PLATFORM=Desktop -DCMAKE_BUILD_TYPE=$CI_BUILD_TYPE -DLINPHONEAPP_APPLICATION_NAME="$APPLICATION_NAME" -DLINPHONEAPP_EXECUABLE_NAME="$EXECUTABLE_NAME" $DEFAULT_LINUX_CMAKE_OPTIONS $CMAKE_OPTIONS $SCHEDULE_CMAKE_OPTIONS $CMAKE_SANITIZER_OPTIONS
|
||||||
|
- cmake --build . --target install --config $CI_BUILD_TYPE $LBC_NODEBUG_OPTIONS
|
||||||
|
extends: .linux-desktop
|
||||||
|
<<: *docker_image_platform_and_runner_tag
|
||||||
|
|
||||||
|
#################################################
|
||||||
|
# Package - Nightly
|
||||||
|
#################################################
|
||||||
|
|
||||||
|
ubuntu2004-makefile-gcc-package:
|
||||||
|
stage: package
|
||||||
|
tags: [ "docker" ]
|
||||||
|
image: gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-ubuntu-20-04-lts:$UBUNTU_2004_IMAGE_VERSION
|
||||||
|
dependencies: []
|
||||||
|
rules:
|
||||||
|
- !reference [.rules-merge-request-manual, rules]
|
||||||
|
- if: $NIGHTLY_MASTER
|
||||||
|
- if: $PACKAGE_LINUX
|
||||||
|
- if: $DEPLOY_LINUX
|
||||||
|
variables:
|
||||||
|
CMAKE_OPTIONS: -DENABLE_APP_PACKAGING=YES -DLINPHONE_BUILDER_SIGNING_IDENTITY=$GPG_SIGNING_KEYID -DENABLE_G729=ON -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$LINUX_PLATFORM/$APP_FOLDER -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=ON
|
||||||
|
CMAKE_GENERATOR: Unix Makefiles
|
||||||
|
CC: gcc
|
||||||
|
CXX: g++
|
||||||
|
APPIMAGETOOL_SIGN_PASSPHRASE: $GPG_SIGNING_PASS
|
||||||
|
extends: .linux-desktop
|
||||||
|
script:
|
||||||
|
- echo "$GPG_SIGNING_PUB" > file.key && sed -i 's/\r /\n/g' file.key && chmod 600 file.key
|
||||||
|
- gpg --import file.key
|
||||||
|
- rm -f file.key
|
||||||
|
- echo "$GPG_SIGNING_KEY" > file.key && sed -i 's/\r /\n/g' file.key && chmod 600 file.key
|
||||||
|
- base64 -w 0 file.key | base64 -d | gpg --import --no-tty --batch --yes
|
||||||
|
- rm -f file.key
|
||||||
|
- cmake --version
|
||||||
|
- export CC=$CC
|
||||||
|
- export CXX=$CXX
|
||||||
|
- mkdir -p build/OUTPUT
|
||||||
|
- echo $CI_BUILD_TYPE
|
||||||
|
- echo $CMAKE_GENERATOR
|
||||||
|
- echo $DEFAULT_LINUX_CMAKE_OPTIONS
|
||||||
|
- echo $CMAKE_SANITIZER_OPTIONS
|
||||||
|
- eval "$(qtchooser -qt=$QT_LINUX_VER -print-env)"
|
||||||
|
- export PATH=${QTTOOLDIR}:$PATH
|
||||||
|
- cd build
|
||||||
|
- cmake .. -G "$CMAKE_GENERATOR" -DCMAKE_VERBOSE_MAKEFILE=ON -DLINPHONESDK_PLATFORM=Desktop -DCMAKE_BUILD_TYPE=$CI_BUILD_TYPE -DLINPHONEAPP_APPLICATION_NAME="$APPLICATION_NAME" -DLINPHONEAPP_EXECUTABLE_NAME="$EXECUTABLE_NAME" $DEFAULT_LINUX_CMAKE_OPTIONS $CMAKE_OPTIONS $SCHEDULE_CMAKE_OPTIONS $CMAKE_SANITIZER_OPTIONS
|
||||||
|
- cmake --build . --target install --config $CI_BUILD_TYPE $LBC_NODEBUG_OPTIONS
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- build/OUTPUT/*
|
||||||
|
expire_in: 1 week
|
||||||
|
|
||||||
|
#################################################
|
||||||
|
# Deploy - Nightly
|
||||||
|
#################################################
|
||||||
|
|
||||||
|
ubuntu2004-makefile-gcc-deploy:
|
||||||
|
stage: deploy
|
||||||
|
tags: [ "deploy" ]
|
||||||
|
needs:
|
||||||
|
- ubuntu2004-makefile-gcc-package
|
||||||
|
only:
|
||||||
|
variables:
|
||||||
|
- $NIGHTLY_MASTER
|
||||||
|
- $DEPLOY_LINUX
|
||||||
|
script:
|
||||||
|
- rsync -rlv --ignore-existing build/OUTPUT/Packages/*.AppImage $DEPLOY_SERVER:$UPLOAD_ROOT_PATH/$LINUX_PLATFORM/$APP_FOLDER
|
||||||
|
- |-
|
||||||
|
if [[ $MAKE_RELEASE_FILE_URL != "" ]]; then
|
||||||
|
rsync -rlv build/OUTPUT/Packages/RELEASE $DEPLOY_SERVER:$UPLOAD_ROOT_PATH/$LINUX_PLATFORM
|
||||||
|
rsync -rlv build/OUTPUT/Packages/RELEASE $MAIN_DEPLOY_SERVER:$UPLOAD_ROOT_PATH/$LINUX_PLATFORM
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
ubuntu2004-makefile-gcc-plugins-deploy:
|
||||||
|
stage: deploy
|
||||||
|
tags: [ "deploy" ]
|
||||||
|
needs:
|
||||||
|
- ubuntu2004-makefile-gcc
|
||||||
|
only:
|
||||||
|
variables:
|
||||||
|
- $DEPLOY_PLUGINS
|
||||||
|
script:
|
||||||
|
- rsync -rlv --ignore-existing build/OUTPUT/plugins/app/*.so $DEPLOY_SERVER:$UPLOAD_ROOT_PATH/$LINUX_PLATFORM/$APP_FOLDER/plugins/
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
.factorize_ubuntu2204: &docker_image_platform_and_runner_tag
|
.factorize_ubuntu2204: &docker_image_platform_and_runner_tag
|
||||||
tags: [ "docker-flat" ]
|
tags: [ "docker" ]
|
||||||
image: gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-ubuntu-22-04-lts:$UBUNTU_2204_IMAGE_VERSION
|
image: gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-ubuntu-22-04-lts:$UBUNTU_2204_IMAGE_VERSION
|
||||||
|
|
||||||
ubuntu2204-ninja-gcc:
|
ubuntu2204-ninja-gcc:
|
||||||
|
|
@ -36,7 +36,7 @@ ubuntu2204-ninja-clang:
|
||||||
- !reference [.rules-merge-request-manual, rules]
|
- !reference [.rules-merge-request-manual, rules]
|
||||||
- if: $NIGHTLY_MASTER
|
- if: $NIGHTLY_MASTER
|
||||||
variables:
|
variables:
|
||||||
CMAKE_OPTIONS: -DENABLE_DOC=ON -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=OFF
|
CMAKE_OPTIONS: -DENABLE_DOC=ON -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=ON
|
||||||
CMAKE_GENERATOR: Ninja
|
CMAKE_GENERATOR: Ninja
|
||||||
CC: clang
|
CC: clang
|
||||||
CXX: clang++
|
CXX: clang++
|
||||||
|
|
@ -53,17 +53,41 @@ ubuntu2204-ninja-clang-small:
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
extends: ubuntu2204-ninja-clang
|
extends: ubuntu2204-ninja-clang
|
||||||
|
|
||||||
ubuntu2204-makefile-gcc-signed:
|
ubuntu2204-makefile-gcc:
|
||||||
rules:
|
rules:
|
||||||
- !reference [.rules-merge-request-manual, rules]
|
- !reference [.rules-merge-request-manual, rules]
|
||||||
- if: $NIGHTLY_MASTER
|
- if: $NIGHTLY_MASTER
|
||||||
- if: $DEPLOY_PLUGINS
|
- if: $DEPLOY_PLUGINS
|
||||||
variables:
|
variables:
|
||||||
|
CMAKE_OPTIONS: -DLINPHONE_BUILDER_SIGNING_IDENTITY=$GPG_SIGNING_KEYID -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=ON
|
||||||
CMAKE_GENERATOR: Unix Makefiles
|
CMAKE_GENERATOR: Unix Makefiles
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
ADDITIONAL_BUILD_OPTIONS: -j$MAKEFILE_JOBS
|
ADDITIONAL_BUILD_OPTIONS: -j$MAKEFILE_JOBS
|
||||||
extends: .linux-sign-build
|
APPIMAGETOOL_SIGN_PASSPHRASE: $GPG_SIGNING_PASS
|
||||||
|
script:
|
||||||
|
- echo "$GPG_SIGNING_PUB" > file.key && sed -i 's/\r /\n/g' file.key && chmod 600 file.key
|
||||||
|
- gpg --import file.key
|
||||||
|
- rm -f file.key
|
||||||
|
- echo "$GPG_SIGNING_KEY" > file.key && sed -i 's/\r /\n/g' file.key && chmod 600 file.key
|
||||||
|
- base64 -w 0 file.key | base64 -d | gpg --import --no-tty --batch --yes
|
||||||
|
- rm -f file.key
|
||||||
|
- cmake --version
|
||||||
|
- export CC=$CC
|
||||||
|
- export CXX=$CXX
|
||||||
|
- mkdir -p build/OUTPUT
|
||||||
|
- echo $CI_BUILD_TYPE
|
||||||
|
- echo $CMAKE_GENERATOR
|
||||||
|
- echo $DEFAULT_LINUX_CMAKE_OPTIONS
|
||||||
|
- echo $CMAKE_SANITIZER_OPTIONS
|
||||||
|
- eval "$(qtchooser -qt=$QT_LINUX_VER -print-env)"
|
||||||
|
- export PATH=${QTTOOLDIR}:$PATH
|
||||||
|
- export Qt6_DIR=${QTLIBDIR}/cmake/Qt6
|
||||||
|
- echo "Using Qt $QT_LINUX_VER at ${QTLIBDIR}"
|
||||||
|
- cd build
|
||||||
|
- cmake .. -G "$CMAKE_GENERATOR" -DCMAKE_VERBOSE_MAKEFILE=ON -DLINPHONESDK_PLATFORM=Desktop -DCMAKE_BUILD_TYPE=$CI_BUILD_TYPE -DLINPHONEAPP_APPLICATION_NAME="$APPLICATION_NAME" -DLINPHONEAPP_EXECUABLE_NAME="$EXECUTABLE_NAME" $DEFAULT_LINUX_CMAKE_OPTIONS $CMAKE_OPTIONS $SCHEDULE_CMAKE_OPTIONS $CMAKE_SANITIZER_OPTIONS
|
||||||
|
- cmake --build . --target install --config $CI_BUILD_TYPE $LBC_NODEBUG_OPTIONS
|
||||||
|
extends: .linux-desktop
|
||||||
<<: *docker_image_platform_and_runner_tag
|
<<: *docker_image_platform_and_runner_tag
|
||||||
|
|
||||||
#################################################
|
#################################################
|
||||||
|
|
@ -71,41 +95,77 @@ ubuntu2204-makefile-gcc-signed:
|
||||||
#################################################
|
#################################################
|
||||||
|
|
||||||
ubuntu2204-makefile-gcc-package:
|
ubuntu2204-makefile-gcc-package:
|
||||||
tags: [ "docker-flat" ]
|
stage: package
|
||||||
|
tags: [ "docker" ]
|
||||||
image: gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-ubuntu-22-04-lts:$UBUNTU_2204_IMAGE_VERSION
|
image: gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-ubuntu-22-04-lts:$UBUNTU_2204_IMAGE_VERSION
|
||||||
needs: []
|
dependencies: []
|
||||||
rules:
|
rules:
|
||||||
- !reference [.rules-merge-request-manual, rules]
|
- !reference [.rules-merge-request-manual, rules]
|
||||||
- if: $NIGHTLY_MASTER
|
- if: $NIGHTLY_MASTER
|
||||||
- if: $PACKAGE_LINUX
|
- if: $PACKAGE_LINUX
|
||||||
- if: $DEPLOY_LINUX
|
- if: $DEPLOY_LINUX
|
||||||
variables:
|
variables:
|
||||||
|
CMAKE_OPTIONS: -DENABLE_APP_PACKAGING=YES -DLINPHONE_BUILDER_SIGNING_IDENTITY=$GPG_SIGNING_KEYID -DENABLE_G729=ON -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$LINUX_PLATFORM/$APP_FOLDER -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=ON
|
||||||
CMAKE_GENERATOR: Unix Makefiles
|
CMAKE_GENERATOR: Unix Makefiles
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
extends: .linux-sign-package
|
APPIMAGETOOL_SIGN_PASSPHRASE: $GPG_SIGNING_PASS
|
||||||
|
extends: .linux-desktop
|
||||||
|
script:
|
||||||
|
- echo "$GPG_SIGNING_PUB" > file.key && sed -i 's/\r /\n/g' file.key && chmod 600 file.key
|
||||||
|
- gpg --import file.key
|
||||||
|
- rm -f file.key
|
||||||
|
- echo "$GPG_SIGNING_KEY" > file.key && sed -i 's/\r /\n/g' file.key && chmod 600 file.key
|
||||||
|
- base64 -w 0 file.key | base64 -d | gpg --import --no-tty --batch --yes
|
||||||
|
- rm -f file.key
|
||||||
|
- cmake --version
|
||||||
|
- export CC=$CC
|
||||||
|
- export CXX=$CXX
|
||||||
|
- mkdir -p build/OUTPUT
|
||||||
|
- echo $CI_BUILD_TYPE
|
||||||
|
- echo $CMAKE_GENERATOR
|
||||||
|
- echo $DEFAULT_LINUX_CMAKE_OPTIONS
|
||||||
|
- echo $CMAKE_SANITIZER_OPTIONS
|
||||||
|
- eval "$(qtchooser -qt=$QT_LINUX_VER -print-env)"
|
||||||
|
- export PATH=${QTTOOLDIR}:$PATH
|
||||||
|
- cd build
|
||||||
|
- cmake .. -G "$CMAKE_GENERATOR" -DCMAKE_VERBOSE_MAKEFILE=ON -DLINPHONESDK_PLATFORM=Desktop -DCMAKE_BUILD_TYPE=$CI_BUILD_TYPE -DLINPHONEAPP_APPLICATION_NAME="$APPLICATION_NAME" -DLINPHONEAPP_EXECUTABLE_NAME="$EXECUTABLE_NAME" $DEFAULT_LINUX_CMAKE_OPTIONS $CMAKE_OPTIONS $SCHEDULE_CMAKE_OPTIONS $CMAKE_SANITIZER_OPTIONS
|
||||||
|
- cmake --build . --target install --config $CI_BUILD_TYPE $LBC_NODEBUG_OPTIONS
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- build/OUTPUT/*
|
||||||
|
expire_in: 1 week
|
||||||
|
|
||||||
#################################################
|
#################################################
|
||||||
# Deploy - Nightly
|
# Deploy - Nightly
|
||||||
#################################################
|
#################################################
|
||||||
|
|
||||||
ubuntu2204-makefile-gcc-deploy:
|
ubuntu2204-makefile-gcc-deploy:
|
||||||
extends: .linux-deploy
|
stage: deploy
|
||||||
needs:
|
tags: [ "deploy" ]
|
||||||
- ubuntu2204-makefile-gcc-package
|
needs:
|
||||||
only:
|
- ubuntu2204-makefile-gcc-package
|
||||||
|
only:
|
||||||
variables:
|
variables:
|
||||||
- $NIGHTLY_MASTER
|
- $NIGHTLY_MASTER
|
||||||
- $DEPLOY_LINUX
|
- $DEPLOY_LINUX
|
||||||
|
script:
|
||||||
|
- rsync -rlv --ignore-existing build/OUTPUT/Packages/*.AppImage $DEPLOY_SERVER:$UPLOAD_ROOT_PATH/$LINUX_PLATFORM/$APP_FOLDER
|
||||||
|
- |-
|
||||||
|
if [[ $MAKE_RELEASE_FILE_URL != "" ]]; then
|
||||||
|
rsync -rlv build/OUTPUT/Packages/RELEASE $DEPLOY_SERVER:$UPLOAD_ROOT_PATH/$LINUX_PLATFORM
|
||||||
|
rsync -rlv build/OUTPUT/Packages/RELEASE $MAIN_DEPLOY_SERVER:$UPLOAD_ROOT_PATH/$LINUX_PLATFORM
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
ubuntu2204-makefile-gcc-plugins-deploy:
|
ubuntu2204-makefile-gcc-plugins-deploy:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
tags: [ "deploy-flat" ]
|
tags: [ "deploy" ]
|
||||||
needs:
|
needs:
|
||||||
- ubuntu2204-makefile-gcc
|
- ubuntu2204-makefile-gcc
|
||||||
only:
|
only:
|
||||||
variables:
|
variables:
|
||||||
- $DEPLOY_PLUGINS
|
- $DEPLOY_PLUGINS
|
||||||
script:
|
script:
|
||||||
- rsync -rlv --ignore-existing build/OUTPUT/plugins/app/*.so $DEPLOY_SERVER:$UPLOAD_ROOT_PATH/$LINUX_PLATFORM/$APP_FOLDER/plugins/
|
- rsync -rlv --ignore-existing build/OUTPUT/plugins/app/*.so $DEPLOY_SERVER:$UPLOAD_ROOT_PATH/$LINUX_PLATFORM/$APP_FOLDER/plugins/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
# BUILD
|
# BUILD
|
||||||
#################################################
|
#################################################
|
||||||
|
|
||||||
.common_linux: &common_linux |
|
.build_all_linux_script: &build_all_linux_script |
|
||||||
cmake --version
|
cmake --version
|
||||||
export CC=$CC
|
export CC=$CC
|
||||||
export CXX=$CXX
|
export CXX=$CXX
|
||||||
|
|
@ -11,68 +11,20 @@
|
||||||
echo $CMAKE_GENERATOR
|
echo $CMAKE_GENERATOR
|
||||||
echo $DEFAULT_LINUX_CMAKE_OPTIONS
|
echo $DEFAULT_LINUX_CMAKE_OPTIONS
|
||||||
echo $CMAKE_SANITIZER_OPTIONS
|
echo $CMAKE_SANITIZER_OPTIONS
|
||||||
eval "$(qtchooser -qt=$QT_LINUX_VER-${QT_OPEN_SOURCE_DIRECTORY:-proprietary} -print-env)"
|
cd build
|
||||||
|
eval "$(qtchooser -qt=$QT_LINUX_VER -print-env)"
|
||||||
export PATH=${QTTOOLDIR}:$PATH
|
export PATH=${QTTOOLDIR}:$PATH
|
||||||
export Qt6_DIR=${QTLIBDIR}/cmake/Qt6
|
export Qt6_DIR=${QTLIBDIR}/cmake/Qt6
|
||||||
echo "Using Qt $QT_LINUX_VER at ${QTLIBDIR}"
|
echo "Using Qt $QT_LINUX_VER at ${QTLIBDIR}"
|
||||||
cd build
|
|
||||||
|
|
||||||
.build_all_linux_script: &build_all_linux_script |
|
|
||||||
cmake .. -G "$CMAKE_GENERATOR" -DCMAKE_VERBOSE_MAKEFILE=ON -DLINPHONESDK_PLATFORM=Desktop -DCMAKE_BUILD_TYPE=$CI_BUILD_TYPE -DLINPHONEAPP_APPLICATION_NAME="$APPLICATION_NAME" -DLINPHONEAPP_EXECUABLE_NAME="$EXECUTABLE_NAME" $DEFAULT_LINUX_CMAKE_OPTIONS $CMAKE_OPTIONS $SCHEDULE_CMAKE_OPTIONS $CMAKE_SANITIZER_OPTIONS
|
cmake .. -G "$CMAKE_GENERATOR" -DCMAKE_VERBOSE_MAKEFILE=ON -DLINPHONESDK_PLATFORM=Desktop -DCMAKE_BUILD_TYPE=$CI_BUILD_TYPE -DLINPHONEAPP_APPLICATION_NAME="$APPLICATION_NAME" -DLINPHONEAPP_EXECUABLE_NAME="$EXECUTABLE_NAME" $DEFAULT_LINUX_CMAKE_OPTIONS $CMAKE_OPTIONS $SCHEDULE_CMAKE_OPTIONS $CMAKE_SANITIZER_OPTIONS
|
||||||
cmake --build . --target install --config $CI_BUILD_TYPE $LBC_NODEBUG_OPTIONS
|
cmake --build . --target install --config $CI_BUILD_TYPE $LBC_NODEBUG_OPTIONS
|
||||||
|
|
||||||
.common_signed_linux: &common_signed_linux |
|
|
||||||
echo "$GPG_SIGNING_PUB" > file.key && sed -i 's/\r /\n/g' file.key && chmod 600 file.key
|
|
||||||
gpg --import file.key
|
|
||||||
rm -f file.key
|
|
||||||
echo "$GPG_SIGNING_KEY" > file.key && sed -i 's/\r /\n/g' file.key && chmod 600 file.key
|
|
||||||
base64 -w 0 file.key | base64 -d | gpg --import --no-tty --batch --yes
|
|
||||||
rm -f file.key
|
|
||||||
|
|
||||||
.deploy_linux: &deploy_linux |
|
|
||||||
rsync -rlv --chmod=Fu=rw,Fg=r,Fo=r --ignore-existing build/OUTPUT/Packages/*.AppImage $DEPLOY_SERVER:$UPLOAD_ROOT_PATH/$LINUX_PLATFORM/$APP_FOLDER
|
|
||||||
if [[ $MAKE_RELEASE_FILE_URL != "" ]]; then
|
|
||||||
rsync -rlv --chmod=Fu=rw,Fg=r,Fo=r build/OUTPUT/Packages/RELEASE $DEPLOY_SERVER:$UPLOAD_ROOT_PATH/$LINUX_PLATFORM
|
|
||||||
rsync -rlv --chmod=Fu=rw,Fg=r,Fo=r build/OUTPUT/Packages/RELEASE $MAIN_DEPLOY_SERVER:$UPLOAD_ROOT_PATH/$LINUX_PLATFORM
|
|
||||||
fi
|
|
||||||
|
|
||||||
.linux-desktop:
|
.linux-desktop:
|
||||||
stage: build
|
stage: build
|
||||||
extends: .linux-prepare
|
extends: .linux-prepare
|
||||||
script:
|
script:
|
||||||
- *common_linux
|
|
||||||
- *build_all_linux_script
|
- *build_all_linux_script
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- build/OUTPUT
|
- build/OUTPUT
|
||||||
expire_in: 1 week
|
expire_in: 1 week
|
||||||
|
|
||||||
.linux-sign-build:
|
|
||||||
extends: .linux-desktop
|
|
||||||
variables:
|
|
||||||
CMAKE_OPTIONS: -DLINPHONE_BUILDER_SIGNING_IDENTITY=$GPG_SIGNING_KEYID -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=OFF
|
|
||||||
APPIMAGETOOL_SIGN_PASSPHRASE: $GPG_SIGNING_PASS
|
|
||||||
script:
|
|
||||||
- *common_signed_linux
|
|
||||||
- *common_linux
|
|
||||||
- cmake .. -G "$CMAKE_GENERATOR" -DCMAKE_VERBOSE_MAKEFILE=ON -DLINPHONESDK_PLATFORM=Desktop -DCMAKE_BUILD_TYPE=$CI_BUILD_TYPE -DLINPHONEAPP_APPLICATION_NAME="$APPLICATION_NAME" -DLINPHONEAPP_EXECUABLE_NAME="$EXECUTABLE_NAME" $DEFAULT_LINUX_CMAKE_OPTIONS $CMAKE_OPTIONS $SCHEDULE_CMAKE_OPTIONS $CMAKE_SANITIZER_OPTIONS
|
|
||||||
- cmake --build . --target install --config $CI_BUILD_TYPE $LBC_NODEBUG_OPTIONS
|
|
||||||
|
|
||||||
.linux-sign-package:
|
|
||||||
stage: package
|
|
||||||
extends: .linux-desktop
|
|
||||||
variables:
|
|
||||||
CMAKE_OPTIONS: -DENABLE_APP_PACKAGING=YES -DLINPHONE_BUILDER_SIGNING_IDENTITY=$GPG_SIGNING_KEYID -DENABLE_G729=ON -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$LINUX_PLATFORM/$APP_FOLDER -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=OFF
|
|
||||||
APPIMAGETOOL_SIGN_PASSPHRASE: $GPG_SIGNING_PASS
|
|
||||||
script:
|
|
||||||
- *common_signed_linux
|
|
||||||
- *common_linux
|
|
||||||
- cmake .. -G "$CMAKE_GENERATOR" -DCMAKE_VERBOSE_MAKEFILE=ON -DLINPHONESDK_PLATFORM=Desktop -DCMAKE_BUILD_TYPE=$CI_BUILD_TYPE -DLINPHONEAPP_APPLICATION_NAME="$APPLICATION_NAME" -DLINPHONEAPP_EXECUTABLE_NAME="$EXECUTABLE_NAME" $DEFAULT_LINUX_CMAKE_OPTIONS $CMAKE_OPTIONS $SCHEDULE_CMAKE_OPTIONS $CMAKE_SANITIZER_OPTIONS
|
|
||||||
- cmake --build . --target install --config $CI_BUILD_TYPE $LBC_NODEBUG_OPTIONS
|
|
||||||
|
|
||||||
|
|
||||||
.linux-deploy:
|
|
||||||
stage: deploy
|
|
||||||
tags: [ "deploy-flat" ]
|
|
||||||
script:
|
|
||||||
- *deploy_linux
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
.macosx-desktop:
|
.macosx-desktop:
|
||||||
stage: build
|
stage: build
|
||||||
tags: [ "macmini-m1-xcode15-flat" ]
|
tags: [ "macos-min-xcode12.2" ]
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $DOCKER_UPDATE == null && $SKIP_MACOSX == null
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $DOCKER_UPDATE == null && $SKIP_MACOSX == null
|
||||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $DOCKER_UPDATE == null && $SKIP_MACOSX == null
|
- if: $CI_PIPELINE_SOURCE == "schedule" && $DOCKER_UPDATE == null && $SKIP_MACOSX == null
|
||||||
|
|
@ -93,8 +93,8 @@ macosx-ninja-novideo:
|
||||||
# WAIT for QT6 for arm64
|
# WAIT for QT6 for arm64
|
||||||
macosx-ninja-package:
|
macosx-ninja-package:
|
||||||
stage: package
|
stage: package
|
||||||
tags: [ "macmini-m1-xcode15-flat" ]
|
tags: [ "macos-min-xcode12.2" ]
|
||||||
needs: []
|
dependencies: []
|
||||||
rules:
|
rules:
|
||||||
- !reference [.rules-merge-request-manual, rules]
|
- !reference [.rules-merge-request-manual, rules]
|
||||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $DOCKER_UPDATE == null && $SKIP_MACOSX == null
|
- if: $CI_PIPELINE_SOURCE == "schedule" && $DOCKER_UPDATE == null && $SKIP_MACOSX == null
|
||||||
|
|
@ -102,7 +102,7 @@ macosx-ninja-package:
|
||||||
- if: $PACKAGE_MACOSX
|
- if: $PACKAGE_MACOSX
|
||||||
- if: $DEPLOY_MACOSX
|
- if: $DEPLOY_MACOSX
|
||||||
variables:
|
variables:
|
||||||
CMAKE_OPTIONS: -DPython3_ROOT_DIR=/opt/bc/pip-packages/ -DENABLE_APP_PACKAGING=ON -DENABLE_GPL_THIRD_PARTIES=OFF -DENABLE_G729=ON
|
CMAKE_OPTIONS: -DPython3_ROOT_DIR=/opt/bc/pip-packages/ -DENABLE_APP_PACKAGING=ON -DENABLE_GPL_THIRD_PARTIES=ON -DENABLE_G729=ON
|
||||||
RELEASE_FILE: -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$MACOSX_PLATFORM/$APP_FOLDER
|
RELEASE_FILE: -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$MACOSX_PLATFORM/$APP_FOLDER
|
||||||
extends: macosx-ninja
|
extends: macosx-ninja
|
||||||
script:
|
script:
|
||||||
|
|
@ -117,7 +117,7 @@ macosx-ninja-package:
|
||||||
|
|
||||||
macosx-codesigning:
|
macosx-codesigning:
|
||||||
stage: signing
|
stage: signing
|
||||||
tags: [ "macmini-m1-xcode15-flat" ]
|
tags: [ "macos-min-xcode12.2" ]
|
||||||
needs:
|
needs:
|
||||||
- macosx-ninja-package
|
- macosx-ninja-package
|
||||||
rules:
|
rules:
|
||||||
|
|
@ -142,7 +142,7 @@ macosx-codesigning:
|
||||||
|
|
||||||
macosx-deploy:
|
macosx-deploy:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
tags: [ "macmini-m1-xcode15-flat" ]
|
tags: [ "macos-min-xcode12.2" ]
|
||||||
needs:
|
needs:
|
||||||
- macosx-codesigning
|
- macosx-codesigning
|
||||||
only:
|
only:
|
||||||
|
|
@ -160,7 +160,7 @@ macosx-deploy:
|
||||||
|
|
||||||
macosx-makefile-plugins-deploy:
|
macosx-makefile-plugins-deploy:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
tags: [ "macmini-m1-xcode15-flat" ]
|
tags: [ "macos-min-xcode12.2" ]
|
||||||
needs:
|
needs:
|
||||||
- macosx-makefile
|
- macosx-makefile
|
||||||
only:
|
only:
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $DOCKER_UPDATE == null && $SKIP_WINDOWS == null
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $DOCKER_UPDATE == null && $SKIP_WINDOWS == null
|
||||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $DOCKER_UPDATE == null && $SKIP_WINDOWS == null
|
- if: $CI_PIPELINE_SOURCE == "schedule" && $DOCKER_UPDATE == null && $SKIP_WINDOWS == null
|
||||||
variables:
|
variables:
|
||||||
CMAKE_OPTIONS: -DENABLE_UNIT_TESTS=ON -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=OFF
|
CMAKE_OPTIONS: -DENABLE_UNIT_TESTS=ON -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=ON
|
||||||
LINPHONESDK_PLATFORM: Desktop
|
LINPHONESDK_PLATFORM: Desktop
|
||||||
OUTPUT_ZIP_FOLDER: win64
|
OUTPUT_ZIP_FOLDER: win64
|
||||||
MINGW_TYPE: mingw64
|
MINGW_TYPE: mingw64
|
||||||
|
|
@ -92,11 +92,11 @@
|
||||||
|
|
||||||
.windows-vs2022:
|
.windows-vs2022:
|
||||||
extends: .windows-vs
|
extends: .windows-vs
|
||||||
tags: [ "windows-powershell-vs-17-2022-flat" ]
|
tags: [ "windows-powershell-vs-17-2022" ]
|
||||||
|
|
||||||
.windows-codesigning:
|
.windows-codesigning:
|
||||||
extends: .prepare
|
extends: .prepare
|
||||||
tags: [ "windows-powershell-vs-17-2022-apps-flat" ]
|
tags: [ "windows-powershell-vs-17-2022-apps" ]
|
||||||
|
|
||||||
.windows-msbuild-variables:
|
.windows-msbuild-variables:
|
||||||
variables:
|
variables:
|
||||||
|
|
@ -177,7 +177,7 @@ win64-ninja-vs2022-scheduled-windows:
|
||||||
|
|
||||||
.vs-win64-package:
|
.vs-win64-package:
|
||||||
stage: package
|
stage: package
|
||||||
needs: []
|
dependencies: []
|
||||||
rules:
|
rules:
|
||||||
- !reference [.rules-merge-request-manual, rules]
|
- !reference [.rules-merge-request-manual, rules]
|
||||||
- if: $NIGHTLY_MASTER
|
- if: $NIGHTLY_MASTER
|
||||||
|
|
@ -185,7 +185,7 @@ win64-ninja-vs2022-scheduled-windows:
|
||||||
- if: $PACKAGE_WINDOWS
|
- if: $PACKAGE_WINDOWS
|
||||||
- if: $DEPLOY_WINDOWS
|
- if: $DEPLOY_WINDOWS
|
||||||
variables:
|
variables:
|
||||||
CMAKE_OPTIONS: -DENABLE_APP_PACKAGING=YES -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=OFF
|
CMAKE_OPTIONS: -DENABLE_APP_PACKAGING=YES -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=ON
|
||||||
RELEASE_FILE: -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$WINDOWS_PLATFORM/$APP_FOLDER
|
RELEASE_FILE: -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$WINDOWS_PLATFORM/$APP_FOLDER
|
||||||
|
|
||||||
win64-ninja-vs2022-package-windows:
|
win64-ninja-vs2022-package-windows:
|
||||||
|
|
@ -232,15 +232,15 @@ win64-codesigning:
|
||||||
|
|
||||||
.win64-upload:
|
.win64-upload:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
tags: [ "windows-powershell-flat" ]
|
tags: [ "windows-powershell" ]
|
||||||
rules:
|
rules:
|
||||||
- if: $NIGHTLY_MASTER
|
- if: $NIGHTLY_MASTER
|
||||||
- if: $DEPLOY_WINDOWS
|
- if: $DEPLOY_WINDOWS
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- rsync --perms --chmod=Fu=rw,Fg=r,Fo=r build-desktop/OUTPUT/Packages/*.exe ${DEPLOY_SERVER}:${UPLOAD_ROOT_PATH}/${WINDOWS_PLATFORM}/${APP_FOLDER}
|
- scp -pr build-desktop/OUTPUT/Packages/*.exe ${DEPLOY_SERVER}:${UPLOAD_ROOT_PATH}/${WINDOWS_PLATFORM}/${APP_FOLDER}
|
||||||
- if ($MAKE_RELEASE_FILE_URL) { rsync --perms --chmod=Fu=rw,Fg=r,Fo=r build-desktop/OUTPUT/Packages/RELEASE ${DEPLOY_SERVER}:${UPLOAD_ROOT_PATH}/${WINDOWS_PLATFORM}/ }
|
- if ($MAKE_RELEASE_FILE_URL) { scp -pr build-desktop/OUTPUT/Packages/RELEASE ${DEPLOY_SERVER}:${UPLOAD_ROOT_PATH}/${WINDOWS_PLATFORM}/ }
|
||||||
- if ($MAKE_RELEASE_FILE_URL) { rsync --perms --chmod=Fu=rw,Fg=r,Fo=r build-desktop/OUTPUT/Packages/RELEASE ${MAIN_DEPLOY_SERVER}:${UPLOAD_ROOT_PATH}/${WINDOWS_PLATFORM}/ }
|
- if ($MAKE_RELEASE_FILE_URL) { scp -pr build-desktop/OUTPUT/Packages/RELEASE ${MAIN_DEPLOY_SERVER}:${UPLOAD_ROOT_PATH}/${WINDOWS_PLATFORM}/ }
|
||||||
|
|
||||||
win64-ninja-vs2022-upload:
|
win64-ninja-vs2022-upload:
|
||||||
extends:
|
extends:
|
||||||
|
|
@ -250,7 +250,7 @@ win64-ninja-vs2022-upload:
|
||||||
|
|
||||||
.win64-plugins-upload:
|
.win64-plugins-upload:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
tags: [ "windows-flat" ]
|
tags: [ "windows" ]
|
||||||
rules:
|
rules:
|
||||||
- if: $DEPLOY_PLUGINS
|
- if: $DEPLOY_PLUGINS
|
||||||
script:
|
script:
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,13 @@ variables:
|
||||||
#CMAKE_OPTIONS: -DENABLE_LIME_X3DH=YES
|
#CMAKE_OPTIONS: -DENABLE_LIME_X3DH=YES
|
||||||
|
|
||||||
# Docker image version
|
# Docker image version
|
||||||
UBUNTU_2204_IMAGE_VERSION: 20251106_add_commercial_qt_version_5.15.14_5.15.19_6.8.1_6.8.3_6.9.1_6.10.0
|
ARCHLINUX_IMAGE_VERSION: latestupdated
|
||||||
|
CENTOS_7_QT_IMAGE_VERSION: 20211012_add_qtwebview
|
||||||
|
DEBIAN_9_QT_IMAGE_VERSION: 20230417_qtopen_gstreamer
|
||||||
|
DEBIAN_10_IMAGE_VERSION: 20210217_python3
|
||||||
|
UBUNTU_ROLLING_IMAGE_VERSION: 20211012_add_qtwebview
|
||||||
|
UBUNTU_2004_IMAGE_VERSION: 20250226_qt6-8-0
|
||||||
|
UBUNTU_2204_IMAGE_VERSION: 20250512_qt6-9-0
|
||||||
|
|
||||||
|
|
||||||
workflow:
|
workflow:
|
||||||
|
|
@ -45,6 +51,7 @@ include:
|
||||||
- '.gitlab-ci-files/rules.yml'
|
- '.gitlab-ci-files/rules.yml'
|
||||||
- '.gitlab-ci-files/linux-prepare.yml'
|
- '.gitlab-ci-files/linux-prepare.yml'
|
||||||
- '.gitlab-ci-files/linux-desktop.yml'
|
- '.gitlab-ci-files/linux-desktop.yml'
|
||||||
|
# - '.gitlab-ci-files/linux-desktop-ubuntu-2004.yml'
|
||||||
- '.gitlab-ci-files/linux-desktop-ubuntu-2204.yml'
|
- '.gitlab-ci-files/linux-desktop-ubuntu-2204.yml'
|
||||||
- '.gitlab-ci-files/windows-desktop.yml'
|
- '.gitlab-ci-files/windows-desktop.yml'
|
||||||
- '.gitlab-ci-files/macosx-desktop.yml'
|
- '.gitlab-ci-files/macosx-desktop.yml'
|
||||||
|
|
|
||||||
2
.gitmodules
vendored
2
.gitmodules
vendored
|
|
@ -1,3 +1,3 @@
|
||||||
[submodule "linphone-sdk"]
|
[submodule "linphone-sdk"]
|
||||||
path = external/linphone-sdk
|
path = external/linphone-sdk
|
||||||
url = https://gitlab.linphone.org/BC/public/linphone-sdk.git
|
url = https://gitlab.linphone.org/BC/public/linphone-sdk.git
|
||||||
|
|
@ -31,9 +31,3 @@ Group changes to describe their impact on the project, as follows:
|
||||||
- Default screen (between contacts, call history, conversations & meetings list) will change depending on where you were when the app was paused or killed, and you will return to that last visited screen on the next startup.
|
- Default screen (between contacts, call history, conversations & meetings list) will change depending on where you were when the app was paused or killed, and you will return to that last visited screen on the next startup.
|
||||||
- Minimum supported Qt version is now 6.5.3
|
- Minimum supported Qt version is now 6.5.3
|
||||||
- Some settings have changed name and/or section in linphonerc file.
|
- Some settings have changed name and/or section in linphonerc file.
|
||||||
|
|
||||||
|
|
||||||
## [6.1.0] - XXXX-XX-XX
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Minimum supported Qt version is now 6.10.0
|
|
||||||
|
|
@ -60,6 +60,7 @@ project(linphoneqt)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
|
include(Linphone/application_info.cmake)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
if(LINPHONEAPP_INSTALL_PREFIX)
|
if(LINPHONEAPP_INSTALL_PREFIX)
|
||||||
|
|
@ -71,11 +72,8 @@ endif()
|
||||||
|
|
||||||
set(CMAKE_INSTALL_PREFIX "${APPLICATION_OUTPUT_DIR}")
|
set(CMAKE_INSTALL_PREFIX "${APPLICATION_OUTPUT_DIR}")
|
||||||
|
|
||||||
set(LINPHONEAPP_APPLICATION_NAME "Linphone" CACHE STRING "Application name" )
|
set(LINPHONEAPP_APPLICATION_NAME "Linphone6" CACHE STRING "Application name" )
|
||||||
set(LINPHONEAPP_EXECUTABLE_NAME "linphone" CACHE STRING "Executable name" )
|
set(LINPHONEAPP_EXECUTABLE_NAME "linphone6" CACHE STRING "Executable name" )
|
||||||
|
|
||||||
# Include application_info.cmake here as the LINPHONEAPP_APPLICATION_NAME variable must be known as it is set to the APPLICATION_NAME variable.
|
|
||||||
include(Linphone/application_info.cmake)
|
|
||||||
|
|
||||||
if( APPLE )
|
if( APPLE )
|
||||||
set(LINPHONEAPP_MACOS_ARCHS "arm64" CACHE STRING "MacOS architectures to build: comma-separated list of values in [arm64, x86_64]")
|
set(LINPHONEAPP_MACOS_ARCHS "arm64" CACHE STRING "MacOS architectures to build: comma-separated list of values in [arm64, x86_64]")
|
||||||
|
|
@ -165,7 +163,7 @@ add_option(OPTION_LIST ENABLE_FFMPEG "Build mediastreamer2 with ffmpeg video sup
|
||||||
add_option(OPTION_LIST ENABLE_LDAP "Enable LDAP support." YES)
|
add_option(OPTION_LIST ENABLE_LDAP "Enable LDAP support." YES)
|
||||||
add_option(OPTION_LIST ENABLE_NON_FREE_CODECS "Enable the use of non free codecs" YES)
|
add_option(OPTION_LIST ENABLE_NON_FREE_CODECS "Enable the use of non free codecs" YES)
|
||||||
add_option(OPTION_LIST ENABLE_NON_FREE_FEATURES "Enable the use of non free codecs" ${ENABLE_NON_FREE_CODECS})
|
add_option(OPTION_LIST ENABLE_NON_FREE_FEATURES "Enable the use of non free codecs" ${ENABLE_NON_FREE_CODECS})
|
||||||
add_option(OPTION_LIST ENABLE_QT_KEYCHAIN "Build QtKeychain to manage VFS from System key stores." OFF)
|
add_option(OPTION_LIST ENABLE_QT_KEYCHAIN "Build QtKeychain to manage VFS from System key stores." ON)
|
||||||
add_option(OPTION_LIST ENABLE_QRCODE "Enable QRCode support" OFF)#Experimental
|
add_option(OPTION_LIST ENABLE_QRCODE "Enable QRCode support" OFF)#Experimental
|
||||||
add_option(OPTION_LIST ENABLE_RELATIVE_PREFIX "Set Internal packages relative to the binary" ON)
|
add_option(OPTION_LIST ENABLE_RELATIVE_PREFIX "Set Internal packages relative to the binary" ON)
|
||||||
add_option(OPTION_LIST ENABLE_SANITIZER "Enable sanitizer." OFF)
|
add_option(OPTION_LIST ENABLE_SANITIZER "Enable sanitizer." OFF)
|
||||||
|
|
@ -187,9 +185,9 @@ add_option(OPTION_LIST ENABLE_SCREENSHARING "Enable screen sharing." ${ENABLE_VI
|
||||||
# QtKeychain
|
# QtKeychain
|
||||||
add_option(OPTION_LIST LIBSECRET_SUPPORT "Build with libsecret support" OFF) # Need libsecret-devel
|
add_option(OPTION_LIST LIBSECRET_SUPPORT "Build with libsecret support" OFF) # Need libsecret-devel
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_cache(OPTION_LIST QTKEYCHAIN_TARGET_NAME "Override Qt6Keychain library name for a workaround with windeployqt" "EQt6Keychain")
|
add_cache(OPTION_LIST QTKEYCHAIN_TARGET_NAME "Override Qt5Keychain library name for a workaround with windeployqt" "EQt5Keychain")
|
||||||
else()
|
else()
|
||||||
add_cache(OPTION_LIST QTKEYCHAIN_TARGET_NAME "Override Qt6Keychain library name" "Qt6Keychain")
|
add_cache(OPTION_LIST QTKEYCHAIN_TARGET_NAME "Override Qt5Keychain library name" "Qt5Keychain")
|
||||||
endif()
|
endif()
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_option(OPTION_LIST ENABLE_OPENSSL_EXPORT "Enable OpenSSL deployment" YES)
|
add_option(OPTION_LIST ENABLE_OPENSSL_EXPORT "Enable OpenSSL deployment" YES)
|
||||||
|
|
@ -208,7 +206,7 @@ set(ENABLE_CSHARP_WRAPPER OFF CACHE BOOL "Build the CSharp wrapper for Liblinpho
|
||||||
set(ENABLE_THEORA OFF)
|
set(ENABLE_THEORA OFF)
|
||||||
set(ENABLE_QT_GL ${ENABLE_VIDEO})
|
set(ENABLE_QT_GL ${ENABLE_VIDEO})
|
||||||
|
|
||||||
find_package(Qt6 REQUIRED COMPONENTS Core Quick Widgets)
|
find_package(Qt6 REQUIRED COMPONENTS Core)
|
||||||
|
|
||||||
if(NOT Qt6_FOUND)
|
if(NOT Qt6_FOUND)
|
||||||
message(FATAL_ERROR "Minimum supported Qt6!")
|
message(FATAL_ERROR "Minimum supported Qt6!")
|
||||||
|
|
@ -229,11 +227,18 @@ endif()
|
||||||
if(NOT APPLE OR MONO_ARCH)
|
if(NOT APPLE OR MONO_ARCH)
|
||||||
add_custom_target(linphone-deps)
|
add_custom_target(linphone-deps)
|
||||||
if(NOT LINPHONE_QT_ONLY)
|
if(NOT LINPHONE_QT_ONLY)
|
||||||
function(add_external)
|
function(add_external)
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) # Prevent project from overriding the options we just set here
|
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) # Prevent project from overriding the options we just set here
|
||||||
add_subdirectory("external")
|
add_subdirectory("external")
|
||||||
endfunction()
|
endfunction()
|
||||||
add_external()
|
add_external()
|
||||||
|
|
||||||
|
if(ENABLE_QT_KEYCHAIN)
|
||||||
|
function(add_linphone_keychain)
|
||||||
|
#add_subdirectory("external/qtkeychain")
|
||||||
|
endfunction()
|
||||||
|
add_linphone_keychain()
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
function(add_linphone_app)
|
function(add_linphone_app)
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) # Prevent project from overriding the options we just set here
|
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) # Prevent project from overriding the options we just set here
|
||||||
|
|
@ -265,16 +270,4 @@ else()
|
||||||
include(cmake/TasksMacos.cmake)
|
include(cmake/TasksMacos.cmake)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# if (ENABLE_QT_KEYCHAIN)
|
|
||||||
# target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${PROJECT_SOURCE_DIR}/external/qtkeychain)
|
|
||||||
# target_link_libraries(${TARGET_NAME} PUBLIC ${QTKEYCHAIN_TARGET_NAME})
|
|
||||||
# message(STATUS "link libraries: ${TARGET_NAME} ${QTKEYCHAIN_TARGET_NAME}")
|
|
||||||
# message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
|
|
||||||
# message(STATUS "PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}")
|
|
||||||
# message(STATUS "Contents of qtkeychain:")
|
|
||||||
# file(GLOB QTKEYCHAIN_HEADERS "${PROJECT_SOURCE_DIR}/external/qtkeychain/qtkeychain/*.h")
|
|
||||||
# message(STATUS "Found headers: ${QTKEYCHAIN_HEADERS}")
|
|
||||||
# endif()
|
|
||||||
|
|
||||||
|
|
||||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/cmake/hook/pre-commit" DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/.git/hooks/")
|
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/cmake/hook/pre-commit" DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/.git/hooks/")
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
project(Linphone VERSION 6.2.0 LANGUAGES CXX)
|
project(Linphone VERSION 6.0.0 LANGUAGES CXX)
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
# PACKAGES
|
# PACKAGES
|
||||||
|
|
@ -19,14 +19,14 @@ endforeach()
|
||||||
set(TARGET_NAME Linphone)
|
set(TARGET_NAME Linphone)
|
||||||
set(APP_TARGETS ${LinphoneCxx_TARGET}
|
set(APP_TARGETS ${LinphoneCxx_TARGET}
|
||||||
${Mediastreamer2_TARGET}#MediastreamerUtils
|
${Mediastreamer2_TARGET}#MediastreamerUtils
|
||||||
${LibLinphone_TARGET})#Liblinphone
|
${LibLinphone_TARGET})#MediastreamerUtils
|
||||||
|
|
||||||
set(QT_DEFAULT_MAJOR_VERSION 6)
|
set(QT_DEFAULT_MAJOR_VERSION 6)
|
||||||
set(QT_PACKAGES Quick Qml Widgets Svg Multimedia Test NetworkAuth Concurrent)# Search Core at first for initialize Qt scripts for next find_packages.
|
set(QT_PACKAGES Core Quick Qml Widgets Svg Multimedia Test NetworkAuth Concurrent)# Search Core at first for initialize Qt scripts for next find_packages.
|
||||||
if (UNIX AND NOT APPLE)
|
if (UNIX AND NOT APPLE)
|
||||||
list(APPEND QT_PACKAGES DBus)
|
list(APPEND QT_PACKAGES DBus)
|
||||||
endif()
|
endif()
|
||||||
find_package(Qt6 REQUIRED COMPONENTS Core)
|
find_package(Qt6 REQUIRED COMPONENTS Core)
|
||||||
find_package(Qt6 REQUIRED COMPONENTS ${QT_PACKAGES})
|
find_package(Qt6 REQUIRED COMPONENTS ${QT_PACKAGES})
|
||||||
find_package(Qt6 REQUIRED COMPONENTS LinguistTools)
|
find_package(Qt6 REQUIRED COMPONENTS LinguistTools)
|
||||||
|
|
||||||
|
|
@ -98,11 +98,15 @@ endif()
|
||||||
|
|
||||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/config.h")
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/config.h")
|
||||||
|
|
||||||
if(${Qt6_VERSION} VERSION_LESS "6.10.0")
|
if(${Qt6_VERSION} VERSION_LESS "6.3.0")
|
||||||
message( FATAL_ERROR "Linphone requires Qt 6.10.0 or newer. Exiting CMake." )
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
else()
|
||||||
|
qt6_standard_project_setup()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
qt6_standard_project_setup()
|
|
||||||
|
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
|
|
@ -123,7 +127,7 @@ add_subdirectory(core)
|
||||||
|
|
||||||
set(LANGUAGES_DIRECTORY "data/languages")
|
set(LANGUAGES_DIRECTORY "data/languages")
|
||||||
set(I18N_FILENAME i18n.qrc)
|
set(I18N_FILENAME i18n.qrc)
|
||||||
set(LANGUAGES en fr de)
|
set(LANGUAGES en fr_FR de)
|
||||||
|
|
||||||
# Add languages support.
|
# Add languages support.
|
||||||
add_subdirectory("${LANGUAGES_DIRECTORY}" "data/languages")
|
add_subdirectory("${LANGUAGES_DIRECTORY}" "data/languages")
|
||||||
|
|
@ -170,12 +174,6 @@ qt6_add_qml_module(Linphone
|
||||||
RESOURCES data/fonts.qrc
|
RESOURCES data/fonts.qrc
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
if(MSVC AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
|
|
||||||
install(FILES "$<TARGET_PDB_FILE:${TARGET_NAME}>" DESTINATION ${CMAKE_INSTALL_BINDIR})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
qt6_add_resources(Linphone "resources" PREFIX "/" FILES ${_LINPHONEAPP_RC_FILES})
|
qt6_add_resources(Linphone "resources" PREFIX "/" FILES ${_LINPHONEAPP_RC_FILES})
|
||||||
set_property(TARGET Linphone PROPERTY POSITION_INDEPENDENT_CODE ON) #Need by Qt
|
set_property(TARGET Linphone PROPERTY POSITION_INDEPENDENT_CODE ON) #Need by Qt
|
||||||
|
|
||||||
|
|
@ -201,7 +199,6 @@ set_target_properties(${TARGET_NAME} PROPERTIES
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
set_target_properties(${TARGET_NAME} PROPERTIES PDB_NAME "${EXECUTABLE_NAME}_app")
|
set_target_properties(${TARGET_NAME} PROPERTIES PDB_NAME "${EXECUTABLE_NAME}_app")
|
||||||
endif()
|
endif()
|
||||||
set_target_properties(${TARGET_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
if(ENABLE_SCREENSHARING)
|
if(ENABLE_SCREENSHARING)
|
||||||
|
|
@ -217,7 +214,6 @@ foreach(T ${APP_TARGETS})
|
||||||
target_link_libraries(${TARGET_NAME} PUBLIC ${T})
|
target_link_libraries(${TARGET_NAME} PUBLIC ${T})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
target_link_libraries(${TARGET_NAME} PRIVATE Qt6::Core)
|
|
||||||
foreach(T ${QT_PACKAGES})
|
foreach(T ${QT_PACKAGES})
|
||||||
target_link_libraries(${TARGET_NAME} PRIVATE Qt6::${T})
|
target_link_libraries(${TARGET_NAME} PRIVATE Qt6::${T})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "App.hpp"
|
#include "App.hpp"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QFileSelector>
|
#include <QFileSelector>
|
||||||
|
|
@ -52,19 +53,9 @@
|
||||||
#include "core/call/CallList.hpp"
|
#include "core/call/CallList.hpp"
|
||||||
#include "core/call/CallProxy.hpp"
|
#include "core/call/CallProxy.hpp"
|
||||||
#include "core/camera/CameraGui.hpp"
|
#include "core/camera/CameraGui.hpp"
|
||||||
#include "core/chat/ChatProxy.hpp"
|
|
||||||
#include "core/chat/files/ChatMessageFileProxy.hpp"
|
|
||||||
#include "core/chat/message/ChatMessageGui.hpp"
|
|
||||||
#include "core/chat/message/EventLogGui.hpp"
|
|
||||||
#include "core/chat/message/EventLogList.hpp"
|
|
||||||
#include "core/chat/message/EventLogProxy.hpp"
|
|
||||||
#include "core/chat/message/content/ChatMessageContentGui.hpp"
|
|
||||||
#include "core/chat/message/content/ChatMessageContentProxy.hpp"
|
|
||||||
#include "core/chat/message/imdn/ImdnStatusProxy.hpp"
|
|
||||||
#include "core/conference/ConferenceGui.hpp"
|
#include "core/conference/ConferenceGui.hpp"
|
||||||
#include "core/conference/ConferenceInfoGui.hpp"
|
#include "core/conference/ConferenceInfoGui.hpp"
|
||||||
#include "core/conference/ConferenceInfoProxy.hpp"
|
#include "core/conference/ConferenceInfoProxy.hpp"
|
||||||
#include "core/emoji/EmojiProxy.hpp"
|
|
||||||
#include "core/fps-counter/FPSCounter.hpp"
|
#include "core/fps-counter/FPSCounter.hpp"
|
||||||
#include "core/friend/FriendCore.hpp"
|
#include "core/friend/FriendCore.hpp"
|
||||||
#include "core/friend/FriendGui.hpp"
|
#include "core/friend/FriendGui.hpp"
|
||||||
|
|
@ -73,50 +64,34 @@
|
||||||
#include "core/notifier/Notifier.hpp"
|
#include "core/notifier/Notifier.hpp"
|
||||||
#include "core/participant/ParticipantDeviceProxy.hpp"
|
#include "core/participant/ParticipantDeviceProxy.hpp"
|
||||||
#include "core/participant/ParticipantGui.hpp"
|
#include "core/participant/ParticipantGui.hpp"
|
||||||
#include "core/participant/ParticipantInfoProxy.hpp"
|
|
||||||
#include "core/participant/ParticipantProxy.hpp"
|
#include "core/participant/ParticipantProxy.hpp"
|
||||||
#include "core/payload-type/PayloadTypeCore.hpp"
|
#include "core/payload-type/PayloadTypeCore.hpp"
|
||||||
#include "core/payload-type/PayloadTypeGui.hpp"
|
#include "core/payload-type/PayloadTypeGui.hpp"
|
||||||
#include "core/payload-type/PayloadTypeProxy.hpp"
|
#include "core/payload-type/PayloadTypeProxy.hpp"
|
||||||
#include "core/phone-number/PhoneNumber.hpp"
|
#include "core/phone-number/PhoneNumber.hpp"
|
||||||
#include "core/phone-number/PhoneNumberProxy.hpp"
|
#include "core/phone-number/PhoneNumberProxy.hpp"
|
||||||
#include "core/recorder/RecorderGui.hpp"
|
|
||||||
#include "core/register/RegisterPage.hpp"
|
#include "core/register/RegisterPage.hpp"
|
||||||
#include "core/screen/ScreenList.hpp"
|
#include "core/screen/ScreenList.hpp"
|
||||||
#include "core/screen/ScreenProxy.hpp"
|
#include "core/screen/ScreenProxy.hpp"
|
||||||
#include "core/search/MagicSearchProxy.hpp"
|
#include "core/search/MagicSearchProxy.hpp"
|
||||||
#include "core/setting/SettingsCore.hpp"
|
#include "core/setting/SettingsCore.hpp"
|
||||||
#include "core/singleapplication/singleapplication.h"
|
#include "core/singleapplication/singleapplication.h"
|
||||||
#include "core/sound-player/SoundPlayerGui.hpp"
|
|
||||||
#include "core/timezone/TimeZoneProxy.hpp"
|
#include "core/timezone/TimeZoneProxy.hpp"
|
||||||
#include "core/translator/DefaultTranslatorCore.hpp"
|
#include "core/translator/DefaultTranslatorCore.hpp"
|
||||||
#include "core/variant/VariantList.hpp"
|
#include "core/variant/VariantList.hpp"
|
||||||
#include "core/videoSource/VideoSourceDescriptorGui.hpp"
|
#include "core/videoSource/VideoSourceDescriptorGui.hpp"
|
||||||
#include "model/friend/FriendsManager.hpp"
|
|
||||||
#include "model/object/VariantObject.hpp"
|
#include "model/object/VariantObject.hpp"
|
||||||
#include "model/tool/ToolModel.hpp"
|
#include "model/tool/ToolModel.hpp"
|
||||||
#include "tool/Constants.hpp"
|
#include "tool/Constants.hpp"
|
||||||
#include "tool/EnumsToString.hpp"
|
#include "tool/EnumsToString.hpp"
|
||||||
#include "tool/Utils.hpp"
|
#include "tool/Utils.hpp"
|
||||||
#include "tool/accessibility/AccessibilityHelper.hpp"
|
|
||||||
#include "tool/accessibility/FocusHelper.hpp"
|
|
||||||
#include "tool/accessibility/KeyboardShortcuts.hpp"
|
|
||||||
#include "tool/native/DesktopTools.hpp"
|
#include "tool/native/DesktopTools.hpp"
|
||||||
#include "tool/providers/AvatarProvider.hpp"
|
#include "tool/providers/AvatarProvider.hpp"
|
||||||
#include "tool/providers/EmojiProvider.hpp"
|
|
||||||
#include "tool/providers/ImageProvider.hpp"
|
#include "tool/providers/ImageProvider.hpp"
|
||||||
#include "tool/providers/ScreenProvider.hpp"
|
#include "tool/providers/ScreenProvider.hpp"
|
||||||
#include "tool/providers/ThumbnailProvider.hpp"
|
|
||||||
#include "tool/request/CallbackHelper.hpp"
|
#include "tool/request/CallbackHelper.hpp"
|
||||||
#include "tool/request/RequestDialog.hpp"
|
#include "tool/request/RequestDialog.hpp"
|
||||||
#include "tool/thread/Thread.hpp"
|
#include "tool/thread/Thread.hpp"
|
||||||
#include "tool/ui/DashRectangle.hpp"
|
|
||||||
|
|
||||||
#if defined(Q_OS_MACOS)
|
|
||||||
#include "core/event-count-notifier/EventCountNotifierMacOs.hpp"
|
|
||||||
#else
|
|
||||||
#include "core/event-count-notifier/EventCountNotifierSystemTrayIcon.hpp"
|
|
||||||
#endif // if defined(Q_OS_MACOS)
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(App)
|
DEFINE_ABSTRACT_OBJECT(App)
|
||||||
|
|
||||||
|
|
@ -267,7 +242,9 @@ void App::setAutoStart(bool enabled) {
|
||||||
|
|
||||||
void App::setAutoStart(bool enabled) {
|
void App::setAutoStart(bool enabled) {
|
||||||
QSettings settings(AutoStartSettingsFilePath, QSettings::NativeFormat);
|
QSettings settings(AutoStartSettingsFilePath, QSettings::NativeFormat);
|
||||||
if (enabled) settings.setValue(EXECUTABLE_NAME, QDir::toNativeSeparators(applicationFilePath()));
|
QString parameters;
|
||||||
|
if (!mSettings->getExitOnClose()) parameters = " --minimized";
|
||||||
|
if (enabled) settings.setValue(EXECUTABLE_NAME, QDir::toNativeSeparators(applicationFilePath()) + parameters);
|
||||||
else settings.remove(EXECUTABLE_NAME);
|
else settings.remove(EXECUTABLE_NAME);
|
||||||
|
|
||||||
mAutoStart = enabled;
|
mAutoStart = enabled;
|
||||||
|
|
@ -282,14 +259,10 @@ void App::setAutoStart(bool enabled) {
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
App::App(int &argc, char *argv[])
|
App::App(int &argc, char *argv[])
|
||||||
: SingleApplication(argc, argv, true, Mode::User | Mode::ExcludeAppPath | Mode::ExcludeAppVersion) {
|
: SingleApplication(argc, argv, true, Mode::User | Mode::ExcludeAppPath | Mode::ExcludeAppVersion) {
|
||||||
// Do not use APPLICATION_NAME here.
|
// Do not use APPLICATION_NAME here.
|
||||||
// The EXECUTABLE_NAME will be used in qt standard paths. It's our goal.
|
// The EXECUTABLE_NAME will be used in qt standard paths. It's our goal.
|
||||||
QDir::setCurrent(
|
|
||||||
QCoreApplication::applicationDirPath()); // Set working directory as the executable to allow relative paths.
|
|
||||||
QThread::currentThread()->setPriority(QThread::HighPriority);
|
QThread::currentThread()->setPriority(QThread::HighPriority);
|
||||||
qDebug() << "app thread is" << QThread::currentThread();
|
|
||||||
lDebug() << "Starting app with Qt version" << qVersion();
|
|
||||||
QCoreApplication::setApplicationName(EXECUTABLE_NAME);
|
QCoreApplication::setApplicationName(EXECUTABLE_NAME);
|
||||||
QApplication::setOrganizationDomain(EXECUTABLE_NAME);
|
QApplication::setOrganizationDomain(EXECUTABLE_NAME);
|
||||||
QCoreApplication::setApplicationVersion(APPLICATION_SEMVER);
|
QCoreApplication::setApplicationVersion(APPLICATION_SEMVER);
|
||||||
|
|
@ -306,7 +279,7 @@ App::App(int &argc, char *argv[])
|
||||||
.arg(applicationVersion())
|
.arg(applicationVersion())
|
||||||
.arg(Utils::getOsProduct())
|
.arg(Utils::getOsProduct())
|
||||||
.arg(qVersion());
|
.arg(qVersion());
|
||||||
lInfo() << "at " << QDir().absolutePath();
|
|
||||||
mCurrentDate = QDate::currentDate();
|
mCurrentDate = QDate::currentDate();
|
||||||
mAutoStart = autoStartEnabled();
|
mAutoStart = autoStartEnabled();
|
||||||
mDateUpdateTimer.setInterval(60000);
|
mDateUpdateTimer.setInterval(60000);
|
||||||
|
|
@ -318,12 +291,7 @@ App::App(int &argc, char *argv[])
|
||||||
emit currentDateChanged();
|
emit currentDateChanged();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mEventCountNotifier = new EventCountNotifier(this);
|
|
||||||
mDateUpdateTimer.start();
|
mDateUpdateTimer.start();
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
exportDesktopFile();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
App::~App() {
|
App::~App() {
|
||||||
|
|
@ -337,7 +305,7 @@ void App::setSelf(QSharedPointer<App>(me)) {
|
||||||
auto callCore = CallCore::create(call);
|
auto callCore = CallCore::create(call);
|
||||||
mCoreModelConnection->invokeToCore([this, callCore] {
|
mCoreModelConnection->invokeToCore([this, callCore] {
|
||||||
auto callGui = new CallGui(callCore);
|
auto callGui = new CallGui(callCore);
|
||||||
auto win = getOrCreateCallsWindow(QVariant::fromValue(callGui));
|
auto win = getCallsWindow(QVariant::fromValue(callGui));
|
||||||
Utils::smartShowWindow(win);
|
Utils::smartShowWindow(win);
|
||||||
auto mainwin = getMainWindow();
|
auto mainwin = getMainWindow();
|
||||||
QMetaObject::invokeMethod(mainwin, "callCreated");
|
QMetaObject::invokeMethod(mainwin, "callCreated");
|
||||||
|
|
@ -381,106 +349,21 @@ void App::setSelf(QSharedPointer<App>(me)) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mCoreModelConnection->makeConnectToModel(&CoreModel::authenticationRequested, &App::onAuthenticationRequested);
|
mCoreModelConnection->makeConnectToModel(&CoreModel::authenticationRequested, &App::onAuthenticationRequested);
|
||||||
// Config error message
|
|
||||||
mCoreModelConnection->makeConnectToModel(
|
|
||||||
&CoreModel::configuringStatus, [this](const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::ConfiguringState status, const std::string &message) {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
if (status == linphone::ConfiguringState::Failed) {
|
|
||||||
mCoreModelConnection->invokeToCore([this, message]() {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
//: Error
|
|
||||||
Utils::showInformationPopup(
|
|
||||||
tr("info_popup_error_title"),
|
|
||||||
tr("info_popup_configuration_failed_message").arg(Utils::coreStringToAppString(message)),
|
|
||||||
false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mCoreModelConnection->makeConnectToModel(
|
|
||||||
&CoreModel::accountAdded,
|
|
||||||
[this](const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::Account> &account) {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
if (CoreModel::getInstance()->mConfigStatus == linphone::ConfiguringState::Successful) {
|
|
||||||
bool accountConnected = account && account->getState() == linphone::RegistrationState::Ok;
|
|
||||||
mCoreModelConnection->invokeToCore([this, accountConnected]() {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
// There is an account added by a remote provisioning, force switching to main page
|
|
||||||
// because the account may not be connected already
|
|
||||||
// if (accountConnected)
|
|
||||||
if (mPossiblyLookForAddedAccount) {
|
|
||||||
QMetaObject::invokeMethod(mMainWindow, "openMainPage", Qt::DirectConnection,
|
|
||||||
Q_ARG(QVariant, accountConnected));
|
|
||||||
}
|
|
||||||
mPossiblyLookForAddedAccount = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Synchronize state for because linphoneCore was ran before any connections.
|
// Synchronize state for because linphoneCore was ran before any connections.
|
||||||
mCoreModelConnection->invokeToModel([this]() {
|
mCoreModelConnection->invokeToModel([this]() {
|
||||||
auto state = CoreModel::getInstance()->getCore()->getGlobalState();
|
auto state = CoreModel::getInstance()->getCore()->getGlobalState();
|
||||||
mCoreModelConnection->invokeToCore([this, state] { setCoreStarted(state == linphone::GlobalState::On); });
|
mCoreModelConnection->invokeToCore([this, state] { setCoreStarted(state == linphone::GlobalState::On); });
|
||||||
});
|
});
|
||||||
|
|
||||||
mCoreModelConnection->makeConnectToModel(&CoreModel::unreadNotificationsChanged, [this] {
|
|
||||||
int n = mEventCountNotifier->getCurrentEventCount();
|
|
||||||
mCoreModelConnection->invokeToCore([this, n] { mEventCountNotifier->notifyEventCount(n); });
|
|
||||||
});
|
|
||||||
mCoreModelConnection->makeConnectToModel(&CoreModel::defaultAccountChanged, [this] {
|
|
||||||
int n = mEventCountNotifier->getCurrentEventCount();
|
|
||||||
mCoreModelConnection->invokeToCore([this, n] {
|
|
||||||
mEventCountNotifier->notifyEventCount(n);
|
|
||||||
emit defaultAccountChanged();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check update
|
|
||||||
mCoreModelConnection->makeConnectToModel(
|
|
||||||
&CoreModel::versionUpdateCheckResultReceived,
|
|
||||||
[this](const std::shared_ptr<linphone::Core> &core, linphone::VersionUpdateCheckResult result,
|
|
||||||
const std::string &version, const std::string &url, bool checkRequestedByUser) {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
mCoreModelConnection->invokeToCore([this, result, version, url, checkRequestedByUser] {
|
|
||||||
switch (result) {
|
|
||||||
case linphone::VersionUpdateCheckResult::Error:
|
|
||||||
Utils::showInformationPopup(tr("info_popup_error_title"),
|
|
||||||
//: An error occured while trying to check update. Please
|
|
||||||
//: try again later or contact support team.
|
|
||||||
tr("info_popup_error_checking_update"), false);
|
|
||||||
break;
|
|
||||||
case linphone::VersionUpdateCheckResult::NewVersionAvailable: {
|
|
||||||
QString downloadLink =
|
|
||||||
QStringLiteral("<a href='%1'><font color='DefaultStyle.main2_600'>%2</a>")
|
|
||||||
.arg(url)
|
|
||||||
//: Download it !
|
|
||||||
.arg(tr("info_popup_new_version_download_label"));
|
|
||||||
Utils::showInformationPopup(
|
|
||||||
//: New version available !
|
|
||||||
tr("info_popup_new_version_available_title"),
|
|
||||||
//: A new version of Linphone (%1) is available. %2
|
|
||||||
tr("info_popup_new_version_available_message").arg(version).arg(downloadLink));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case linphone::VersionUpdateCheckResult::UpToDate:
|
|
||||||
if (checkRequestedByUser)
|
|
||||||
//: Up to date
|
|
||||||
Utils::showInformationPopup(tr("info_popup_version_up_to_date_title"),
|
|
||||||
//: Your version is up to date
|
|
||||||
tr("info_popup_version_up_to_date_message"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------
|
||||||
mCliModelConnection = SafeConnection<App, CliModel>::create(me, CliModel::getInstance());
|
mCliModelConnection = SafeConnection<App, CliModel>::create(me, CliModel::getInstance());
|
||||||
mCliModelConnection->makeConnectToCore(&App::receivedMessage, [this](int, const QByteArray &byteArray) {
|
mCliModelConnection->makeConnectToCore(&App::receivedMessage, [this](int, const QByteArray &byteArray) {
|
||||||
QString command(byteArray);
|
QString command(byteArray);
|
||||||
if (command.isEmpty()) {
|
if (command.isEmpty()) {
|
||||||
lInfo() << log().arg("Check with CliModel for commands");
|
lDebug() << log().arg("Check with CliModel for commands");
|
||||||
mCliModelConnection->invokeToModel([]() { CliModel::getInstance()->runProcess(); });
|
mCliModelConnection->invokeToModel([]() { CliModel::getInstance()->runProcess(); });
|
||||||
} else {
|
} else {
|
||||||
lInfo() << log().arg("Received command from other application: `%1`.").arg(command);
|
qInfo() << QStringLiteral("Received command from other application: `%1`.").arg(command);
|
||||||
mCliModelConnection->invokeToModel([command]() { CliModel::getInstance()->executeCommand(command); });
|
mCliModelConnection->invokeToModel([command]() { CliModel::getInstance()->executeCommand(command); });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -493,22 +376,13 @@ App *App::getInstance() {
|
||||||
return dynamic_cast<App *>(QApplication::instance());
|
return dynamic_cast<App *>(QApplication::instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread *App::getLinphoneThread() {
|
QThread *App::getLinphoneThread() {
|
||||||
return App::getInstance()->mLinphoneThread;
|
return App::getInstance()->mLinphoneThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
Notifier *App::getNotifier() const {
|
Notifier *App::getNotifier() const {
|
||||||
return mNotifier;
|
return mNotifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventCountNotifier *App::getEventCountNotifier() {
|
|
||||||
return mEventCountNotifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
int App::getEventCount() const {
|
|
||||||
return mEventCountNotifier ? mEventCountNotifier->getEventCount() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
// Initializations
|
// Initializations
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
|
|
@ -548,12 +422,10 @@ void App::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::initCore() {
|
void App::initCore() {
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
// Core. Manage the logger so it must be instantiate at first.
|
// Core. Manage the logger so it must be instantiate at first.
|
||||||
CoreModel::create("", mLinphoneThread);
|
CoreModel::create("", mLinphoneThread);
|
||||||
if (mParser->isSet("verbose")) QtLogger::enableVerbose(true);
|
if (mParser->isSet("verbose")) QtLogger::enableVerbose(true);
|
||||||
if (mParser->isSet("qt-logs-only")) QtLogger::enableQtOnly(true);
|
if (mParser->isSet("qt-logs-only")) QtLogger::enableQtOnly(true);
|
||||||
qDebug() << "linphone thread is" << mLinphoneThread;
|
|
||||||
QMetaObject::invokeMethod(
|
QMetaObject::invokeMethod(
|
||||||
mLinphoneThread->getThreadId(),
|
mLinphoneThread->getThreadId(),
|
||||||
[this, settings = mSettings]() mutable {
|
[this, settings = mSettings]() mutable {
|
||||||
|
|
@ -611,12 +483,10 @@ void App::initCore() {
|
||||||
|
|
||||||
initCppInterfaces();
|
initCppInterfaces();
|
||||||
mEngine->addImageProvider(ImageProvider::ProviderId, new ImageProvider());
|
mEngine->addImageProvider(ImageProvider::ProviderId, new ImageProvider());
|
||||||
mEngine->addImageProvider(EmojiProvider::ProviderId, new EmojiProvider());
|
|
||||||
mEngine->addImageProvider(AvatarProvider::ProviderId, new AvatarProvider());
|
mEngine->addImageProvider(AvatarProvider::ProviderId, new AvatarProvider());
|
||||||
mEngine->addImageProvider(ScreenProvider::ProviderId, new ScreenProvider());
|
mEngine->addImageProvider(ScreenProvider::ProviderId, new ScreenProvider());
|
||||||
mEngine->addImageProvider(WindowProvider::ProviderId, new WindowProvider());
|
mEngine->addImageProvider(WindowProvider::ProviderId, new WindowProvider());
|
||||||
mEngine->addImageProvider(WindowIconProvider::ProviderId, new WindowIconProvider());
|
mEngine->addImageProvider(WindowIconProvider::ProviderId, new WindowIconProvider());
|
||||||
mEngine->addImageProvider(ThumbnailProvider::ProviderId, new ThumbnailProvider());
|
|
||||||
|
|
||||||
// Enable notifications.
|
// Enable notifications.
|
||||||
mNotifier = new Notifier(mEngine);
|
mNotifier = new Notifier(mEngine);
|
||||||
|
|
@ -627,14 +497,6 @@ void App::initCore() {
|
||||||
mAccountList->setInitialized(false);
|
mAccountList->setInitialized(false);
|
||||||
mAccountList->lUpdate(true);
|
mAccountList->lUpdate(true);
|
||||||
}
|
}
|
||||||
// Update global unread Notifications when an account updates his unread Notifications
|
|
||||||
connect(mAccountList.get(), &AccountList::unreadNotificationsChanged, this, [this]() {
|
|
||||||
lDebug() << "unreadNotificationsChanged of AccountList";
|
|
||||||
mCoreModelConnection->invokeToModel([this] {
|
|
||||||
int n = mEventCountNotifier->getCurrentEventCount();
|
|
||||||
mCoreModelConnection->invokeToCore([this, n] { mEventCountNotifier->notifyEventCount(n); });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
if (!mCallList) setCallList(CallList::create());
|
if (!mCallList) setCallList(CallList::create());
|
||||||
else mCallList->lUpdate();
|
else mCallList->lUpdate();
|
||||||
if (!mSettings) {
|
if (!mSettings) {
|
||||||
|
|
@ -660,7 +522,7 @@ void App::initCore() {
|
||||||
setLocale(settings->getConfigLocale());
|
setLocale(settings->getConfigLocale());
|
||||||
setAutoStart(settings->getAutoStart());
|
setAutoStart(settings->getAutoStart());
|
||||||
setQuitOnLastWindowClosed(settings->getExitOnClose());
|
setQuitOnLastWindowClosed(settings->getExitOnClose());
|
||||||
}
|
}
|
||||||
const QUrl url("qrc:/qt/qml/Linphone/view/Page/Window/Main/MainWindow.qml");
|
const QUrl url("qrc:/qt/qml/Linphone/view/Page/Window/Main/MainWindow.qml");
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
mEngine, &QQmlApplicationEngine::objectCreated, this,
|
mEngine, &QQmlApplicationEngine::objectCreated, this,
|
||||||
|
|
@ -672,45 +534,18 @@ void App::initCore() {
|
||||||
}
|
}
|
||||||
auto window = qobject_cast<QQuickWindow *>(obj);
|
auto window = qobject_cast<QQuickWindow *>(obj);
|
||||||
setMainWindow(window);
|
setMainWindow(window);
|
||||||
#if defined(__APPLE__)
|
#ifndef __APPLE__
|
||||||
setMacOSDockActions();
|
|
||||||
#else
|
|
||||||
// Enable TrayIconSystem.
|
// Enable TrayIconSystem.
|
||||||
if (!QSystemTrayIcon::isSystemTrayAvailable())
|
if (!QSystemTrayIcon::isSystemTrayAvailable())
|
||||||
qWarning("System tray not found on this system.");
|
qWarning("System tray not found on this system.");
|
||||||
else setSysTrayIcon();
|
else setSysTrayIcon();
|
||||||
#endif // if defined(__APPLE__)
|
#endif // ifndef __APPLE__
|
||||||
|
|
||||||
static bool firstOpen = true;
|
static bool firstOpen = true;
|
||||||
if (!firstOpen || !mParser->isSet("minimized")) {
|
if (!firstOpen || !mParser->isSet("minimized")) {
|
||||||
lDebug() << log().arg("Openning window");
|
lDebug() << log().arg("Openning window");
|
||||||
if (window) window->show();
|
window->show();
|
||||||
} else lInfo() << log().arg("Stay minimized");
|
} else lInfo() << log().arg("Stay minimized");
|
||||||
firstOpen = false;
|
firstOpen = false;
|
||||||
lInfo() << log().arg("Checking remote provisioning");
|
|
||||||
if (mIsRestarting) {
|
|
||||||
if (CoreModel::getInstance()->mConfigStatus == linphone::ConfiguringState::Failed) {
|
|
||||||
QMetaObject::invokeMethod(thread(), [this]() {
|
|
||||||
auto message = CoreModel::getInstance()->mConfigMessage;
|
|
||||||
//: not reachable
|
|
||||||
if (message.isEmpty()) message = tr("configuration_error_detail");
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
//: Error
|
|
||||||
Utils::showInformationPopup(
|
|
||||||
tr("info_popup_error_title"),
|
|
||||||
//: Remote provisioning failed : %1
|
|
||||||
tr("info_popup_configuration_failed_message").arg(message), false);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
mPossiblyLookForAddedAccount = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checkForUpdate();
|
|
||||||
mIsRestarting = false;
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------
|
|
||||||
lDebug() << log().arg("Creating KeyboardShortcuts");
|
|
||||||
KeyboardShortcuts::create(getMainWindow());
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
|
|
@ -722,6 +557,7 @@ void App::initCore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool installLocale(App &app, QTranslator &translator, const QLocale &locale) {
|
static inline bool installLocale(App &app, QTranslator &translator, const QLocale &locale) {
|
||||||
|
auto appPath = QStandardPaths::ApplicationsLocation;
|
||||||
bool ok = translator.load(locale.name(), Constants::LanguagePath);
|
bool ok = translator.load(locale.name(), Constants::LanguagePath);
|
||||||
ok = ok && app.installTranslator(&translator);
|
ok = ok && app.installTranslator(&translator);
|
||||||
if (ok) QLocale::setDefault(locale);
|
if (ok) QLocale::setDefault(locale);
|
||||||
|
|
@ -729,6 +565,7 @@ static inline bool installLocale(App &app, QTranslator &translator, const QLocal
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::initLocale() {
|
void App::initLocale() {
|
||||||
|
|
||||||
// Try to use preferred locale.
|
// Try to use preferred locale.
|
||||||
QString locale;
|
QString locale;
|
||||||
|
|
||||||
|
|
@ -736,28 +573,28 @@ void App::initLocale() {
|
||||||
mLocale = QLocale(QLocale::English);
|
mLocale = QLocale(QLocale::English);
|
||||||
if (!installLocale(*this, *mDefaultTranslatorCore, mLocale)) qFatal("Unable to install default translator.");
|
if (!installLocale(*this, *mDefaultTranslatorCore, mLocale)) qFatal("Unable to install default translator.");
|
||||||
|
|
||||||
// if (installLocale(*this, *mTranslatorCore, getLocale())) {
|
// if (installLocale(*this, *mTranslatorCore, getLocale())) {
|
||||||
// qDebug() << "installed locale" << getLocale().name();
|
// qDebug() << "installed locale" << getLocale().name();
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Try to use system locale.
|
// Try to use system locale.
|
||||||
// #ifdef Q_OS_MACOS
|
// #ifdef Q_OS_MACOS
|
||||||
// Use this workaround if there is still an issue about detecting wrong language from system on Mac. Qt doesn't
|
// Use this workaround if there is still an issue about detecting wrong language from system on Mac. Qt doesn't use
|
||||||
// use the current system language on QLocale::system(). So we need to get it from user settings and overwrite
|
// the current system language on QLocale::system(). So we need to get it from user settings and overwrite its
|
||||||
// its Locale.
|
// Locale.
|
||||||
// QSettings settings;
|
// QSettings settings;
|
||||||
// QString preferredLanguage = settings.value("AppleLanguages").toStringList().first();
|
// QString preferredLanguage = settings.value("AppleLanguages").toStringList().first();
|
||||||
// QStringList qtLocale = QLocale::system().name().split('_');
|
// QStringList qtLocale = QLocale::system().name().split('_');
|
||||||
// if(qtLocale[0] != preferredLanguage){
|
// if(qtLocale[0] != preferredLanguage){
|
||||||
// qInfo() << "Override Qt language from " << qtLocale[0] << " to the preferred language : " <<
|
// qInfo() << "Override Qt language from " << qtLocale[0] << " to the preferred language : " <<
|
||||||
// preferredLanguage; qtLocale[0] = preferredLanguage;
|
// preferredLanguage; qtLocale[0] = preferredLanguage;
|
||||||
// }
|
// }
|
||||||
// QLocale sysLocale = QLocale(qtLocale.join('_'));
|
// QLocale sysLocale = QLocale(qtLocale.join('_'));
|
||||||
// #else
|
// #else
|
||||||
QLocale sysLocale(QLocale::system().name()); // Use Locale from name because Qt has a bug where it didn't use
|
QLocale sysLocale(QLocale::system().name()); // Use Locale from name because Qt has a bug where it didn't use the
|
||||||
// the QLocale::language (aka : translator.language !=
|
// QLocale::language (aka : translator.language != locale.language) on
|
||||||
// locale.language) on Mac. #endif
|
// Mac. #endif
|
||||||
if (installLocale(*this, *mTranslatorCore, sysLocale)) {
|
if (installLocale(*this, *mTranslatorCore, sysLocale)) {
|
||||||
qDebug() << "installed sys locale" << sysLocale.name();
|
qDebug() << "installed sys locale" << sysLocale.name();
|
||||||
setLocale(sysLocale.name());
|
setLocale(sysLocale.name());
|
||||||
|
|
@ -795,18 +632,10 @@ void App::initCppInterfaces() {
|
||||||
"SettingsCpp", 1, 0, "SettingsCpp",
|
"SettingsCpp", 1, 0, "SettingsCpp",
|
||||||
[this](QQmlEngine *engine, QJSEngine *) -> QObject * { return mSettings.get(); });
|
[this](QQmlEngine *engine, QJSEngine *) -> QObject * { return mSettings.get(); });
|
||||||
|
|
||||||
qmlRegisterSingletonType<AccessibilityHelper>(
|
|
||||||
"AccessibilityHelperCpp", 1, 0, "AccessibilityHelperCpp",
|
|
||||||
[](QQmlEngine *engine, QJSEngine *) -> QObject * { return new AccessibilityHelper(engine); });
|
|
||||||
|
|
||||||
qmlRegisterType<FocusHelper>("CustomControls", 1, 0, "FocusHelper");
|
|
||||||
|
|
||||||
qmlRegisterType<DashRectangle>(Constants::MainQmlUri, 1, 0, "DashRectangle");
|
|
||||||
qmlRegisterType<PhoneNumberProxy>(Constants::MainQmlUri, 1, 0, "PhoneNumberProxy");
|
qmlRegisterType<PhoneNumberProxy>(Constants::MainQmlUri, 1, 0, "PhoneNumberProxy");
|
||||||
qmlRegisterType<VariantObject>(Constants::MainQmlUri, 1, 0, "VariantObject");
|
qmlRegisterType<VariantObject>(Constants::MainQmlUri, 1, 0, "VariantObject");
|
||||||
qmlRegisterType<VariantList>(Constants::MainQmlUri, 1, 0, "VariantList");
|
qmlRegisterType<VariantList>(Constants::MainQmlUri, 1, 0, "VariantList");
|
||||||
|
|
||||||
qmlRegisterType<ParticipantInfoProxy>(Constants::MainQmlUri, 1, 0, "ParticipantInfoProxy");
|
|
||||||
qmlRegisterType<ParticipantProxy>(Constants::MainQmlUri, 1, 0, "ParticipantProxy");
|
qmlRegisterType<ParticipantProxy>(Constants::MainQmlUri, 1, 0, "ParticipantProxy");
|
||||||
qmlRegisterType<ParticipantGui>(Constants::MainQmlUri, 1, 0, "ParticipantGui");
|
qmlRegisterType<ParticipantGui>(Constants::MainQmlUri, 1, 0, "ParticipantGui");
|
||||||
qmlRegisterType<ConferenceInfoProxy>(Constants::MainQmlUri, 1, 0, "ConferenceInfoProxy");
|
qmlRegisterType<ConferenceInfoProxy>(Constants::MainQmlUri, 1, 0, "ConferenceInfoProxy");
|
||||||
|
|
@ -823,16 +652,6 @@ void App::initCppInterfaces() {
|
||||||
qmlRegisterType<CallHistoryProxy>(Constants::MainQmlUri, 1, 0, "CallHistoryProxy");
|
qmlRegisterType<CallHistoryProxy>(Constants::MainQmlUri, 1, 0, "CallHistoryProxy");
|
||||||
qmlRegisterType<CallGui>(Constants::MainQmlUri, 1, 0, "CallGui");
|
qmlRegisterType<CallGui>(Constants::MainQmlUri, 1, 0, "CallGui");
|
||||||
qmlRegisterType<CallProxy>(Constants::MainQmlUri, 1, 0, "CallProxy");
|
qmlRegisterType<CallProxy>(Constants::MainQmlUri, 1, 0, "CallProxy");
|
||||||
qmlRegisterType<ChatList>(Constants::MainQmlUri, 1, 0, "ChatList");
|
|
||||||
qmlRegisterType<ChatProxy>(Constants::MainQmlUri, 1, 0, "ChatProxy");
|
|
||||||
qmlRegisterType<ChatGui>(Constants::MainQmlUri, 1, 0, "ChatGui");
|
|
||||||
qmlRegisterType<EventLogGui>(Constants::MainQmlUri, 1, 0, "EventLogGui");
|
|
||||||
qmlRegisterType<ChatMessageGui>(Constants::MainQmlUri, 1, 0, "ChatMessageGui");
|
|
||||||
qmlRegisterType<EventLogList>(Constants::MainQmlUri, 1, 0, "EventLogList");
|
|
||||||
qmlRegisterType<EventLogProxy>(Constants::MainQmlUri, 1, 0, "EventLogProxy");
|
|
||||||
qmlRegisterType<ChatMessageContentProxy>(Constants::MainQmlUri, 1, 0, "ChatMessageContentProxy");
|
|
||||||
qmlRegisterType<ChatMessageFileProxy>(Constants::MainQmlUri, 1, 0, "ChatMessageFileProxy");
|
|
||||||
qmlRegisterType<ChatMessageContentGui>(Constants::MainQmlUri, 1, 0, "ChatMessageContentGui");
|
|
||||||
qmlRegisterUncreatableType<ConferenceCore>(Constants::MainQmlUri, 1, 0, "ConferenceCore",
|
qmlRegisterUncreatableType<ConferenceCore>(Constants::MainQmlUri, 1, 0, "ConferenceCore",
|
||||||
QLatin1String("Uncreatable"));
|
QLatin1String("Uncreatable"));
|
||||||
qmlRegisterType<ConferenceGui>(Constants::MainQmlUri, 1, 0, "ConferenceGui");
|
qmlRegisterType<ConferenceGui>(Constants::MainQmlUri, 1, 0, "ConferenceGui");
|
||||||
|
|
@ -842,11 +661,6 @@ void App::initCppInterfaces() {
|
||||||
qmlRegisterType<MagicSearchList>(Constants::MainQmlUri, 1, 0, "MagicSearchList");
|
qmlRegisterType<MagicSearchList>(Constants::MainQmlUri, 1, 0, "MagicSearchList");
|
||||||
qmlRegisterType<CameraGui>(Constants::MainQmlUri, 1, 0, "CameraGui");
|
qmlRegisterType<CameraGui>(Constants::MainQmlUri, 1, 0, "CameraGui");
|
||||||
qmlRegisterType<FPSCounter>(Constants::MainQmlUri, 1, 0, "FPSCounter");
|
qmlRegisterType<FPSCounter>(Constants::MainQmlUri, 1, 0, "FPSCounter");
|
||||||
qmlRegisterType<EmojiModel>(Constants::MainQmlUri, 1, 0, "EmojiModel");
|
|
||||||
qmlRegisterType<EmojiProxy>(Constants::MainQmlUri, 1, 0, "EmojiProxy");
|
|
||||||
qmlRegisterType<ImdnStatusProxy>(Constants::MainQmlUri, 1, 0, "ImdnStatusProxy");
|
|
||||||
qmlRegisterType<SoundPlayerGui>(Constants::MainQmlUri, 1, 0, "SoundPlayerGui");
|
|
||||||
qmlRegisterType<RecorderGui>(Constants::MainQmlUri, 1, 0, "RecorderGui");
|
|
||||||
|
|
||||||
qmlRegisterType<TimeZoneProxy>(Constants::MainQmlUri, 1, 0, "TimeZoneProxy");
|
qmlRegisterType<TimeZoneProxy>(Constants::MainQmlUri, 1, 0, "TimeZoneProxy");
|
||||||
|
|
||||||
|
|
@ -887,14 +701,6 @@ void App::initFonts() {
|
||||||
allFamilies << QFontDatabase::applicationFontFamilies(id);
|
allFamilies << QFontDatabase::applicationFontFamilies(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QDirIterator itEmojis(":/emoji/font/", QDirIterator::Subdirectories);
|
|
||||||
while (itEmojis.hasNext()) {
|
|
||||||
QString ttf = itEmojis.next();
|
|
||||||
if (itEmojis.fileInfo().isFile()) {
|
|
||||||
auto id = QFontDatabase::addApplicationFont(ttf);
|
|
||||||
allFamilies << QFontDatabase::applicationFontFamilies(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
QDirIterator itFonts(":/linux/font/", QDirIterator::Subdirectories);
|
QDirIterator itFonts(":/linux/font/", QDirIterator::Subdirectories);
|
||||||
while (itFonts.hasNext()) {
|
while (itFonts.hasNext()) {
|
||||||
|
|
@ -942,10 +748,8 @@ void App::clean() {
|
||||||
}
|
}
|
||||||
void App::restart() {
|
void App::restart() {
|
||||||
mCoreModelConnection->invokeToModel([this]() {
|
mCoreModelConnection->invokeToModel([this]() {
|
||||||
FriendsManager::getInstance()->clearMaps();
|
|
||||||
CoreModel::getInstance()->getCore()->stop();
|
CoreModel::getInstance()->getCore()->stop();
|
||||||
mCoreModelConnection->invokeToCore([this]() {
|
mCoreModelConnection->invokeToCore([this]() {
|
||||||
mIsRestarting = true;
|
|
||||||
closeCallsWindow();
|
closeCallsWindow();
|
||||||
setMainWindow(nullptr);
|
setMainWindow(nullptr);
|
||||||
mEngine->clearComponentCache();
|
mEngine->clearComponentCache();
|
||||||
|
|
@ -971,37 +775,34 @@ void App::createCommandParser() {
|
||||||
//: "A free and open source SIP video-phone."
|
//: "A free and open source SIP video-phone."
|
||||||
mParser->setApplicationDescription(tr("application_description"));
|
mParser->setApplicationDescription(tr("application_description"));
|
||||||
//: "Send an order to the application towards a command line"
|
//: "Send an order to the application towards a command line"
|
||||||
mParser->addPositionalArgument("command", tr("command_line_arg_order").replace("%1", APPLICATION_NAME),
|
mParser->addPositionalArgument("command", tr("command_line_arg_order").replace("%1", APPLICATION_NAME), "[command]");
|
||||||
"[command]");
|
|
||||||
mParser->addOptions({
|
mParser->addOptions({
|
||||||
//: "Show this help"
|
//: "Show this help"
|
||||||
{{"h", "help"}, tr("command_line_option_show_help")},
|
{{"h", "help"}, tr("command_line_option_show_help")},
|
||||||
|
|
||||||
//{"cli-help", tr("commandLineOptionCliHelp").replace("%1", APPLICATION_NAME)},
|
//{"cli-help", tr("commandLineOptionCliHelp").replace("%1", APPLICATION_NAME)},
|
||||||
|
|
||||||
//:"Show app version"
|
//:"Show app version"
|
||||||
{{"v", "version"}, tr("command_line_option_show_app_version")},
|
{{"v", "version"}, tr("command_line_option_show_app_version")},
|
||||||
|
|
||||||
//{"config", tr("command_line_option_config").replace("%1", EXECUTABLE_NAME),
|
//{"config", tr("command_line_option_config").replace("%1", EXECUTABLE_NAME), tr("command_line_option_config_arg")},
|
||||||
// tr("command_line_option_config_arg")},
|
|
||||||
|
|
||||||
{"fetch-config",
|
{"fetch-config",
|
||||||
//: "Specify the linphone configuration file to be fetched. It will be merged with the current
|
//: "Specify the linphone configuration file to be fetched. It will be merged with the current configuration."
|
||||||
//: configuration."
|
tr("command_line_option_config_to_fetch")
|
||||||
tr("command_line_option_config_to_fetch").replace("%1", EXECUTABLE_NAME),
|
.replace("%1", EXECUTABLE_NAME),
|
||||||
//: "URL, path or file"
|
//: "URL, path or file"
|
||||||
tr("command_line_option_config_to_fetch_arg")},
|
tr("command_line_option_config_to_fetch_arg")},
|
||||||
|
|
||||||
//{{"c", "call"}, tr("command_line_option_call").replace("%1", EXECUTABLE_NAME),
|
//{{"c", "call"}, tr("command_line_option_call").replace("%1", EXECUTABLE_NAME), tr("command_line_option_call_arg")},
|
||||||
// tr("command_line_option_call_arg")},
|
|
||||||
|
|
||||||
{"minimized", tr("command_line_option_minimized")},
|
{"minimized", tr("command_line_option_minimized")},
|
||||||
|
|
||||||
//: "Log to stdout some debug information while running"
|
//: "Log to stdout some debug information while running"
|
||||||
{{"V", "verbose"}, tr("command_line_option_log_to_stdout")},
|
{{"V", "verbose"}, tr("command_line_option_log_to_stdout")},
|
||||||
|
|
||||||
//: "Print only logs from the application"
|
//: "Print only logs from the application"
|
||||||
{"qt-logs-only", tr("command_line_option_print_app_logs_only")},
|
{"qt-logs-only", tr("command_line_option_print_app_logs_only")},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Should be call only at first start
|
// Should be call only at first start
|
||||||
|
|
@ -1054,9 +855,9 @@ bool App::notify(QObject *receiver, QEvent *event) {
|
||||||
try {
|
try {
|
||||||
done = QApplication::notify(receiver, event);
|
done = QApplication::notify(receiver, event);
|
||||||
} catch (const std::exception &ex) {
|
} catch (const std::exception &ex) {
|
||||||
lFatal() << log().arg("Exception has been catch in notify: %1").arg(ex.what());
|
lCritical() << log().arg("Exception has been catch in notify: %1").arg(ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
lFatal() << log().arg("Generic exeption has been catch in notify");
|
lCritical() << log().arg("Generic exeption has been catch in notify");
|
||||||
}
|
}
|
||||||
if (event->type() == QEvent::MouseButtonPress) {
|
if (event->type() == QEvent::MouseButtonPress) {
|
||||||
auto window = findParentWindow(receiver);
|
auto window = findParentWindow(receiver);
|
||||||
|
|
@ -1070,38 +871,7 @@ bool App::notify(QObject *receiver, QEvent *event) {
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::handleAppActivity() {
|
QQuickWindow *App::getCallsWindow(QVariant callGui) {
|
||||||
auto handle = [this](QSharedPointer<AccountCore> accountCore) {
|
|
||||||
if (!accountCore) return;
|
|
||||||
auto accountPresence = accountCore->getPresence();
|
|
||||||
if ((mMainWindow && mMainWindow->isActive() || (mCallsWindow && mCallsWindow->isActive())) &&
|
|
||||||
accountPresence == LinphoneEnums::Presence::Away)
|
|
||||||
accountCore->lSetPresence(LinphoneEnums::Presence::Online);
|
|
||||||
if (((!mMainWindow || !mMainWindow->isActive()) && (!mCallsWindow || !mCallsWindow->isActive())) &&
|
|
||||||
accountPresence == LinphoneEnums::Presence::Online)
|
|
||||||
accountCore->lSetPresence(LinphoneEnums::Presence::Away);
|
|
||||||
};
|
|
||||||
if (mAccountList) {
|
|
||||||
for (auto &account : mAccountList->getSharedList<AccountCore>())
|
|
||||||
handle(account);
|
|
||||||
} else {
|
|
||||||
connect(
|
|
||||||
this, &App::accountsChanged, this,
|
|
||||||
[this, &handle] {
|
|
||||||
if (mAccountList) {
|
|
||||||
for (auto &account : mAccountList->getSharedList<AccountCore>())
|
|
||||||
handle(account);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Qt::SingleShotConnection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QQuickWindow *App::getCallsWindow() {
|
|
||||||
return mCallsWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
QQuickWindow *App::getOrCreateCallsWindow(QVariant callGui) {
|
|
||||||
mustBeInMainThread(getClassName());
|
mustBeInMainThread(getClassName());
|
||||||
if (!mCallsWindow) {
|
if (!mCallsWindow) {
|
||||||
const QUrl callUrl("qrc:/qt/qml/Linphone/view/Page/Window/Call/CallsWindow.qml");
|
const QUrl callUrl("qrc:/qt/qml/Linphone/view/Page/Window/Call/CallsWindow.qml");
|
||||||
|
|
@ -1136,7 +906,6 @@ QQuickWindow *App::getOrCreateCallsWindow(QVariant callGui) {
|
||||||
}
|
}
|
||||||
// window->setParent(mMainWindow);
|
// window->setParent(mMainWindow);
|
||||||
mCallsWindow = window;
|
mCallsWindow = window;
|
||||||
connect(mCallsWindow, &QQuickWindow::activeChanged, this, &App::handleAppActivity);
|
|
||||||
}
|
}
|
||||||
if (!callGui.isNull() && callGui.isValid()) mCallsWindow->setProperty("call", callGui);
|
if (!callGui.isNull() && callGui.isValid()) mCallsWindow->setProperty("call", callGui);
|
||||||
return mCallsWindow;
|
return mCallsWindow;
|
||||||
|
|
@ -1147,7 +916,7 @@ void App::setCallsWindowProperty(const char *id, QVariant property) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::closeCallsWindow() {
|
void App::closeCallsWindow() {
|
||||||
if (mCallsWindow && mCallList && !mCallList->getHaveCall()) {
|
if (mCallsWindow) {
|
||||||
mCallsWindow->close();
|
mCallsWindow->close();
|
||||||
mCallsWindow->deleteLater();
|
mCallsWindow->deleteLater();
|
||||||
mCallsWindow = nullptr;
|
mCallsWindow = nullptr;
|
||||||
|
|
@ -1159,11 +928,8 @@ QQuickWindow *App::getMainWindow() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::setMainWindow(QQuickWindow *data) {
|
void App::setMainWindow(QQuickWindow *data) {
|
||||||
if (mMainWindow) disconnect(mMainWindow, &QQuickWindow::activeChanged, this, nullptr);
|
|
||||||
if (mMainWindow != data) {
|
if (mMainWindow != data) {
|
||||||
mMainWindow = data;
|
mMainWindow = data;
|
||||||
connect(mMainWindow, &QQuickWindow::activeChanged, this, &App::handleAppActivity);
|
|
||||||
handleAppActivity();
|
|
||||||
emit mainWindowChanged();
|
emit mainWindowChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1371,16 +1137,6 @@ bool App::event(QEvent *event) {
|
||||||
} else if (event->type() == QEvent::ApplicationStateChange) {
|
} else if (event->type() == QEvent::ApplicationStateChange) {
|
||||||
auto state = static_cast<QApplicationStateChangeEvent *>(event);
|
auto state = static_cast<QApplicationStateChangeEvent *>(event);
|
||||||
if (state->applicationState() == Qt::ApplicationActive) Utils::smartShowWindow(getLastActiveWindow());
|
if (state->applicationState() == Qt::ApplicationActive) Utils::smartShowWindow(getLastActiveWindow());
|
||||||
} else if (event->type() == QEvent::ApplicationActivate) {
|
|
||||||
for (int i = 0; i < getAccountList()->rowCount(); ++i) {
|
|
||||||
auto accountCore = getAccountList()->getAt<AccountCore>(i);
|
|
||||||
emit accountCore->lSetPresence(LinphoneEnums::Presence::Online, false, false);
|
|
||||||
}
|
|
||||||
} else if (event->type() == QEvent::ApplicationDeactivate) {
|
|
||||||
for (int i = 0; i < getAccountList()->rowCount(); ++i) {
|
|
||||||
auto accountCore = getAccountList()->getAt<AccountCore>(i);
|
|
||||||
emit accountCore->lSetPresence(LinphoneEnums::Presence::Away, false, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SingleApplication::event(event);
|
return SingleApplication::event(event);
|
||||||
|
|
@ -1393,7 +1149,6 @@ bool App::event(QEvent *event) {
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
|
|
||||||
void App::setSysTrayIcon() {
|
void App::setSysTrayIcon() {
|
||||||
qDebug() << "setSysTrayIcon";
|
|
||||||
QQuickWindow *root = getMainWindow();
|
QQuickWindow *root = getMainWindow();
|
||||||
QSystemTrayIcon *systemTrayIcon =
|
QSystemTrayIcon *systemTrayIcon =
|
||||||
(mSystemTrayIcon ? mSystemTrayIcon
|
(mSystemTrayIcon ? mSystemTrayIcon
|
||||||
|
|
@ -1409,7 +1164,7 @@ void App::setSysTrayIcon() {
|
||||||
//: "Afficher"
|
//: "Afficher"
|
||||||
restoreAction->setText(visible ? tr("hide_action") : tr("show_action"));
|
restoreAction->setText(visible ? tr("hide_action") : tr("show_action"));
|
||||||
};
|
};
|
||||||
setRestoreActionText(root ? root->isVisible() : false);
|
setRestoreActionText(root->isVisible());
|
||||||
connect(root, &QWindow::visibleChanged, restoreAction, setRestoreActionText);
|
connect(root, &QWindow::visibleChanged, restoreAction, setRestoreActionText);
|
||||||
|
|
||||||
root->connect(restoreAction, &QAction::triggered, this, [this, restoreAction](bool checked) {
|
root->connect(restoreAction, &QAction::triggered, this, [this, restoreAction](bool checked) {
|
||||||
|
|
@ -1425,9 +1180,6 @@ void App::setSysTrayIcon() {
|
||||||
QAction *quitAction = new QAction(tr("quit_action"), root);
|
QAction *quitAction = new QAction(tr("quit_action"), root);
|
||||||
root->connect(quitAction, &QAction::triggered, this, &App::quit);
|
root->connect(quitAction, &QAction::triggered, this, &App::quit);
|
||||||
|
|
||||||
//: "Mark all as read"
|
|
||||||
QAction *markAllReadAction = createMarkAsReadAction(root);
|
|
||||||
|
|
||||||
// trayIcon: Left click actions.
|
// trayIcon: Left click actions.
|
||||||
QMenu *menu = mSystemTrayIcon ? mSystemTrayIcon->contextMenu() : new QMenu();
|
QMenu *menu = mSystemTrayIcon ? mSystemTrayIcon->contextMenu() : new QMenu();
|
||||||
menu->clear();
|
menu->clear();
|
||||||
|
|
@ -1437,13 +1189,6 @@ void App::setSysTrayIcon() {
|
||||||
menu->addAction(restoreAction);
|
menu->addAction(restoreAction);
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
}
|
}
|
||||||
menu->addAction(markAllReadAction);
|
|
||||||
//: Check for update
|
|
||||||
if (mSettings->isCheckForUpdateAvailable()) {
|
|
||||||
QAction *checkForUpdateAction = new QAction(tr("check_for_update"), root);
|
|
||||||
root->connect(checkForUpdateAction, &QAction::triggered, this, [this] { checkForUpdate(true); });
|
|
||||||
menu->addAction(checkForUpdateAction);
|
|
||||||
}
|
|
||||||
menu->addAction(quitAction);
|
menu->addAction(quitAction);
|
||||||
if (!mSystemTrayIcon) {
|
if (!mSystemTrayIcon) {
|
||||||
systemTrayIcon->setContextMenu(menu); // This is a Qt bug. We cannot call setContextMenu more than once. So
|
systemTrayIcon->setContextMenu(menu); // This is a Qt bug. We cannot call setContextMenu more than once. So
|
||||||
|
|
@ -1463,24 +1208,6 @@ void App::setSysTrayIcon() {
|
||||||
if (!QSystemTrayIcon::isSystemTrayAvailable()) qInfo() << "System tray is not available";
|
if (!QSystemTrayIcon::isSystemTrayAvailable()) qInfo() << "System tray is not available";
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
|
||||||
// MacOS dock menu actions
|
|
||||||
//-----------------------------------------------------------
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
/**
|
|
||||||
* Set more actions to the MacOS Dock actions
|
|
||||||
* WARNING: call this function only on macOS
|
|
||||||
*/
|
|
||||||
void App::setMacOSDockActions() {
|
|
||||||
QMenu *menu = new QMenu();
|
|
||||||
QQuickWindow *root = getMainWindow();
|
|
||||||
QAction *markAllReadAction = createMarkAsReadAction(root);
|
|
||||||
menu->addAction(markAllReadAction);
|
|
||||||
menu->setAsDockMenu();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
// Locale TODO - App only in French now.
|
// Locale TODO - App only in French now.
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
|
|
@ -1522,48 +1249,3 @@ QString App::getSdkVersion() {
|
||||||
return tr('unknown');
|
return tr('unknown');
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QString App::getQtVersion() const {
|
|
||||||
return qVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
void App::checkForUpdate(bool requestedByUser) {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
if (CoreModel::getInstance() && mCoreModelConnection) {
|
|
||||||
mCoreModelConnection->invokeToModel([this, requestedByUser] {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
CoreModel::getInstance()->checkForUpdate(Utils::appStringToCoreString(applicationVersion()),
|
|
||||||
requestedByUser);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatGui *App::getCurrentChat() const {
|
|
||||||
return mCurrentChat;
|
|
||||||
}
|
|
||||||
|
|
||||||
void App::setCurrentChat(ChatGui *chat) {
|
|
||||||
if (chat != mCurrentChat) {
|
|
||||||
mCurrentChat = chat;
|
|
||||||
emit currentChatChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float App::getScreenRatio() const {
|
|
||||||
return mScreenRatio;
|
|
||||||
}
|
|
||||||
|
|
||||||
void App::setScreenRatio(float ratio) {
|
|
||||||
mScreenRatio = ratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction *App::createMarkAsReadAction(QQuickWindow *window) {
|
|
||||||
QAction *markAllReadAction = new QAction(tr("mark_all_read_action"), window);
|
|
||||||
window->connect(markAllReadAction, &QAction::triggered, this, [this] {
|
|
||||||
lDebug() << "Mark all as read";
|
|
||||||
emit mAccountList->lResetMissedCalls();
|
|
||||||
emit mAccountList->lResetUnreadMessages();
|
|
||||||
mCoreModelConnection->invokeToModel([this]() { CoreModel::getInstance()->unreadNotificationsChanged(); });
|
|
||||||
});
|
|
||||||
return markAllReadAction;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -18,14 +18,12 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QAction>
|
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
#include <QQmlApplicationEngine>
|
#include <QQmlApplicationEngine>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
|
||||||
#include "core/account/AccountProxy.hpp"
|
#include "core/account/AccountProxy.hpp"
|
||||||
#include "core/call/CallProxy.hpp"
|
#include "core/call/CallProxy.hpp"
|
||||||
#include "core/chat/ChatGui.hpp"
|
|
||||||
#include "core/setting/SettingsCore.hpp"
|
#include "core/setting/SettingsCore.hpp"
|
||||||
#include "core/singleapplication/singleapplication.h"
|
#include "core/singleapplication/singleapplication.h"
|
||||||
#include "model/cli/CliModel.hpp"
|
#include "model/cli/CliModel.hpp"
|
||||||
|
|
@ -33,7 +31,6 @@
|
||||||
#include "tool/AbstractObject.hpp"
|
#include "tool/AbstractObject.hpp"
|
||||||
|
|
||||||
class CallGui;
|
class CallGui;
|
||||||
class ChatGui;
|
|
||||||
class Thread;
|
class Thread;
|
||||||
class Notifier;
|
class Notifier;
|
||||||
class QQuickWindow;
|
class QQuickWindow;
|
||||||
|
|
@ -46,22 +43,17 @@ class App : public SingleApplication, public AbstractObject {
|
||||||
Q_PROPERTY(AccountList *accounts READ getAccounts NOTIFY accountsChanged)
|
Q_PROPERTY(AccountList *accounts READ getAccounts NOTIFY accountsChanged)
|
||||||
Q_PROPERTY(CallList *calls READ getCalls NOTIFY callsChanged)
|
Q_PROPERTY(CallList *calls READ getCalls NOTIFY callsChanged)
|
||||||
Q_PROPERTY(QString shortApplicationVersion READ getShortApplicationVersion CONSTANT)
|
Q_PROPERTY(QString shortApplicationVersion READ getShortApplicationVersion CONSTANT)
|
||||||
Q_PROPERTY(QString qtVersion READ getQtVersion CONSTANT)
|
|
||||||
Q_PROPERTY(QString gitBranchName READ getGitBranchName CONSTANT)
|
Q_PROPERTY(QString gitBranchName READ getGitBranchName CONSTANT)
|
||||||
Q_PROPERTY(QString sdkVersion READ getSdkVersion CONSTANT)
|
Q_PROPERTY(QString sdkVersion READ getSdkVersion CONSTANT)
|
||||||
Q_PROPERTY(ChatGui *currentChat READ getCurrentChat WRITE setCurrentChat NOTIFY currentChatChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
App(int &argc, char *argv[]);
|
App(int &argc, char *argv[]);
|
||||||
~App();
|
~App();
|
||||||
void setSelf(QSharedPointer<App>(me));
|
void setSelf(QSharedPointer<App>(me));
|
||||||
static App *getInstance();
|
static App *getInstance();
|
||||||
static Thread *getLinphoneThread();
|
static QThread *getLinphoneThread();
|
||||||
Notifier *getNotifier() const;
|
Notifier *getNotifier() const;
|
||||||
|
|
||||||
EventCountNotifier *getEventCountNotifier();
|
|
||||||
int getEventCount() const;
|
|
||||||
|
|
||||||
// App::postModelAsync(<lambda>) => run lambda in model thread and continue.
|
// App::postModelAsync(<lambda>) => run lambda in model thread and continue.
|
||||||
// App::postModelSync(<lambda>) => run lambda in current thread and block connection.
|
// App::postModelSync(<lambda>) => run lambda in current thread and block connection.
|
||||||
template <typename Func, typename... Args>
|
template <typename Func, typename... Args>
|
||||||
|
|
@ -127,10 +119,6 @@ public:
|
||||||
void restart();
|
void restart();
|
||||||
bool autoStartEnabled();
|
bool autoStartEnabled();
|
||||||
void setSysTrayIcon();
|
void setSysTrayIcon();
|
||||||
QSystemTrayIcon *getSystemTrayIcon() const {
|
|
||||||
return mSystemTrayIcon;
|
|
||||||
}
|
|
||||||
void updateSysTrayCount(int n);
|
|
||||||
QLocale getLocale();
|
QLocale getLocale();
|
||||||
|
|
||||||
void onLoggerInitialized();
|
void onLoggerInitialized();
|
||||||
|
|
@ -139,9 +127,7 @@ public:
|
||||||
bool getCoreStarted() const;
|
bool getCoreStarted() const;
|
||||||
void setCoreStarted(bool started);
|
void setCoreStarted(bool started);
|
||||||
|
|
||||||
QQuickWindow *getCallsWindow();
|
QQuickWindow *getCallsWindow(QVariant callGui = QVariant());
|
||||||
Q_INVOKABLE void handleAppActivity();
|
|
||||||
QQuickWindow *getOrCreateCallsWindow(QVariant callGui = QVariant());
|
|
||||||
void setCallsWindowProperty(const char *id, QVariant property);
|
void setCallsWindowProperty(const char *id, QVariant property);
|
||||||
void closeCallsWindow();
|
void closeCallsWindow();
|
||||||
|
|
||||||
|
|
@ -167,14 +153,6 @@ public:
|
||||||
QString getShortApplicationVersion();
|
QString getShortApplicationVersion();
|
||||||
QString getGitBranchName();
|
QString getGitBranchName();
|
||||||
QString getSdkVersion();
|
QString getSdkVersion();
|
||||||
QString getQtVersion() const;
|
|
||||||
|
|
||||||
Q_INVOKABLE void checkForUpdate(bool requestedByUser = false);
|
|
||||||
ChatGui *getCurrentChat() const;
|
|
||||||
void setCurrentChat(ChatGui *chat);
|
|
||||||
|
|
||||||
float getScreenRatio() const;
|
|
||||||
Q_INVOKABLE void setScreenRatio(float ratio);
|
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
Q_INVOKABLE void exportDesktopFile();
|
Q_INVOKABLE void exportDesktopFile();
|
||||||
|
|
@ -194,30 +172,22 @@ signals:
|
||||||
void mainWindowChanged();
|
void mainWindowChanged();
|
||||||
void coreStartedChanged(bool coreStarted);
|
void coreStartedChanged(bool coreStarted);
|
||||||
void accountsChanged();
|
void accountsChanged();
|
||||||
void defaultAccountChanged();
|
|
||||||
void callsChanged();
|
void callsChanged();
|
||||||
void currentDateChanged();
|
void currentDateChanged();
|
||||||
void currentChatChanged();
|
|
||||||
// void executeCommand(QString command);
|
// void executeCommand(QString command);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createCommandParser();
|
void createCommandParser();
|
||||||
QAction *createMarkAsReadAction(QQuickWindow *window);
|
|
||||||
void setMacOSDockActions(); // Should only be called on MacOS
|
|
||||||
void setAutoStart(bool enabled);
|
void setAutoStart(bool enabled);
|
||||||
void setLocale(QString configLocale);
|
void setLocale(QString configLocale);
|
||||||
|
|
||||||
QCommandLineParser *mParser = nullptr;
|
QCommandLineParser *mParser = nullptr;
|
||||||
Thread *mLinphoneThread = nullptr;
|
Thread *mLinphoneThread = nullptr;
|
||||||
Notifier *mNotifier = nullptr;
|
Notifier *mNotifier = nullptr;
|
||||||
EventCountNotifier *mEventCountNotifier = nullptr;
|
|
||||||
QSystemTrayIcon *mSystemTrayIcon = nullptr;
|
QSystemTrayIcon *mSystemTrayIcon = nullptr;
|
||||||
QQuickWindow *mMainWindow = nullptr;
|
QQuickWindow *mMainWindow = nullptr;
|
||||||
QQuickWindow *mCallsWindow = nullptr;
|
QQuickWindow *mCallsWindow = nullptr;
|
||||||
QQuickWindow *mLastActiveWindow = nullptr;
|
QQuickWindow *mLastActiveWindow = nullptr;
|
||||||
// Holds the current chat displayed in the view
|
|
||||||
// to know if we need to display the notification
|
|
||||||
ChatGui *mCurrentChat = nullptr;
|
|
||||||
QSharedPointer<SettingsCore> mSettings;
|
QSharedPointer<SettingsCore> mSettings;
|
||||||
QSharedPointer<AccountList> mAccountList;
|
QSharedPointer<AccountList> mAccountList;
|
||||||
QSharedPointer<CallList> mCallList;
|
QSharedPointer<CallList> mCallList;
|
||||||
|
|
@ -225,14 +195,11 @@ private:
|
||||||
QSharedPointer<SafeConnection<App, CliModel>> mCliModelConnection;
|
QSharedPointer<SafeConnection<App, CliModel>> mCliModelConnection;
|
||||||
bool mAutoStart = false;
|
bool mAutoStart = false;
|
||||||
bool mCoreStarted = false;
|
bool mCoreStarted = false;
|
||||||
bool mIsRestarting = false;
|
|
||||||
bool mPossiblyLookForAddedAccount = false;
|
|
||||||
QLocale mLocale = QLocale::system();
|
QLocale mLocale = QLocale::system();
|
||||||
DefaultTranslatorCore *mTranslatorCore = nullptr;
|
DefaultTranslatorCore *mTranslatorCore = nullptr;
|
||||||
DefaultTranslatorCore *mDefaultTranslatorCore = nullptr;
|
DefaultTranslatorCore *mDefaultTranslatorCore = nullptr;
|
||||||
QTimer mDateUpdateTimer;
|
QTimer mDateUpdateTimer;
|
||||||
QDate mCurrentDate;
|
QDate mCurrentDate;
|
||||||
float mScreenRatio = 1;
|
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -19,28 +19,6 @@ list(APPEND _LINPHONEAPP_SOURCES
|
||||||
core/camera/CameraGui.cpp
|
core/camera/CameraGui.cpp
|
||||||
core/camera/CameraDummy.cpp
|
core/camera/CameraDummy.cpp
|
||||||
core/camera/PreviewManager.cpp
|
core/camera/PreviewManager.cpp
|
||||||
core/chat/ChatCore.cpp
|
|
||||||
core/chat/ChatGui.cpp
|
|
||||||
core/chat/ChatList.cpp
|
|
||||||
core/chat/ChatProxy.cpp
|
|
||||||
core/chat/message/ChatMessageCore.cpp
|
|
||||||
core/chat/message/ChatMessageGui.cpp
|
|
||||||
core/chat/message/EventLogCore.cpp
|
|
||||||
core/chat/message/EventLogGui.cpp
|
|
||||||
core/chat/message/EventLogList.cpp
|
|
||||||
core/chat/message/EventLogProxy.cpp
|
|
||||||
core/chat/message/content/ChatMessageContentCore.cpp
|
|
||||||
core/chat/message/content/ChatMessageContentGui.cpp
|
|
||||||
core/chat/message/content/ChatMessageContentList.cpp
|
|
||||||
core/chat/message/content/ChatMessageContentProxy.cpp
|
|
||||||
core/chat/files/ChatMessageFileList.cpp
|
|
||||||
core/chat/files/ChatMessageFileProxy.cpp
|
|
||||||
core/chat/message/imdn/ImdnStatusList.cpp
|
|
||||||
core/chat/message/imdn/ImdnStatusProxy.cpp
|
|
||||||
core/emoji/EmojiList.cpp
|
|
||||||
core/emoji/EmojiModel.cpp
|
|
||||||
core/emoji/EmojiProxy.cpp
|
|
||||||
core/event-count-notifier/AbstractEventCountNotifier.cpp
|
|
||||||
core/fps-counter/FPSCounter.cpp
|
core/fps-counter/FPSCounter.cpp
|
||||||
core/friend/FriendCore.cpp
|
core/friend/FriendCore.cpp
|
||||||
core/friend/FriendGui.cpp
|
core/friend/FriendGui.cpp
|
||||||
|
|
@ -86,18 +64,10 @@ list(APPEND _LINPHONEAPP_SOURCES
|
||||||
core/participant/ParticipantDeviceProxy.cpp
|
core/participant/ParticipantDeviceProxy.cpp
|
||||||
core/participant/ParticipantList.cpp
|
core/participant/ParticipantList.cpp
|
||||||
core/participant/ParticipantProxy.cpp
|
core/participant/ParticipantProxy.cpp
|
||||||
core/participant/ParticipantInfoList.cpp
|
|
||||||
core/participant/ParticipantInfoProxy.cpp
|
|
||||||
|
|
||||||
core/screen/ScreenList.cpp
|
core/screen/ScreenList.cpp
|
||||||
core/screen/ScreenProxy.cpp
|
core/screen/ScreenProxy.cpp
|
||||||
|
|
||||||
core/sound-player/SoundPlayerCore.cpp
|
|
||||||
core/sound-player/SoundPlayerGui.cpp
|
|
||||||
|
|
||||||
core/recorder/RecorderCore.cpp
|
|
||||||
core/recorder/RecorderGui.cpp
|
|
||||||
|
|
||||||
core/videoSource/VideoSourceDescriptorCore.cpp
|
core/videoSource/VideoSourceDescriptorCore.cpp
|
||||||
core/videoSource/VideoSourceDescriptorGui.cpp
|
core/videoSource/VideoSourceDescriptorGui.cpp
|
||||||
|
|
||||||
|
|
@ -129,9 +99,5 @@ else() # Use QDBus for Linux
|
||||||
core/singleapplication/SingleApplicationDBusPrivate.hpp
|
core/singleapplication/SingleApplicationDBusPrivate.hpp
|
||||||
core/singleapplication/SingleApplicationDBus.cpp)
|
core/singleapplication/SingleApplicationDBus.cpp)
|
||||||
endif()
|
endif()
|
||||||
if(APPLE)
|
|
||||||
list(APPEND _LINPHONEAPP_SOURCES core/event-count-notifier/EventCountNotifierMacOs.m)
|
|
||||||
else()
|
|
||||||
list(APPEND _LINPHONEAPP_SOURCES core/event-count-notifier/EventCountNotifierSystemTrayIcon.cpp)
|
|
||||||
endif()
|
|
||||||
set(_LINPHONEAPP_SOURCES ${_LINPHONEAPP_SOURCES} PARENT_SCOPE)
|
set(_LINPHONEAPP_SOURCES ${_LINPHONEAPP_SOURCES} PARENT_SCOPE)
|
||||||
|
|
|
||||||
|
|
@ -43,18 +43,18 @@ AccountCore::AccountCore(const std::shared_ptr<linphone::Account> &account) : QO
|
||||||
auto address = account->getContactAddress();
|
auto address = account->getContactAddress();
|
||||||
mContactAddress = address ? Utils::coreStringToAppString(account->getContactAddress()->asStringUriOnly()) : "";
|
mContactAddress = address ? Utils::coreStringToAppString(account->getContactAddress()->asStringUriOnly()) : "";
|
||||||
auto params = account->getParams()->clone();
|
auto params = account->getParams()->clone();
|
||||||
auto identityAddress = params->getIdentityAddress();
|
auto identityAddress = params->getIdentityAddress()->clone();
|
||||||
mIdentityAddress = identityAddress ? Utils::coreStringToAppString(identityAddress->asStringUriOnly()) : "";
|
mIdentityAddress = identityAddress ? Utils::coreStringToAppString(identityAddress->asStringUriOnly()) : "";
|
||||||
mPictureUri = Utils::coreStringToAppString(params->getPictureUri());
|
mPictureUri = Utils::coreStringToAppString(params->getPictureUri());
|
||||||
mRegistrationState = LinphoneEnums::fromLinphone(account->getState());
|
mRegistrationState = LinphoneEnums::fromLinphone(account->getState());
|
||||||
mIsDefaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount() == account;
|
mIsDefaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount() == account;
|
||||||
mUnreadNotifications = account->getMissedCallsCount() + account->getUnreadChatMessageCount();
|
// mUnreadNotifications = account->getUnreadChatMessageCount() + account->getMissedCallsCount(); // TODO
|
||||||
|
mUnreadNotifications = account->getMissedCallsCount();
|
||||||
mDisplayName = Utils::coreStringToAppString(identityAddress->getDisplayName());
|
mDisplayName = Utils::coreStringToAppString(identityAddress->getDisplayName());
|
||||||
if (mDisplayName.isEmpty()) {
|
if (mDisplayName.isEmpty()) {
|
||||||
mDisplayName = ToolModel::getDisplayName(identityAddress);
|
mDisplayName = ToolModel::getDisplayName(identityAddress);
|
||||||
auto copyAddress = identityAddress->clone();
|
identityAddress->setDisplayName(Utils::appStringToCoreString(mDisplayName));
|
||||||
copyAddress->setDisplayName(Utils::appStringToCoreString(mDisplayName));
|
params->setIdentityAddress(identityAddress);
|
||||||
params->setIdentityAddress(copyAddress);
|
|
||||||
account->setParams(params);
|
account->setParams(params);
|
||||||
}
|
}
|
||||||
mRegisterEnabled = params->registerEnabled();
|
mRegisterEnabled = params->registerEnabled();
|
||||||
|
|
@ -65,11 +65,9 @@ AccountCore::AccountCore(const std::shared_ptr<linphone::Account> &account) : QO
|
||||||
<< "TLS"
|
<< "TLS"
|
||||||
<< "DTLS";
|
<< "DTLS";
|
||||||
mTransport = LinphoneEnums::toString(LinphoneEnums::fromLinphone(params->getTransport()));
|
mTransport = LinphoneEnums::toString(LinphoneEnums::fromLinphone(params->getTransport()));
|
||||||
mRegistrarUri =
|
mServerAddress =
|
||||||
params->getServerAddress() ? Utils::coreStringToAppString(params->getServerAddress()->asString()) : "";
|
params->getServerAddress() ? Utils::coreStringToAppString(params->getServerAddress()->asString()) : "";
|
||||||
auto routesAddresses = params->getRoutesAddresses();
|
mOutboundProxyEnabled = params->outboundProxyEnabled();
|
||||||
mOutboundProxyUri =
|
|
||||||
routesAddresses.empty() ? "" : Utils::coreStringToAppString(routesAddresses.front()->asString());
|
|
||||||
auto policy = params->getNatPolicy() ? params->getNatPolicy() : account->getCore()->createNatPolicy();
|
auto policy = params->getNatPolicy() ? params->getNatPolicy() : account->getCore()->createNatPolicy();
|
||||||
mStunServer = Utils::coreStringToAppString(policy->getStunServer());
|
mStunServer = Utils::coreStringToAppString(policy->getStunServer());
|
||||||
mIceEnabled = policy->iceEnabled();
|
mIceEnabled = policy->iceEnabled();
|
||||||
|
|
@ -84,19 +82,10 @@ AccountCore::AccountCore(const std::shared_ptr<linphone::Account> &account) : QO
|
||||||
? Utils::coreStringToAppString(params->getAudioVideoConferenceFactoryAddress()->asString())
|
? Utils::coreStringToAppString(params->getAudioVideoConferenceFactoryAddress()->asString())
|
||||||
: "";
|
: "";
|
||||||
mLimeServerUrl = Utils::coreStringToAppString(params->getLimeServerUrl());
|
mLimeServerUrl = Utils::coreStringToAppString(params->getLimeServerUrl());
|
||||||
mCcmpServerUrl = Utils::coreStringToAppString(params->getCcmpServerUrl());
|
|
||||||
|
|
||||||
// Add listener
|
// Add listener
|
||||||
mAccountModel = Utils::makeQObject_ptr<AccountModel>(account); // OK
|
mAccountModel = Utils::makeQObject_ptr<AccountModel>(account); // OK
|
||||||
mAccountModel->setSelf(mAccountModel);
|
mAccountModel->setSelf(mAccountModel);
|
||||||
mExplicitPresence = LinphoneEnums::fromString(
|
|
||||||
Utils::coreStringToAppString(CoreModel::getInstance()->getCore()->getConfig()->getString(
|
|
||||||
ToolModel::configAccountSection(account), "explicit_presence", "")));
|
|
||||||
mPresenceNote = Utils::coreStringToAppString(CoreModel::getInstance()->getCore()->getConfig()->getString(
|
|
||||||
ToolModel::configAccountSection(account), "presence_note", ""));
|
|
||||||
mMaxPresenceNoteSize = CoreModel::getInstance()->getCore()->getConfig()->getInt(
|
|
||||||
ToolModel::configAccountSection(account), "max_presence_note_size", 140);
|
|
||||||
mPresence = mAccountModel->getPresence();
|
|
||||||
mNotificationsAllowed = mAccountModel->getNotificationsAllowed();
|
mNotificationsAllowed = mAccountModel->getNotificationsAllowed();
|
||||||
mDialPlan = Utils::createDialPlanVariant("", " ");
|
mDialPlan = Utils::createDialPlanVariant("", " ");
|
||||||
mDialPlans << mDialPlan;
|
mDialPlans << mDialPlan;
|
||||||
|
|
@ -139,8 +128,8 @@ AccountCore::AccountCore(const AccountCore &accountCore) {
|
||||||
mVoicemailAddress = accountCore.mVoicemailAddress;
|
mVoicemailAddress = accountCore.mVoicemailAddress;
|
||||||
mTransport = accountCore.mTransport;
|
mTransport = accountCore.mTransport;
|
||||||
mTransports = accountCore.mTransports;
|
mTransports = accountCore.mTransports;
|
||||||
mRegistrarUri = accountCore.mRegistrarUri;
|
mServerAddress = accountCore.mServerAddress;
|
||||||
mOutboundProxyUri = accountCore.mOutboundProxyUri;
|
mOutboundProxyEnabled = accountCore.mOutboundProxyEnabled;
|
||||||
mStunServer = accountCore.mStunServer;
|
mStunServer = accountCore.mStunServer;
|
||||||
mIceEnabled = accountCore.mIceEnabled;
|
mIceEnabled = accountCore.mIceEnabled;
|
||||||
mAvpfEnabled = accountCore.mAvpfEnabled;
|
mAvpfEnabled = accountCore.mAvpfEnabled;
|
||||||
|
|
@ -149,7 +138,6 @@ AccountCore::AccountCore(const AccountCore &accountCore) {
|
||||||
mConferenceFactoryAddress = accountCore.mConferenceFactoryAddress;
|
mConferenceFactoryAddress = accountCore.mConferenceFactoryAddress;
|
||||||
mAudioVideoConferenceFactoryAddress = accountCore.mAudioVideoConferenceFactoryAddress;
|
mAudioVideoConferenceFactoryAddress = accountCore.mAudioVideoConferenceFactoryAddress;
|
||||||
mLimeServerUrl = accountCore.mLimeServerUrl;
|
mLimeServerUrl = accountCore.mLimeServerUrl;
|
||||||
mCcmpServerUrl = accountCore.mCcmpServerUrl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountCore::setSelf(QSharedPointer<AccountCore> me) {
|
void AccountCore::setSelf(QSharedPointer<AccountCore> me) {
|
||||||
|
|
@ -160,12 +148,6 @@ void AccountCore::setSelf(QSharedPointer<AccountCore> me) {
|
||||||
mAccountModelConnection->invokeToCore(
|
mAccountModelConnection->invokeToCore(
|
||||||
[this, account, state, message]() { onRegistrationStateChanged(account, state, message); });
|
[this, account, state, message]() { onRegistrationStateChanged(account, state, message); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnectToModel(
|
|
||||||
&AccountModel::conferenceInformationUpdated,
|
|
||||||
[this](const std::shared_ptr<linphone::Account> &account,
|
|
||||||
const std::list<std::shared_ptr<linphone::ConferenceInfo>> &infos) {
|
|
||||||
mAccountModelConnection->invokeToCore([this]() { emit conferenceInformationUpdated(); });
|
|
||||||
});
|
|
||||||
// From Model
|
// From Model
|
||||||
mAccountModelConnection->makeConnectToModel(&AccountModel::defaultAccountChanged, [this](bool isDefault) {
|
mAccountModelConnection->makeConnectToModel(&AccountModel::defaultAccountChanged, [this](bool isDefault) {
|
||||||
mAccountModelConnection->invokeToCore([this, isDefault]() { onDefaultAccountChanged(isDefault); });
|
mAccountModelConnection->invokeToCore([this, isDefault]() { onDefaultAccountChanged(isDefault); });
|
||||||
|
|
@ -205,11 +187,11 @@ void AccountCore::setSelf(QSharedPointer<AccountCore> me) {
|
||||||
mAccountModelConnection->invokeToCore(
|
mAccountModelConnection->invokeToCore(
|
||||||
[this, value]() { onTransportChanged(LinphoneEnums::toString(LinphoneEnums::fromLinphone(value))); });
|
[this, value]() { onTransportChanged(LinphoneEnums::toString(LinphoneEnums::fromLinphone(value))); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnectToModel(&AccountModel::registrarUriChanged, [this](QString value) {
|
mAccountModelConnection->makeConnectToModel(&AccountModel::serverAddressChanged, [this](QString value) {
|
||||||
mAccountModelConnection->invokeToCore([this, value]() { onRegistrarUriChanged(value); });
|
mAccountModelConnection->invokeToCore([this, value]() { onServerAddressChanged(value); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnectToModel(&AccountModel::outboundProxyUriChanged, [this](QString value) {
|
mAccountModelConnection->makeConnectToModel(&AccountModel::outboundProxyEnabledChanged, [this](bool value) {
|
||||||
mAccountModelConnection->invokeToCore([this, value]() { onOutboundProxyUriChanged(value); });
|
mAccountModelConnection->invokeToCore([this, value]() { onOutboundProxyEnabledChanged(value); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnectToModel(&AccountModel::stunServerChanged, [this](QString value) {
|
mAccountModelConnection->makeConnectToModel(&AccountModel::stunServerChanged, [this](QString value) {
|
||||||
mAccountModelConnection->invokeToCore([this, value]() { onStunServerChanged(value); });
|
mAccountModelConnection->invokeToCore([this, value]() { onStunServerChanged(value); });
|
||||||
|
|
@ -238,23 +220,9 @@ void AccountCore::setSelf(QSharedPointer<AccountCore> me) {
|
||||||
mAccountModelConnection->makeConnectToModel(&AccountModel::limeServerUrlChanged, [this](QString value) {
|
mAccountModelConnection->makeConnectToModel(&AccountModel::limeServerUrlChanged, [this](QString value) {
|
||||||
mAccountModelConnection->invokeToCore([this, value]() { onLimeServerUrlChanged(value); });
|
mAccountModelConnection->invokeToCore([this, value]() { onLimeServerUrlChanged(value); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnectToModel(&AccountModel::ccmpServerUrlChanged, [this](QString value) {
|
|
||||||
mAccountModelConnection->invokeToCore([this, value]() { onCcmpServerUrlChanged(value); });
|
|
||||||
});
|
|
||||||
|
|
||||||
mAccountModelConnection->makeConnectToModel(
|
mAccountModelConnection->makeConnectToModel(
|
||||||
&AccountModel::removed, [this]() { mAccountModelConnection->invokeToCore([this]() { emit removed(); }); });
|
&AccountModel::removed, [this]() { mAccountModelConnection->invokeToCore([this]() { emit removed(); }); });
|
||||||
|
|
||||||
mAccountModelConnection->makeConnectToModel(
|
|
||||||
&AccountModel::presenceChanged, [this](LinphoneEnums::Presence presence, bool userInitiated) {
|
|
||||||
mAccountModelConnection->invokeToCore([this, presence, userInitiated]() {
|
|
||||||
if (userInitiated) mExplicitPresence = presence;
|
|
||||||
else mExplicitPresence = LinphoneEnums::Presence::Undefined;
|
|
||||||
mPresence = presence;
|
|
||||||
emit presenceChanged();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// From GUI
|
// From GUI
|
||||||
mAccountModelConnection->makeConnectToCore(&AccountCore::lSetPictureUri, [this](QString uri) {
|
mAccountModelConnection->makeConnectToCore(&AccountCore::lSetPictureUri, [this](QString uri) {
|
||||||
mAccountModelConnection->invokeToModel([this, uri]() { mAccountModel->setPictureUri(uri); });
|
mAccountModelConnection->invokeToModel([this, uri]() { mAccountModel->setPictureUri(uri); });
|
||||||
|
|
@ -265,17 +233,19 @@ void AccountCore::setSelf(QSharedPointer<AccountCore> me) {
|
||||||
mAccountModelConnection->makeConnectToCore(&AccountCore::lResetMissedCalls, [this]() {
|
mAccountModelConnection->makeConnectToCore(&AccountCore::lResetMissedCalls, [this]() {
|
||||||
mAccountModelConnection->invokeToModel([this]() { mAccountModel->resetMissedCallsCount(); });
|
mAccountModelConnection->invokeToModel([this]() { mAccountModel->resetMissedCallsCount(); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnectToCore(&AccountCore::lResetUnreadMessages, [this]() {
|
|
||||||
mAccountModelConnection->invokeToModel([this]() {
|
|
||||||
auto chatRooms = mAccountModel->getChatRooms();
|
|
||||||
for (auto const &chatRoom : chatRooms) {
|
|
||||||
chatRoom->markAsRead();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mAccountModelConnection->makeConnectToCore(&AccountCore::lRefreshNotifications, [this]() {
|
mAccountModelConnection->makeConnectToCore(&AccountCore::lRefreshNotifications, [this]() {
|
||||||
mAccountModelConnection->invokeToModel([this]() { mAccountModel->refreshUnreadNotifications(); });
|
mAccountModelConnection->invokeToModel([this]() { mAccountModel->refreshUnreadNotifications(); });
|
||||||
});
|
});
|
||||||
|
mCoreModelConnection = SafeConnection<AccountCore, CoreModel>::create(me, CoreModel::getInstance());
|
||||||
|
mAccountModelConnection->makeConnectToCore(&AccountCore::unreadCallNotificationsChanged, [this]() {
|
||||||
|
mAccountModelConnection->invokeToModel([this]() { CoreModel::getInstance()->unreadNotificationsChanged(); });
|
||||||
|
});
|
||||||
|
mAccountModelConnection->makeConnectToCore(&AccountCore::unreadMessageNotificationsChanged, [this]() {
|
||||||
|
mAccountModelConnection->invokeToModel([this]() { CoreModel::getInstance()->unreadNotificationsChanged(); });
|
||||||
|
});
|
||||||
|
mAccountModelConnection->makeConnectToCore(&AccountCore::unreadNotificationsChanged, [this]() {
|
||||||
|
mAccountModelConnection->invokeToModel([this]() { CoreModel::getInstance()->unreadNotificationsChanged(); });
|
||||||
|
});
|
||||||
mAccountModelConnection->makeConnectToCore(&AccountCore::lSetDisplayName, [this](QString displayName) {
|
mAccountModelConnection->makeConnectToCore(&AccountCore::lSetDisplayName, [this](QString displayName) {
|
||||||
mAccountModelConnection->invokeToModel([this, displayName]() { mAccountModel->setDisplayName(displayName); });
|
mAccountModelConnection->invokeToModel([this, displayName]() { mAccountModel->setDisplayName(displayName); });
|
||||||
});
|
});
|
||||||
|
|
@ -290,13 +260,6 @@ void AccountCore::setSelf(QSharedPointer<AccountCore> me) {
|
||||||
mAccountModelConnection->makeConnectToCore(&AccountCore::lSetNotificationsAllowed, [this](bool value) {
|
mAccountModelConnection->makeConnectToCore(&AccountCore::lSetNotificationsAllowed, [this](bool value) {
|
||||||
mAccountModelConnection->invokeToModel([this, value]() { mAccountModel->setNotificationsAllowed(value); });
|
mAccountModelConnection->invokeToModel([this, value]() { mAccountModel->setNotificationsAllowed(value); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnectToCore(
|
|
||||||
&AccountCore::lSetPresence, [this](LinphoneEnums::Presence presence, bool userInitiated, bool resetToAuto) {
|
|
||||||
mAccountModelConnection->invokeToModel(
|
|
||||||
[this, presence, userInitiated, resetToAuto, presenceNote = mPresenceNote]() {
|
|
||||||
mAccountModel->setPresence(presence, userInitiated, resetToAuto, presenceNote);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
DEFINE_CORE_GET_CONNECT(mAccountModelConnection, AccountCore, AccountModel, mAccountModel, int, voicemailCount,
|
DEFINE_CORE_GET_CONNECT(mAccountModelConnection, AccountCore, AccountModel, mAccountModel, int, voicemailCount,
|
||||||
VoicemailCount)
|
VoicemailCount)
|
||||||
|
|
@ -306,14 +269,6 @@ void AccountCore::setSelf(QSharedPointer<AccountCore> me) {
|
||||||
mAccountModelConnection->makeConnectToModel(&AccountModel::voicemailAddressChanged, [this](QString value) {
|
mAccountModelConnection->makeConnectToModel(&AccountModel::voicemailAddressChanged, [this](QString value) {
|
||||||
mAccountModelConnection->invokeToCore([this, value]() { setVoicemailAddress(value); });
|
mAccountModelConnection->invokeToCore([this, value]() { setVoicemailAddress(value); });
|
||||||
});
|
});
|
||||||
|
|
||||||
mCoreModelConnection = SafeConnection<AccountCore, CoreModel>::create(me, CoreModel::getInstance());
|
|
||||||
mCoreModelConnection->makeConnectToModel(&CoreModel::messageReadInChatRoom,
|
|
||||||
[this] { mAccountModel->refreshUnreadNotifications(); });
|
|
||||||
|
|
||||||
mAccountModelConnection->makeConnectToModel(&AccountModel::setValueFailed, [this](const QString &errorMessage) {
|
|
||||||
mAccountModelConnection->invokeToCore([this, errorMessage]() { emit setValueFailed(errorMessage); });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountCore::reset(const AccountCore &accountCore) {
|
void AccountCore::reset(const AccountCore &accountCore) {
|
||||||
|
|
@ -323,8 +278,8 @@ void AccountCore::reset(const AccountCore &accountCore) {
|
||||||
setMwiServerAddress(accountCore.mMwiServerAddress);
|
setMwiServerAddress(accountCore.mMwiServerAddress);
|
||||||
setVoicemailAddress(accountCore.mVoicemailAddress);
|
setVoicemailAddress(accountCore.mVoicemailAddress);
|
||||||
setTransport(accountCore.mTransport);
|
setTransport(accountCore.mTransport);
|
||||||
setRegistrarUri(accountCore.mRegistrarUri);
|
setServerAddress(accountCore.mServerAddress);
|
||||||
setOutboundProxyUri(accountCore.mOutboundProxyUri);
|
setOutboundProxyEnabled(accountCore.mOutboundProxyEnabled);
|
||||||
setStunServer(accountCore.mStunServer);
|
setStunServer(accountCore.mStunServer);
|
||||||
setIceEnabled(accountCore.mIceEnabled);
|
setIceEnabled(accountCore.mIceEnabled);
|
||||||
setAvpfEnabled(accountCore.mAvpfEnabled);
|
setAvpfEnabled(accountCore.mAvpfEnabled);
|
||||||
|
|
@ -333,7 +288,6 @@ void AccountCore::reset(const AccountCore &accountCore) {
|
||||||
setConferenceFactoryAddress(accountCore.mConferenceFactoryAddress);
|
setConferenceFactoryAddress(accountCore.mConferenceFactoryAddress);
|
||||||
setAudioVideoConferenceFactoryAddress(accountCore.mAudioVideoConferenceFactoryAddress);
|
setAudioVideoConferenceFactoryAddress(accountCore.mAudioVideoConferenceFactoryAddress);
|
||||||
setLimeServerUrl(accountCore.mLimeServerUrl);
|
setLimeServerUrl(accountCore.mLimeServerUrl);
|
||||||
setCcmpServerUrl(accountCore.mCcmpServerUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::shared_ptr<AccountModel> &AccountCore::getModel() const {
|
const std::shared_ptr<AccountModel> &AccountCore::getModel() const {
|
||||||
|
|
@ -393,8 +347,8 @@ void AccountCore::setUnreadMessageNotifications(int unread) {
|
||||||
void AccountCore::onRegistrationStateChanged(const std::shared_ptr<linphone::Account> &account,
|
void AccountCore::onRegistrationStateChanged(const std::shared_ptr<linphone::Account> &account,
|
||||||
linphone::RegistrationState state,
|
linphone::RegistrationState state,
|
||||||
const std::string &message) {
|
const std::string &message) {
|
||||||
|
lDebug() << log().arg(Q_FUNC_INFO) << (int)state;
|
||||||
mRegistrationState = LinphoneEnums::fromLinphone(state);
|
mRegistrationState = LinphoneEnums::fromLinphone(state);
|
||||||
qDebug() << log().arg(Q_FUNC_INFO) << mRegistrationState;
|
|
||||||
emit registrationStateChanged(Utils::coreStringToAppString(message));
|
emit registrationStateChanged(Utils::coreStringToAppString(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -469,30 +423,6 @@ QString AccountCore::getHumanReadableRegistrationState() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor AccountCore::getRegistrationColor() const {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
switch (mRegistrationState) {
|
|
||||||
case LinphoneEnums::RegistrationState::Ok:
|
|
||||||
return Utils::getDefaultStyleColor("success_500_main");
|
|
||||||
case LinphoneEnums::RegistrationState::Refreshing:
|
|
||||||
return Utils::getDefaultStyleColor("main2_500_main");
|
|
||||||
case LinphoneEnums::RegistrationState::Progress:
|
|
||||||
return Utils::getDefaultStyleColor("main2_500_main");
|
|
||||||
case LinphoneEnums::RegistrationState::Failed:
|
|
||||||
return Utils::getDefaultStyleColor("danger_500_main");
|
|
||||||
case LinphoneEnums::RegistrationState::None:
|
|
||||||
case LinphoneEnums::RegistrationState::Cleared:
|
|
||||||
return Utils::getDefaultStyleColor("warning_600");
|
|
||||||
default:
|
|
||||||
return " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QUrl AccountCore::getRegistrationIcon() const {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
return Utils::getRegistrationStateIcon(mRegistrationState);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AccountCore::getHumanReadableRegistrationStateExplained() const {
|
QString AccountCore::getHumanReadableRegistrationStateExplained() const {
|
||||||
switch (mRegistrationState) {
|
switch (mRegistrationState) {
|
||||||
case LinphoneEnums::RegistrationState::Ok:
|
case LinphoneEnums::RegistrationState::Ok:
|
||||||
|
|
@ -541,12 +471,12 @@ QString AccountCore::getTransport() {
|
||||||
return mTransport;
|
return mTransport;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AccountCore::getRegistrarUri() {
|
QString AccountCore::getServerAddress() {
|
||||||
return mRegistrarUri;
|
return mServerAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AccountCore::getOutboundProxyUri() {
|
bool AccountCore::getOutboundProxyEnabled() {
|
||||||
return mOutboundProxyUri;
|
return mOutboundProxyEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AccountCore::getStunServer() {
|
QString AccountCore::getStunServer() {
|
||||||
|
|
@ -581,10 +511,6 @@ QString AccountCore::getLimeServerUrl() {
|
||||||
return mLimeServerUrl;
|
return mLimeServerUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AccountCore::getCcmpServerUrl() {
|
|
||||||
return mCcmpServerUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AccountCore::setMwiServerAddress(QString value) {
|
void AccountCore::setMwiServerAddress(QString value) {
|
||||||
if (mMwiServerAddress != value) {
|
if (mMwiServerAddress != value) {
|
||||||
mMwiServerAddress = value;
|
mMwiServerAddress = value;
|
||||||
|
|
@ -603,24 +529,32 @@ void AccountCore::setVoicemailAddress(QString value) {
|
||||||
|
|
||||||
void AccountCore::setTransport(QString value) {
|
void AccountCore::setTransport(QString value) {
|
||||||
if (mTransport != value) {
|
if (mTransport != value) {
|
||||||
mTransport = value;
|
mAccountModelConnection->invokeToModel([this, value] {
|
||||||
emit transportChanged();
|
mustBeInLinphoneThread(getClassName() + Q_FUNC_INFO);
|
||||||
|
LinphoneEnums::TransportType transport;
|
||||||
|
LinphoneEnums::fromString(value, &transport);
|
||||||
|
mAccountModel->setTransport(LinphoneEnums::toLinphone(transport), false);
|
||||||
|
});
|
||||||
setIsSaved(false);
|
setIsSaved(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountCore::setRegistrarUri(QString value) {
|
void AccountCore::setServerAddress(QString value) {
|
||||||
if (mRegistrarUri != value) {
|
if (mServerAddress != value) {
|
||||||
mRegistrarUri = value;
|
mAccountModelConnection->invokeToModel([this, value, transportString = mTransport] {
|
||||||
emit registrarUriChanged();
|
LinphoneEnums::TransportType transport;
|
||||||
|
LinphoneEnums::fromString(transportString, &transport);
|
||||||
|
mustBeInLinphoneThread(getClassName() + Q_FUNC_INFO);
|
||||||
|
mAccountModel->setServerAddress(value, LinphoneEnums::toLinphone(transport), false);
|
||||||
|
});
|
||||||
setIsSaved(false);
|
setIsSaved(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountCore::setOutboundProxyUri(QString value) {
|
void AccountCore::setOutboundProxyEnabled(bool value) {
|
||||||
if (mOutboundProxyUri != value) {
|
if (mOutboundProxyEnabled != value) {
|
||||||
mOutboundProxyUri = value;
|
mOutboundProxyEnabled = value;
|
||||||
emit outboundProxyUriChanged();
|
emit outboundProxyEnabledChanged();
|
||||||
setIsSaved(false);
|
setIsSaved(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -689,14 +623,6 @@ void AccountCore::setLimeServerUrl(QString value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountCore::setCcmpServerUrl(QString value) {
|
|
||||||
if (mCcmpServerUrl != value) {
|
|
||||||
mCcmpServerUrl = value;
|
|
||||||
emit ccmpServerUrlChanged();
|
|
||||||
setIsSaved(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AccountCore::isSaved() const {
|
bool AccountCore::isSaved() const {
|
||||||
return mIsSaved;
|
return mIsSaved;
|
||||||
}
|
}
|
||||||
|
|
@ -736,20 +662,19 @@ void AccountCore::onTransportChanged(QString value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountCore::onRegistrarUriChanged(QString value) {
|
void AccountCore::onServerAddressChanged(QString value) {
|
||||||
if (value != mRegistrarUri) {
|
if (value != mServerAddress) {
|
||||||
mRegistrarUri = value;
|
mServerAddress = value;
|
||||||
emit registrarUriChanged();
|
emit serverAddressChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountCore::onOutboundProxyUriChanged(QString value) {
|
void AccountCore::onOutboundProxyEnabledChanged(bool value) {
|
||||||
if (value != mOutboundProxyUri) {
|
if (value != mOutboundProxyEnabled) {
|
||||||
mOutboundProxyUri = value;
|
mOutboundProxyEnabled = value;
|
||||||
emit outboundProxyUriChanged();
|
emit outboundProxyEnabledChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountCore::onStunServerChanged(QString value) {
|
void AccountCore::onStunServerChanged(QString value) {
|
||||||
if (value != mStunServer) {
|
if (value != mStunServer) {
|
||||||
mStunServer = value;
|
mStunServer = value;
|
||||||
|
|
@ -809,21 +734,14 @@ void AccountCore::onLimeServerUrlChanged(QString value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountCore::onCcmpServerUrlChanged(QString value) {
|
|
||||||
if (value != mCcmpServerUrl) {
|
|
||||||
mCcmpServerUrl = value;
|
|
||||||
emit ccmpServerUrlChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AccountCore::writeIntoModel(std::shared_ptr<AccountModel> model) const {
|
void AccountCore::writeIntoModel(std::shared_ptr<AccountModel> model) const {
|
||||||
mustBeInLinphoneThread(getClassName() + Q_FUNC_INFO);
|
mustBeInLinphoneThread(getClassName() + Q_FUNC_INFO);
|
||||||
model->setMwiServerAddress(mMwiServerAddress);
|
model->setMwiServerAddress(mMwiServerAddress);
|
||||||
LinphoneEnums::TransportType transport;
|
LinphoneEnums::TransportType transport;
|
||||||
LinphoneEnums::fromString(mTransport, &transport);
|
LinphoneEnums::fromString(mTransport, &transport);
|
||||||
model->setTransport(LinphoneEnums::toLinphone(transport), true);
|
model->setTransport(LinphoneEnums::toLinphone(transport), true);
|
||||||
model->setRegistrarUri(mRegistrarUri);
|
model->setServerAddress(mServerAddress, LinphoneEnums::toLinphone(transport), true);
|
||||||
model->setOutboundProxyUri(mOutboundProxyUri);
|
model->setOutboundProxyEnabled(mOutboundProxyEnabled);
|
||||||
model->setStunServer(mStunServer);
|
model->setStunServer(mStunServer);
|
||||||
model->setIceEnabled(mIceEnabled);
|
model->setIceEnabled(mIceEnabled);
|
||||||
model->setAvpfEnabled(mAvpfEnabled);
|
model->setAvpfEnabled(mAvpfEnabled);
|
||||||
|
|
@ -832,28 +750,27 @@ void AccountCore::writeIntoModel(std::shared_ptr<AccountModel> model) const {
|
||||||
model->setConferenceFactoryAddress(mConferenceFactoryAddress);
|
model->setConferenceFactoryAddress(mConferenceFactoryAddress);
|
||||||
model->setAudioVideoConferenceFactoryAddress(mAudioVideoConferenceFactoryAddress);
|
model->setAudioVideoConferenceFactoryAddress(mAudioVideoConferenceFactoryAddress);
|
||||||
model->setLimeServerUrl(mLimeServerUrl);
|
model->setLimeServerUrl(mLimeServerUrl);
|
||||||
model->setCcmpServerUrl(mCcmpServerUrl);
|
|
||||||
model->setVoicemailAddress(mVoicemailAddress);
|
model->setVoicemailAddress(mVoicemailAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountCore::writeFromModel(const std::shared_ptr<AccountModel> &model) {
|
void AccountCore::writeFromModel(const std::shared_ptr<AccountModel> &model) {
|
||||||
mustBeInLinphoneThread(getClassName() + Q_FUNC_INFO);
|
mustBeInLinphoneThread(getClassName() + Q_FUNC_INFO);
|
||||||
setUnreadCallNotifications(model->getMissedCallsCount());
|
|
||||||
setUnreadMessageNotifications(model->getUnreadMessagesCount());
|
mUnreadCallNotifications = model->getMissedCallsCount();
|
||||||
onMwiServerAddressChanged(model->getMwiServerAddress());
|
mUnreadMessageNotifications = model->getUnreadMessagesCount();
|
||||||
onTransportChanged(LinphoneEnums::toString(LinphoneEnums::fromLinphone(model->getTransport())));
|
mMwiServerAddress = model->getMwiServerAddress();
|
||||||
onRegistrarUriChanged(model->getRegistrarUri());
|
mTransport = LinphoneEnums::toString(LinphoneEnums::fromLinphone(model->getTransport()));
|
||||||
onOutboundProxyUriChanged(model->getOutboundProxyUri());
|
mServerAddress = model->getServerAddress();
|
||||||
onStunServerChanged(model->getStunServer());
|
mOutboundProxyEnabled = model->getOutboundProxyEnabled();
|
||||||
onIceEnabledChanged(model->getIceEnabled());
|
mStunServer = model->getStunServer();
|
||||||
onAvpfEnabledChanged(model->getAvpfEnabled());
|
mIceEnabled = model->getIceEnabled();
|
||||||
onBundleModeEnabledChanged(model->getBundleModeEnabled());
|
mAvpfEnabled = model->getAvpfEnabled();
|
||||||
onExpireChanged(model->getExpire());
|
mBundleModeEnabled = model->getBundleModeEnabled();
|
||||||
onConferenceFactoryAddressChanged(model->getConferenceFactoryAddress());
|
mExpire = model->getExpire();
|
||||||
onAudioVideoConferenceFactoryAddressChanged(model->getAudioVideoConferenceFactoryAddress());
|
mConferenceFactoryAddress = model->getConferenceFactoryAddress();
|
||||||
onLimeServerUrlChanged(model->getLimeServerUrl());
|
mAudioVideoConferenceFactoryAddress = model->getAudioVideoConferenceFactoryAddress();
|
||||||
onCcmpServerUrlChanged(model->getCcmpServerUrl());
|
mLimeServerUrl = model->getLimeServerUrl();
|
||||||
onVoicemailAddressChanged(model->getVoicemailAddress());
|
mVoicemailAddress = model->getVoicemailAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountCore::save() {
|
void AccountCore::save() {
|
||||||
|
|
@ -885,38 +802,3 @@ void AccountCore::undo() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LinphoneEnums::Presence AccountCore::getPresence() {
|
|
||||||
return mPresence;
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor AccountCore::getPresenceColor() {
|
|
||||||
return Utils::getPresenceColor(mPresence);
|
|
||||||
}
|
|
||||||
|
|
||||||
QUrl AccountCore::getPresenceIcon() {
|
|
||||||
return Utils::getPresenceIcon(mPresence);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AccountCore::getPresenceStatus() {
|
|
||||||
return Utils::getPresenceStatus(mPresence);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AccountCore::resetToAutomaticPresence() {
|
|
||||||
emit lSetPresence(LinphoneEnums::Presence::Online, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
LinphoneEnums::Presence AccountCore::getExplicitPresence() {
|
|
||||||
return mExplicitPresence;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AccountCore::setPresenceNote(QString presenceNote) {
|
|
||||||
if (presenceNote != mPresenceNote) {
|
|
||||||
mPresenceNote = presenceNote;
|
|
||||||
emit lSetPresence(mPresence, mExplicitPresence != LinphoneEnums::Presence::Undefined, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AccountCore::getPresenceNote() {
|
|
||||||
return mPresenceNote;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,9 @@ public:
|
||||||
QString mwiServerAddress READ getMwiServerAddress WRITE setMwiServerAddress NOTIFY mwiServerAddressChanged)
|
QString mwiServerAddress READ getMwiServerAddress WRITE setMwiServerAddress NOTIFY mwiServerAddressChanged)
|
||||||
Q_PROPERTY(QStringList transports READ getTransports CONSTANT)
|
Q_PROPERTY(QStringList transports READ getTransports CONSTANT)
|
||||||
Q_PROPERTY(QString transport READ getTransport WRITE setTransport NOTIFY transportChanged)
|
Q_PROPERTY(QString transport READ getTransport WRITE setTransport NOTIFY transportChanged)
|
||||||
Q_PROPERTY(QString registrarUri READ getRegistrarUri WRITE setRegistrarUri NOTIFY registrarUriChanged)
|
Q_PROPERTY(QString serverAddress READ getServerAddress WRITE setServerAddress NOTIFY serverAddressChanged)
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(bool outboundProxyEnabled READ getOutboundProxyEnabled WRITE setOutboundProxyEnabled NOTIFY
|
||||||
QString outboundProxyUri READ getOutboundProxyUri WRITE setOutboundProxyUri NOTIFY outboundProxyUriChanged)
|
outboundProxyEnabledChanged)
|
||||||
Q_PROPERTY(QString stunServer READ getStunServer WRITE setStunServer NOTIFY stunServerChanged)
|
Q_PROPERTY(QString stunServer READ getStunServer WRITE setStunServer NOTIFY stunServerChanged)
|
||||||
Q_PROPERTY(bool iceEnabled READ getIceEnabled WRITE setIceEnabled NOTIFY iceEnabledChanged)
|
Q_PROPERTY(bool iceEnabled READ getIceEnabled WRITE setIceEnabled NOTIFY iceEnabledChanged)
|
||||||
Q_PROPERTY(bool avpfEnabled READ getAvpfEnabled WRITE setAvpfEnabled NOTIFY avpfEnabledChanged)
|
Q_PROPERTY(bool avpfEnabled READ getAvpfEnabled WRITE setAvpfEnabled NOTIFY avpfEnabledChanged)
|
||||||
|
|
@ -75,16 +75,6 @@ public:
|
||||||
Q_PROPERTY(bool isSaved READ isSaved WRITE setIsSaved NOTIFY isSavedChanged)
|
Q_PROPERTY(bool isSaved READ isSaved WRITE setIsSaved NOTIFY isSavedChanged)
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(
|
||||||
QString voicemailAddress READ getVoicemailAddress WRITE setVoicemailAddress NOTIFY voicemailAddressChanged)
|
QString voicemailAddress READ getVoicemailAddress WRITE setVoicemailAddress NOTIFY voicemailAddressChanged)
|
||||||
Q_PROPERTY(LinphoneEnums::Presence presence READ getPresence WRITE lSetPresence NOTIFY presenceChanged)
|
|
||||||
Q_PROPERTY(QColor presenceColor READ getPresenceColor NOTIFY presenceChanged)
|
|
||||||
Q_PROPERTY(QUrl presenceIcon READ getPresenceIcon NOTIFY presenceChanged)
|
|
||||||
Q_PROPERTY(QString presenceStatus READ getPresenceStatus NOTIFY presenceChanged)
|
|
||||||
Q_PROPERTY(QColor registrationColor READ getRegistrationColor NOTIFY registrationStateChanged)
|
|
||||||
Q_PROPERTY(QUrl registrationIcon READ getRegistrationIcon NOTIFY registrationStateChanged)
|
|
||||||
Q_PROPERTY(LinphoneEnums::Presence explicitPresence MEMBER mExplicitPresence NOTIFY presenceChanged)
|
|
||||||
Q_PROPERTY(QString presenceNote READ getPresenceNote WRITE setPresenceNote NOTIFY presenceChanged)
|
|
||||||
Q_PROPERTY(int maxPresenceNoteSize MEMBER mMaxPresenceNoteSize CONSTANT)
|
|
||||||
Q_PROPERTY(QString ccmpServerUrl READ getCcmpServerUrl WRITE setCcmpServerUrl NOTIFY ccmpServerUrlChanged)
|
|
||||||
|
|
||||||
DECLARE_CORE_GET(int, voicemailCount, VoicemailCount)
|
DECLARE_CORE_GET(int, voicemailCount, VoicemailCount)
|
||||||
static QSharedPointer<AccountCore> create(const std::shared_ptr<linphone::Account> &account);
|
static QSharedPointer<AccountCore> create(const std::shared_ptr<linphone::Account> &account);
|
||||||
|
|
@ -124,8 +114,6 @@ public:
|
||||||
void onDialPlanChanged(QVariantMap internationalPrefix);
|
void onDialPlanChanged(QVariantMap internationalPrefix);
|
||||||
QString getHumanReadableRegistrationState() const;
|
QString getHumanReadableRegistrationState() const;
|
||||||
QString getHumanReadableRegistrationStateExplained() const;
|
QString getHumanReadableRegistrationStateExplained() const;
|
||||||
QColor getRegistrationColor() const;
|
|
||||||
QUrl getRegistrationIcon() const;
|
|
||||||
bool getRegisterEnabled() const;
|
bool getRegisterEnabled() const;
|
||||||
void onRegisterEnabledChanged(bool enabled);
|
void onRegisterEnabledChanged(bool enabled);
|
||||||
|
|
||||||
|
|
@ -133,8 +121,8 @@ public:
|
||||||
QString getMwiServerAddress();
|
QString getMwiServerAddress();
|
||||||
QString getTransport();
|
QString getTransport();
|
||||||
QStringList getTransports();
|
QStringList getTransports();
|
||||||
QString getRegistrarUri();
|
QString getServerAddress();
|
||||||
QString getOutboundProxyUri();
|
bool getOutboundProxyEnabled();
|
||||||
QString getStunServer();
|
QString getStunServer();
|
||||||
bool getIceEnabled();
|
bool getIceEnabled();
|
||||||
bool getAvpfEnabled();
|
bool getAvpfEnabled();
|
||||||
|
|
@ -144,12 +132,11 @@ public:
|
||||||
QString getAudioVideoConferenceFactoryAddress();
|
QString getAudioVideoConferenceFactoryAddress();
|
||||||
QString getLimeServerUrl();
|
QString getLimeServerUrl();
|
||||||
QString getVoicemailAddress();
|
QString getVoicemailAddress();
|
||||||
QString getCcmpServerUrl();
|
|
||||||
|
|
||||||
void setMwiServerAddress(QString value);
|
void setMwiServerAddress(QString value);
|
||||||
void setTransport(QString value);
|
void setTransport(QString value);
|
||||||
void setRegistrarUri(QString value);
|
void setServerAddress(QString value);
|
||||||
void setOutboundProxyUri(QString value);
|
void setOutboundProxyEnabled(bool value);
|
||||||
void setStunServer(QString value);
|
void setStunServer(QString value);
|
||||||
void setIceEnabled(bool value);
|
void setIceEnabled(bool value);
|
||||||
void setAvpfEnabled(bool value);
|
void setAvpfEnabled(bool value);
|
||||||
|
|
@ -159,7 +146,6 @@ public:
|
||||||
void setAudioVideoConferenceFactoryAddress(QString value);
|
void setAudioVideoConferenceFactoryAddress(QString value);
|
||||||
void setLimeServerUrl(QString value);
|
void setLimeServerUrl(QString value);
|
||||||
void setVoicemailAddress(QString value);
|
void setVoicemailAddress(QString value);
|
||||||
void setCcmpServerUrl(QString value);
|
|
||||||
|
|
||||||
bool isSaved() const;
|
bool isSaved() const;
|
||||||
void setIsSaved(bool saved);
|
void setIsSaved(bool saved);
|
||||||
|
|
@ -168,8 +154,8 @@ public:
|
||||||
void onMwiServerAddressChanged(QString value);
|
void onMwiServerAddressChanged(QString value);
|
||||||
void onVoicemailAddressChanged(QString value);
|
void onVoicemailAddressChanged(QString value);
|
||||||
void onTransportChanged(QString value);
|
void onTransportChanged(QString value);
|
||||||
void onRegistrarUriChanged(QString value);
|
void onServerAddressChanged(QString value);
|
||||||
void onOutboundProxyUriChanged(QString value);
|
void onOutboundProxyEnabledChanged(bool value);
|
||||||
void onStunServerChanged(QString value);
|
void onStunServerChanged(QString value);
|
||||||
void onIceEnabledChanged(bool value);
|
void onIceEnabledChanged(bool value);
|
||||||
void onAvpfEnabledChanged(bool value);
|
void onAvpfEnabledChanged(bool value);
|
||||||
|
|
@ -178,26 +164,15 @@ public:
|
||||||
void onConferenceFactoryAddressChanged(QString value);
|
void onConferenceFactoryAddressChanged(QString value);
|
||||||
void onAudioVideoConferenceFactoryAddressChanged(QString value);
|
void onAudioVideoConferenceFactoryAddressChanged(QString value);
|
||||||
void onLimeServerUrlChanged(QString value);
|
void onLimeServerUrlChanged(QString value);
|
||||||
void onCcmpServerUrlChanged(QString value);
|
|
||||||
|
|
||||||
DECLARE_CORE_GET(bool, showMwi, ShowMwi)
|
DECLARE_CORE_GET(bool, showMwi, ShowMwi)
|
||||||
|
|
||||||
Q_INVOKABLE void save();
|
Q_INVOKABLE void save();
|
||||||
Q_INVOKABLE void undo();
|
Q_INVOKABLE void undo();
|
||||||
|
|
||||||
QColor getPresenceColor();
|
|
||||||
QUrl getPresenceIcon();
|
|
||||||
QString getPresenceStatus();
|
|
||||||
LinphoneEnums::Presence getPresence();
|
|
||||||
Q_INVOKABLE void resetToAutomaticPresence();
|
|
||||||
LinphoneEnums::Presence getExplicitPresence();
|
|
||||||
void setPresenceNote(QString presenceNote);
|
|
||||||
QString getPresenceNote();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void pictureUriChanged();
|
void pictureUriChanged();
|
||||||
void registrationStateChanged(const QString &message);
|
void registrationStateChanged(const QString &message);
|
||||||
void conferenceInformationUpdated();
|
|
||||||
void defaultAccountChanged(bool isDefault);
|
void defaultAccountChanged(bool isDefault);
|
||||||
void unreadNotificationsChanged(int unread);
|
void unreadNotificationsChanged(int unread);
|
||||||
void unreadCallNotificationsChanged(int unread);
|
void unreadCallNotificationsChanged(int unread);
|
||||||
|
|
@ -210,8 +185,8 @@ signals:
|
||||||
void notificationsAllowedChanged();
|
void notificationsAllowedChanged();
|
||||||
void mwiServerAddressChanged();
|
void mwiServerAddressChanged();
|
||||||
void transportChanged();
|
void transportChanged();
|
||||||
void registrarUriChanged();
|
void serverAddressChanged();
|
||||||
void outboundProxyUriChanged();
|
void outboundProxyEnabledChanged();
|
||||||
void stunServerChanged();
|
void stunServerChanged();
|
||||||
void iceEnabledChanged();
|
void iceEnabledChanged();
|
||||||
void avpfEnabledChanged();
|
void avpfEnabledChanged();
|
||||||
|
|
@ -223,22 +198,16 @@ signals:
|
||||||
void removed();
|
void removed();
|
||||||
void isSavedChanged();
|
void isSavedChanged();
|
||||||
void voicemailAddressChanged();
|
void voicemailAddressChanged();
|
||||||
void presenceChanged();
|
|
||||||
void ccmpServerUrlChanged();
|
|
||||||
|
|
||||||
void setValueFailed(const QString &error);
|
|
||||||
|
|
||||||
// Account requests
|
// Account requests
|
||||||
void lSetPictureUri(QString pictureUri);
|
void lSetPictureUri(QString pictureUri);
|
||||||
void lSetDefaultAccount();
|
void lSetDefaultAccount();
|
||||||
void lResetMissedCalls();
|
void lResetMissedCalls();
|
||||||
void lResetUnreadMessages();
|
|
||||||
void lRefreshNotifications();
|
void lRefreshNotifications();
|
||||||
void lSetDisplayName(QString displayName);
|
void lSetDisplayName(QString displayName);
|
||||||
void lSetDialPlan(QVariantMap internationalPrefix);
|
void lSetDialPlan(QVariantMap internationalPrefix);
|
||||||
void lSetRegisterEnabled(bool enabled);
|
void lSetRegisterEnabled(bool enabled);
|
||||||
void lSetNotificationsAllowed(bool value);
|
void lSetNotificationsAllowed(bool value);
|
||||||
void lSetPresence(LinphoneEnums::Presence presence, bool userInitiated = true, bool resetToAuto = false);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void writeIntoModel(std::shared_ptr<AccountModel> model) const;
|
void writeIntoModel(std::shared_ptr<AccountModel> model) const;
|
||||||
|
|
@ -262,8 +231,8 @@ private:
|
||||||
QString mMwiServerAddress;
|
QString mMwiServerAddress;
|
||||||
QString mTransport;
|
QString mTransport;
|
||||||
QStringList mTransports;
|
QStringList mTransports;
|
||||||
QString mRegistrarUri;
|
QString mServerAddress;
|
||||||
QString mOutboundProxyUri;
|
bool mOutboundProxyEnabled;
|
||||||
QString mStunServer;
|
QString mStunServer;
|
||||||
bool mIceEnabled;
|
bool mIceEnabled;
|
||||||
bool mAvpfEnabled;
|
bool mAvpfEnabled;
|
||||||
|
|
@ -273,14 +242,8 @@ private:
|
||||||
QString mAudioVideoConferenceFactoryAddress;
|
QString mAudioVideoConferenceFactoryAddress;
|
||||||
QString mLimeServerUrl;
|
QString mLimeServerUrl;
|
||||||
QString mVoicemailAddress;
|
QString mVoicemailAddress;
|
||||||
QString mCcmpServerUrl;
|
|
||||||
LinphoneEnums::Presence mPresence = LinphoneEnums::Presence::Undefined;
|
|
||||||
LinphoneEnums::Presence mExplicitPresence;
|
|
||||||
QString mPresenceNote;
|
|
||||||
int mMaxPresenceNoteSize;
|
|
||||||
|
|
||||||
bool mIsSaved = true;
|
bool mIsSaved = true;
|
||||||
|
|
||||||
std::shared_ptr<AccountModel> mAccountModel;
|
std::shared_ptr<AccountModel> mAccountModel;
|
||||||
QSharedPointer<SafeConnection<AccountCore, AccountModel>> mAccountModelConnection;
|
QSharedPointer<SafeConnection<AccountCore, AccountModel>> mAccountModelConnection;
|
||||||
QSharedPointer<SafeConnection<AccountCore, CoreModel>> mCoreModelConnection;
|
QSharedPointer<SafeConnection<AccountCore, CoreModel>> mCoreModelConnection;
|
||||||
|
|
|
||||||
|
|
@ -69,14 +69,16 @@ void AccountDeviceList::setAccount(const QSharedPointer<AccountCore> &accountCor
|
||||||
mAccountCore = accountCore;
|
mAccountCore = accountCore;
|
||||||
lDebug() << log().arg("Set account model") << mAccountCore.get();
|
lDebug() << log().arg("Set account model") << mAccountCore.get();
|
||||||
// oldConnect.unlock();
|
// oldConnect.unlock();
|
||||||
if (mAccountCore) refreshDevices();
|
refreshDevices();
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountDeviceList::refreshDevices() {
|
void AccountDeviceList::refreshDevices() {
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
||||||
resetData();
|
beginResetModel();
|
||||||
|
clearData();
|
||||||
|
endResetModel();
|
||||||
if (mAccountCore) {
|
if (mAccountCore) {
|
||||||
auto requestDeviceList = [this] {
|
auto requestDeviceList = [this] {
|
||||||
if (!mAccountManagerServicesModelConnection) return;
|
if (!mAccountManagerServicesModelConnection) return;
|
||||||
|
|
@ -148,14 +150,14 @@ void AccountDeviceList::setSelf(QSharedPointer<AccountDeviceList> me) {
|
||||||
&AccountManagerServicesModel::requestError,
|
&AccountManagerServicesModel::requestError,
|
||||||
[this](const std::shared_ptr<const linphone::AccountManagerServicesRequest> &request, int statusCode,
|
[this](const std::shared_ptr<const linphone::AccountManagerServicesRequest> &request, int statusCode,
|
||||||
const std::string &errorMessage,
|
const std::string &errorMessage,
|
||||||
const std::shared_ptr<const linphone::Dictionary> ¶meterErrors) {
|
const std::shared_ptr<const linphone::Dictionary> ¶meterErrors) {
|
||||||
lDebug() << "REQUEST ERROR" << errorMessage << "/" << int(request->getType());
|
lDebug() << "REQUEST ERROR" << errorMessage << "/" << int(request->getType());
|
||||||
QString message = QString::fromStdString(errorMessage);
|
QString message = QString::fromStdString(errorMessage);
|
||||||
if (request->getType() == linphone::AccountManagerServicesRequest::Type::GetDevicesList) {
|
if (request->getType() == linphone::AccountManagerServicesRequest::Type::GetDevicesList) {
|
||||||
//: "Erreur lors de la récupération des appareils"
|
//: "Erreur lors de la récupération des appareils"
|
||||||
message = tr("manage_account_no_device_found_error_message");
|
message = tr("manage_account_no_device_found_error_message");
|
||||||
}
|
}
|
||||||
emit requestError(message);
|
emit requestError(message);
|
||||||
});
|
});
|
||||||
mAccountManagerServicesModelConnection->makeConnectToModel(
|
mAccountManagerServicesModelConnection->makeConnectToModel(
|
||||||
&AccountManagerServicesModel::devicesListFetched,
|
&AccountManagerServicesModel::devicesListFetched,
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,9 @@
|
||||||
#ifndef ACCOUNT_DEVICE_LIST_H_
|
#ifndef ACCOUNT_DEVICE_LIST_H_
|
||||||
#define ACCOUNT_DEVICE_LIST_H_
|
#define ACCOUNT_DEVICE_LIST_H_
|
||||||
|
|
||||||
|
#include "../proxy/ListProxy.hpp"
|
||||||
#include "AccountDeviceCore.hpp"
|
#include "AccountDeviceCore.hpp"
|
||||||
#include "core/account/AccountGui.hpp"
|
#include "core/account/AccountGui.hpp"
|
||||||
#include "core/proxy/ListProxy.hpp"
|
|
||||||
#include "model/account/AccountManagerServicesModel.hpp"
|
#include "model/account/AccountManagerServicesModel.hpp"
|
||||||
#include "tool/AbstractObject.hpp"
|
#include "tool/AbstractObject.hpp"
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
#include "tool/thread/SafeConnection.hpp"
|
||||||
|
|
|
||||||
|
|
@ -61,11 +61,6 @@ void AccountList::setSelf(QSharedPointer<AccountList> me) {
|
||||||
auto model = AccountCore::create(it);
|
auto model = AccountCore::create(it);
|
||||||
if (it == defaultAccount) defaultAccountCore = model;
|
if (it == defaultAccount) defaultAccountCore = model;
|
||||||
accounts->push_back(model);
|
accounts->push_back(model);
|
||||||
connect(model.get(), &AccountCore::unreadNotificationsChanged, this,
|
|
||||||
[this] { emit unreadNotificationsChanged(); });
|
|
||||||
connect(model.get(), &AccountCore::removed, this, [this, model]() {
|
|
||||||
disconnect(model.get(), &AccountCore::unreadNotificationsChanged, this, nullptr);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
mModelConnection->invokeToCore([this, accounts, defaultAccountCore, isInitialization]() {
|
mModelConnection->invokeToCore([this, accounts, defaultAccountCore, isInitialization]() {
|
||||||
mustBeInMainThread(getClassName());
|
mustBeInMainThread(getClassName());
|
||||||
|
|
@ -73,14 +68,8 @@ void AccountList::setSelf(QSharedPointer<AccountList> me) {
|
||||||
setHaveAccount(accounts->size() > 0);
|
setHaveAccount(accounts->size() > 0);
|
||||||
setDefaultAccount(defaultAccountCore);
|
setDefaultAccount(defaultAccountCore);
|
||||||
if (isInitialization) setInitialized(true);
|
if (isInitialization) setInitialized(true);
|
||||||
for (const QSharedPointer<AccountCore> &accountCore : *accounts) {
|
|
||||||
if (accountCore->getExplicitPresence() != LinphoneEnums::Presence::Undefined)
|
|
||||||
emit accountCore->lSetPresence(accountCore->getExplicitPresence(), true, false);
|
|
||||||
}
|
|
||||||
delete accounts;
|
delete accounts;
|
||||||
});
|
});
|
||||||
// Update notification count at startup
|
|
||||||
if (isInitialization) emit unreadNotificationsChanged();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
mModelConnection->makeConnectToModel(
|
mModelConnection->makeConnectToModel(
|
||||||
|
|
@ -99,8 +88,7 @@ void AccountList::setSelf(QSharedPointer<AccountList> me) {
|
||||||
// with the open id account
|
// with the open id account
|
||||||
mModelConnection->makeConnectToModel(&CoreModel::bearerAccountAdded, [this] {
|
mModelConnection->makeConnectToModel(&CoreModel::bearerAccountAdded, [this] {
|
||||||
setInitialized(false);
|
setInitialized(false);
|
||||||
emit lUpdate(true);
|
emit lUpdate(true); });
|
||||||
});
|
|
||||||
|
|
||||||
mModelConnection->makeConnectToModel(
|
mModelConnection->makeConnectToModel(
|
||||||
&CoreModel::globalStateChanged,
|
&CoreModel::globalStateChanged,
|
||||||
|
|
@ -170,18 +158,6 @@ void AccountList::setInitialized(bool init) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountList::lResetMissedCalls() {
|
|
||||||
for (auto &accountCore : getSharedList<AccountCore>()) {
|
|
||||||
accountCore->lResetMissedCalls();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AccountList::lResetUnreadMessages() {
|
|
||||||
for (auto &accountCore : getSharedList<AccountCore>()) {
|
|
||||||
emit accountCore->lResetUnreadMessages();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant AccountList::data(const QModelIndex &index, int role) const {
|
QVariant AccountList::data(const QModelIndex &index, int role) const {
|
||||||
int row = index.row();
|
int row = index.row();
|
||||||
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,6 @@ public:
|
||||||
|
|
||||||
bool isInitialized() const;
|
bool isInitialized() const;
|
||||||
void setInitialized(bool init);
|
void setInitialized(bool init);
|
||||||
void lResetMissedCalls(); // Reset missed calls of all accounts
|
|
||||||
void lResetUnreadMessages(); // Reset unread messages of all accounts
|
|
||||||
|
|
||||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
signals:
|
signals:
|
||||||
|
|
@ -60,7 +58,6 @@ signals:
|
||||||
void haveAccountChanged();
|
void haveAccountChanged();
|
||||||
void defaultAccountChanged();
|
void defaultAccountChanged();
|
||||||
void initializedChanged(bool init);
|
void initializedChanged(bool init);
|
||||||
void unreadNotificationsChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mHaveAccount = false;
|
bool mHaveAccount = false;
|
||||||
|
|
|
||||||
|
|
@ -73,11 +73,8 @@ void CarddavCore::remove() {
|
||||||
|
|
||||||
void CarddavCore::setSelf(QSharedPointer<CarddavCore> me) {
|
void CarddavCore::setSelf(QSharedPointer<CarddavCore> me) {
|
||||||
mCarddavModelConnection = SafeConnection<CarddavCore, CarddavModel>::create(me, mCarddavModel);
|
mCarddavModelConnection = SafeConnection<CarddavCore, CarddavModel>::create(me, mCarddavModel);
|
||||||
mCarddavModelConnection->makeConnectToModel(&CarddavModel::saved, [this](bool success, QString message) {
|
mCarddavModelConnection->makeConnectToModel(&CarddavModel::saved, [this](bool success) {
|
||||||
mCarddavModelConnection->invokeToCore([this, success, message]() {
|
mCarddavModelConnection->invokeToCore([this, success]() { emit saved(success); });
|
||||||
if (success) emit App::getInstance() -> getSettings()->cardDAVAddressBookSynchronized();
|
|
||||||
emit saved(success, message);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public:
|
||||||
DECLARE_CORE_MEMBER(bool, storeNewFriendsInIt, StoreNewFriendsInIt)
|
DECLARE_CORE_MEMBER(bool, storeNewFriendsInIt, StoreNewFriendsInIt)
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void saved(bool success, QString message);
|
void saved(bool success);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<CarddavModel> mCarddavModel;
|
std::shared_ptr<CarddavModel> mCarddavModel;
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,8 @@ CallHistoryCore::CallHistoryCore(const std::shared_ptr<linphone::CallLog> &callL
|
||||||
mustBeInLinphoneThread(getClassName());
|
mustBeInLinphoneThread(getClassName());
|
||||||
mCallHistoryModel = std::make_shared<CallHistoryModel>(callLog);
|
mCallHistoryModel = std::make_shared<CallHistoryModel>(callLog);
|
||||||
|
|
||||||
auto addr = callLog->getRemoteAddress();
|
auto addr = callLog->getRemoteAddress()->clone();
|
||||||
|
addr->clean();
|
||||||
mStatus = LinphoneEnums::fromLinphone(callLog->getStatus());
|
mStatus = LinphoneEnums::fromLinphone(callLog->getStatus());
|
||||||
mDate = QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000);
|
mDate = QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000);
|
||||||
mIsOutgoing = callLog->getDir() == linphone::Call::Dir::Outgoing;
|
mIsOutgoing = callLog->getDir() == linphone::Call::Dir::Outgoing;
|
||||||
|
|
@ -128,16 +129,14 @@ void CallHistoryCore::setSelf(QSharedPointer<CallHistoryCore> me) {
|
||||||
mCoreModelConnection->makeConnectToModel(&CoreModel::friendRemoved, &CallHistoryCore::onRemoved);
|
mCoreModelConnection->makeConnectToModel(&CoreModel::friendRemoved, &CallHistoryCore::onRemoved);
|
||||||
// Update display name when display name has been requested from magic search cause not found in linphone friends
|
// Update display name when display name has been requested from magic search cause not found in linphone friends
|
||||||
// (required to get the right display name if ldap friends cleared)
|
// (required to get the right display name if ldap friends cleared)
|
||||||
// This replace the display name set by a user by a default one, use the linphone address to
|
mCoreModelConnection->makeConnectToModel(&CoreModel::magicSearchResultReceived, [this, remoteAddress = mRemoteAddress] {
|
||||||
// get a correct display name
|
auto displayName = ToolModel::getDisplayName(remoteAddress);
|
||||||
// mCoreModelConnection->makeConnectToModel(&CoreModel::magicSearchResultReceived,
|
mCoreModelConnection->invokeToCore([this, displayName]() {
|
||||||
// [this, remoteAddress = mRemoteAddress] {
|
mDisplayName = displayName;
|
||||||
// auto displayName = ToolModel::getDisplayName(remoteAddress);
|
emit displayNameChanged();
|
||||||
// mCoreModelConnection->invokeToCore([this, displayName]() {
|
});
|
||||||
// mDisplayName = displayName;
|
});
|
||||||
// emit displayNameChanged();
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConferenceInfoGui *CallHistoryCore::getConferenceInfoGui() const {
|
ConferenceInfoGui *CallHistoryCore::getConferenceInfoGui() const {
|
||||||
|
|
|
||||||
|
|
@ -57,12 +57,10 @@ void CallHistoryList::setSelf(QSharedPointer<CallHistoryList> me) {
|
||||||
mModelConnection = SafeConnection<CallHistoryList, CoreModel>::create(me, CoreModel::getInstance());
|
mModelConnection = SafeConnection<CallHistoryList, CoreModel>::create(me, CoreModel::getInstance());
|
||||||
|
|
||||||
mModelConnection->makeConnectToCore(&CallHistoryList::lUpdate, [this]() {
|
mModelConnection->makeConnectToCore(&CallHistoryList::lUpdate, [this]() {
|
||||||
clearData();
|
|
||||||
emit listAboutToBeReset();
|
|
||||||
mModelConnection->invokeToModel([this]() {
|
mModelConnection->invokeToModel([this]() {
|
||||||
mustBeInLinphoneThread(getClassName());
|
|
||||||
// Avoid copy to lambdas
|
// Avoid copy to lambdas
|
||||||
QList<QSharedPointer<CallHistoryCore>> *callLogs = new QList<QSharedPointer<CallHistoryCore>>();
|
QList<QSharedPointer<CallHistoryCore>> *callLogs = new QList<QSharedPointer<CallHistoryCore>>();
|
||||||
|
mustBeInLinphoneThread(getClassName());
|
||||||
std::list<std::shared_ptr<linphone::CallLog>> linphoneCallLogs;
|
std::list<std::shared_ptr<linphone::CallLog>> linphoneCallLogs;
|
||||||
if (auto account = CoreModel::getInstance()->getCore()->getDefaultAccount()) {
|
if (auto account = CoreModel::getInstance()->getCore()->getDefaultAccount()) {
|
||||||
linphoneCallLogs = account->getCallLogs();
|
linphoneCallLogs = account->getCallLogs();
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,6 @@ signals:
|
||||||
void lUpdate();
|
void lUpdate();
|
||||||
void lRemoveEntriesForAddress(QString address);
|
void lRemoveEntriesForAddress(QString address);
|
||||||
void lRemoveAllEntries();
|
void lRemoveAllEntries();
|
||||||
void listAboutToBeReset();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Check the state from CallHistoryCore: sender() must be a CallHistoryCore.
|
// Check the state from CallHistoryCore: sender() must be a CallHistoryCore.
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ DEFINE_ABSTRACT_OBJECT(CallHistoryProxy)
|
||||||
|
|
||||||
CallHistoryProxy::CallHistoryProxy(QObject *parent) : LimitProxy(parent) {
|
CallHistoryProxy::CallHistoryProxy(QObject *parent) : LimitProxy(parent) {
|
||||||
mHistoryList = CallHistoryList::create();
|
mHistoryList = CallHistoryList::create();
|
||||||
connect(mHistoryList.get(), &CallHistoryList::listAboutToBeReset, this, &CallHistoryProxy::listAboutToBeReset);
|
|
||||||
setSourceModels(new SortFilterList(mHistoryList.get(), Qt::DescendingOrder));
|
setSourceModels(new SortFilterList(mHistoryList.get(), Qt::DescendingOrder));
|
||||||
connect(App::getInstance(), &App::currentDateChanged, this, [this] { emit mHistoryList->lUpdate(); });
|
connect(App::getInstance(), &App::currentDateChanged, this, [this] { emit mHistoryList->lUpdate(); });
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +56,7 @@ bool CallHistoryProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QMo
|
||||||
QRegularExpression::CaseInsensitiveOption |
|
QRegularExpression::CaseInsensitiveOption |
|
||||||
QRegularExpression::UseUnicodePropertiesOption);
|
QRegularExpression::UseUnicodePropertiesOption);
|
||||||
auto callLog = getItemAtSource<CallHistoryList, CallHistoryCore>(sourceRow);
|
auto callLog = getItemAtSource<CallHistoryList, CallHistoryCore>(sourceRow);
|
||||||
show = callLog && (callLog->mDisplayName.contains(search) || callLog->mRemoteAddress.contains(search));
|
show = callLog->mDisplayName.contains(search) || callLog->mRemoteAddress.contains(search);
|
||||||
}
|
}
|
||||||
return show;
|
return show;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,6 @@ public:
|
||||||
Q_INVOKABLE void removeEntriesWithFilter(QString filter);
|
Q_INVOKABLE void removeEntriesWithFilter(QString filter);
|
||||||
Q_INVOKABLE void reload();
|
Q_INVOKABLE void reload();
|
||||||
|
|
||||||
signals:
|
|
||||||
void listAboutToBeReset();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QSharedPointer<CallHistoryList> mHistoryList;
|
QSharedPointer<CallHistoryList> mHistoryList;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010-2026 Belledonne Communications SARL.
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||||
*
|
*
|
||||||
* This file is part of linphone-desktop
|
* This file is part of linphone-desktop
|
||||||
* (see https://www.linphone.org).
|
* (see https://www.linphone.org).
|
||||||
|
|
@ -28,8 +28,6 @@
|
||||||
#include "tool/Utils.hpp"
|
#include "tool/Utils.hpp"
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
#include "tool/thread/SafeConnection.hpp"
|
||||||
|
|
||||||
#include <QQuickWindow>
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(CallCore)
|
DEFINE_ABSTRACT_OBJECT(CallCore)
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
|
|
@ -109,17 +107,18 @@ CallCore::CallCore(const std::shared_ptr<linphone::Call> &call) : QObject(nullpt
|
||||||
mCallModel->setSelf(mCallModel);
|
mCallModel->setSelf(mCallModel);
|
||||||
mDuration = call->getDuration();
|
mDuration = call->getDuration();
|
||||||
mIsStarted = mDuration > 0;
|
mIsStarted = mDuration > 0;
|
||||||
auto callParams = call->getParams();
|
mMicrophoneMuted = call->getMicrophoneMuted();
|
||||||
auto videoDirection = callParams->getVideoDirection();
|
mSpeakerMuted = call->getSpeakerMuted();
|
||||||
|
auto videoDirection = call->getParams()->getVideoDirection();
|
||||||
mLocalVideoEnabled =
|
mLocalVideoEnabled =
|
||||||
videoDirection == linphone::MediaDirection::SendOnly || videoDirection == linphone::MediaDirection::SendRecv;
|
videoDirection == linphone::MediaDirection::SendOnly || videoDirection == linphone::MediaDirection::SendRecv;
|
||||||
mCameraEnabled = callParams->cameraEnabled();
|
|
||||||
auto remoteParams = call->getRemoteParams();
|
auto remoteParams = call->getRemoteParams();
|
||||||
videoDirection = remoteParams ? remoteParams->getVideoDirection() : linphone::MediaDirection::Inactive;
|
videoDirection = remoteParams ? remoteParams->getVideoDirection() : linphone::MediaDirection::Inactive;
|
||||||
mRemoteVideoEnabled =
|
mRemoteVideoEnabled =
|
||||||
videoDirection == linphone::MediaDirection::SendOnly || videoDirection == linphone::MediaDirection::SendRecv;
|
videoDirection == linphone::MediaDirection::SendOnly || videoDirection == linphone::MediaDirection::SendRecv;
|
||||||
mState = LinphoneEnums::fromLinphone(call->getState());
|
mState = LinphoneEnums::fromLinphone(call->getState());
|
||||||
auto remoteAddress = call->getCallLog()->getRemoteAddress();
|
auto remoteAddress = call->getCallLog()->getRemoteAddress()->clone();
|
||||||
|
remoteAddress->clean();
|
||||||
mRemoteAddress = Utils::coreStringToAppString(remoteAddress->asStringUriOnly());
|
mRemoteAddress = Utils::coreStringToAppString(remoteAddress->asStringUriOnly());
|
||||||
mRemoteUsername = Utils::coreStringToAppString(remoteAddress->getUsername());
|
mRemoteUsername = Utils::coreStringToAppString(remoteAddress->getUsername());
|
||||||
auto linphoneFriend = ToolModel::findFriendByAddress(remoteAddress);
|
auto linphoneFriend = ToolModel::findFriendByAddress(remoteAddress);
|
||||||
|
|
@ -137,7 +136,7 @@ CallCore::CallCore(const std::shared_ptr<linphone::Call> &call) : QObject(nullpt
|
||||||
mTransferState = LinphoneEnums::fromLinphone(call->getTransferState());
|
mTransferState = LinphoneEnums::fromLinphone(call->getTransferState());
|
||||||
mLocalToken = Utils::coreStringToAppString(mCallModel->getLocalAtuhenticationToken());
|
mLocalToken = Utils::coreStringToAppString(mCallModel->getLocalAtuhenticationToken());
|
||||||
mRemoteTokens = mCallModel->getRemoteAtuhenticationTokens();
|
mRemoteTokens = mCallModel->getRemoteAtuhenticationTokens();
|
||||||
mEncryption = LinphoneEnums::fromLinphone(callParams->getMediaEncryption());
|
mEncryption = LinphoneEnums::fromLinphone(call->getParams()->getMediaEncryption());
|
||||||
auto tokenVerified = call->getAuthenticationTokenVerified();
|
auto tokenVerified = call->getAuthenticationTokenVerified();
|
||||||
mIsMismatch = call->getZrtpCacheMismatchFlag();
|
mIsMismatch = call->getZrtpCacheMismatchFlag();
|
||||||
mIsSecured = (mEncryption == LinphoneEnums::MediaEncryption::Zrtp && tokenVerified) ||
|
mIsSecured = (mEncryption == LinphoneEnums::MediaEncryption::Zrtp && tokenVerified) ||
|
||||||
|
|
@ -159,12 +158,10 @@ CallCore::CallCore(const std::shared_ptr<linphone::Call> &call) : QObject(nullpt
|
||||||
if (mIsConference) {
|
if (mIsConference) {
|
||||||
mConference = ConferenceCore::create(conference);
|
mConference = ConferenceCore::create(conference);
|
||||||
}
|
}
|
||||||
mMicrophoneMuted = conference ? conference->getMicrophoneMuted() : call->getMicrophoneMuted();
|
|
||||||
mSpeakerMuted = call->getSpeakerMuted();
|
|
||||||
mPaused = mState == LinphoneEnums::CallState::Pausing || mState == LinphoneEnums::CallState::Paused ||
|
mPaused = mState == LinphoneEnums::CallState::Pausing || mState == LinphoneEnums::CallState::Paused ||
|
||||||
mState == LinphoneEnums::CallState::PausedByRemote;
|
mState == LinphoneEnums::CallState::PausedByRemote;
|
||||||
|
|
||||||
mRecording = callParams && callParams->isRecording();
|
mRecording = call->getParams() && call->getParams()->isRecording();
|
||||||
mRemoteRecording = call->getRemoteParams() && call->getRemoteParams()->isRecording();
|
mRemoteRecording = call->getRemoteParams() && call->getRemoteParams()->isRecording();
|
||||||
auto settingsModel = SettingsModel::getInstance();
|
auto settingsModel = SettingsModel::getInstance();
|
||||||
mMicrophoneVolume = call->getRecordVolume();
|
mMicrophoneVolume = call->getRecordVolume();
|
||||||
|
|
@ -197,8 +194,8 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
mCallModelConnection->makeConnectToModel(&CallModel::speakerMutedChanged, [this](bool isMuted) {
|
mCallModelConnection->makeConnectToModel(&CallModel::speakerMutedChanged, [this](bool isMuted) {
|
||||||
mCallModelConnection->invokeToCore([this, isMuted]() { setSpeakerMuted(isMuted); });
|
mCallModelConnection->invokeToCore([this, isMuted]() { setSpeakerMuted(isMuted); });
|
||||||
});
|
});
|
||||||
mCallModelConnection->makeConnectToCore(&CallCore::lSetCameraEnabled, [this](bool enabled) {
|
mCallModelConnection->makeConnectToCore(&CallCore::lSetLocalVideoEnabled, [this](bool enabled) {
|
||||||
mCallModelConnection->invokeToModel([this, enabled]() { mCallModel->setCameraEnabled(enabled); });
|
mCallModelConnection->invokeToModel([this, enabled]() { mCallModel->setLocalVideoEnabled(enabled); });
|
||||||
});
|
});
|
||||||
mCallModelConnection->makeConnectToCore(&CallCore::lStartRecording, [this]() {
|
mCallModelConnection->makeConnectToCore(&CallCore::lStartRecording, [this]() {
|
||||||
mCallModelConnection->invokeToModel([this]() { mCallModel->startRecording(); });
|
mCallModelConnection->invokeToModel([this]() { mCallModel->startRecording(); });
|
||||||
|
|
@ -208,15 +205,14 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
});
|
});
|
||||||
mCallModelConnection->makeConnectToModel(
|
mCallModelConnection->makeConnectToModel(
|
||||||
&CallModel::recordingChanged, [this](const std::shared_ptr<linphone::Call> &call, bool recording) {
|
&CallModel::recordingChanged, [this](const std::shared_ptr<linphone::Call> &call, bool recording) {
|
||||||
auto recordFile = QString::fromStdString(mCallModel->getRecordFile());
|
mCallModelConnection->invokeToCore([this, recording]() {
|
||||||
mCallModelConnection->invokeToCore([this, recording, recordFile]() {
|
|
||||||
setRecording(recording);
|
setRecording(recording);
|
||||||
if (recording == false) {
|
if (recording == false) {
|
||||||
//: "Enregistrement terminé"
|
//: "Enregistrement terminé"
|
||||||
Utils::showInformationPopup(tr("call_record_end_message"),
|
Utils::showInformationPopup(tr("call_record_end_message"),
|
||||||
//: "L'appel a été enregistré dans le fichier : %1"
|
//: "L'appel a été enregistré dans le fichier : %1"
|
||||||
tr("call_record_saved_in_file_message").arg(recordFile), true,
|
tr("call_record_saved_in_file_message").arg(QString::fromStdString(mCallModel->getRecordFile())),
|
||||||
App::getInstance()->getOrCreateCallsWindow());
|
true, App::getInstance()->getCallsWindow());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -248,9 +244,6 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
mCallModelConnection->makeConnectToModel(&CallModel::localVideoEnabledChanged, [this](bool enabled) {
|
mCallModelConnection->makeConnectToModel(&CallModel::localVideoEnabledChanged, [this](bool enabled) {
|
||||||
mCallModelConnection->invokeToCore([this, enabled]() { setLocalVideoEnabled(enabled); });
|
mCallModelConnection->invokeToCore([this, enabled]() { setLocalVideoEnabled(enabled); });
|
||||||
});
|
});
|
||||||
mCallModelConnection->makeConnectToModel(&CallModel::cameraEnabledChanged, [this](bool enabled) {
|
|
||||||
mCallModelConnection->invokeToCore([this, enabled]() { setCameraEnabled(enabled); });
|
|
||||||
});
|
|
||||||
mCallModelConnection->makeConnectToModel(&CallModel::durationChanged, [this](int duration) {
|
mCallModelConnection->makeConnectToModel(&CallModel::durationChanged, [this](int duration) {
|
||||||
mCallModelConnection->invokeToCore([this, duration]() { setDuration(duration); });
|
mCallModelConnection->invokeToCore([this, duration]() { setDuration(duration); });
|
||||||
});
|
});
|
||||||
|
|
@ -268,7 +261,6 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
bool isConf = call && call->getConference() != nullptr;
|
bool isConf = call && call->getConference() != nullptr;
|
||||||
auto subject = call->getConference() ? Utils::coreStringToAppString(call->getConference()->getSubject()) : "";
|
auto subject = call->getConference() ? Utils::coreStringToAppString(call->getConference()->getSubject()) : "";
|
||||||
mCallModelConnection->invokeToCore([this, state, subject, isConf]() {
|
mCallModelConnection->invokeToCore([this, state, subject, isConf]() {
|
||||||
lDebug() << log().arg("::onStateChanged") << LinphoneEnums::fromLinphone(state);
|
|
||||||
setRecordable(state == linphone::Call::State::StreamsRunning);
|
setRecordable(state == linphone::Call::State::StreamsRunning);
|
||||||
setPaused(state == linphone::Call::State::Paused || state == linphone::Call::State::PausedByRemote);
|
setPaused(state == linphone::Call::State::Paused || state == linphone::Call::State::PausedByRemote);
|
||||||
if (mConference) mConference->setSubject(subject);
|
if (mConference) mConference->setSubject(subject);
|
||||||
|
|
@ -316,8 +308,8 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
[this, call, encryption, tokenVerified, localToken, remoteTokens, isCaseMismatch]() {
|
[this, call, encryption, tokenVerified, localToken, remoteTokens, isCaseMismatch]() {
|
||||||
setLocalToken(localToken);
|
setLocalToken(localToken);
|
||||||
setRemoteTokens(remoteTokens);
|
setRemoteTokens(remoteTokens);
|
||||||
setIsMismatch(isCaseMismatch);
|
setIsMismatch(isCaseMismatch);
|
||||||
setTokenVerified(tokenVerified);
|
setTokenVerified(tokenVerified);
|
||||||
setEncryption(encryption);
|
setEncryption(encryption);
|
||||||
});
|
});
|
||||||
auto mediaEncryption = call->getParams()->getMediaEncryption();
|
auto mediaEncryption = call->getParams()->getMediaEncryption();
|
||||||
|
|
@ -329,7 +321,7 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
zrtpStats.mHashAlgorithm = Utils::coreStringToAppString(stats->getZrtpHashAlgo());
|
zrtpStats.mHashAlgorithm = Utils::coreStringToAppString(stats->getZrtpHashAlgo());
|
||||||
zrtpStats.mAuthenticationAlgorithm = Utils::coreStringToAppString(stats->getZrtpAuthTagAlgo());
|
zrtpStats.mAuthenticationAlgorithm = Utils::coreStringToAppString(stats->getZrtpAuthTagAlgo());
|
||||||
zrtpStats.mSasAlgorithm = Utils::coreStringToAppString(stats->getZrtpSasAlgo());
|
zrtpStats.mSasAlgorithm = Utils::coreStringToAppString(stats->getZrtpSasAlgo());
|
||||||
zrtpStats.mIsPostQuantum = stats->isZrtpKeyAgreementAlgoPostQuantum();
|
zrtpStats.mIsPostQuantum = stats->isZrtpKeyAgreementAlgoPostQuantum();
|
||||||
mCallModelConnection->invokeToCore([this, zrtpStats]() { setZrtpStats(zrtpStats); });
|
mCallModelConnection->invokeToCore([this, zrtpStats]() { setZrtpStats(zrtpStats); });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -351,8 +343,6 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
});
|
});
|
||||||
mCallModelConnection->makeConnectToModel(&CallModel::conferenceChanged, [this]() {
|
mCallModelConnection->makeConnectToModel(&CallModel::conferenceChanged, [this]() {
|
||||||
auto conference = mCallModel->getMonitor()->getConference();
|
auto conference = mCallModel->getMonitor()->getConference();
|
||||||
// Force enable video if in conference to handle screen sharing
|
|
||||||
if (conference && !mCallModel->videoEnabled()) mCallModel->enableVideo(true);
|
|
||||||
QSharedPointer<ConferenceCore> core = conference ? ConferenceCore::create(conference) : nullptr;
|
QSharedPointer<ConferenceCore> core = conference ? ConferenceCore::create(conference) : nullptr;
|
||||||
mCallModelConnection->invokeToCore([this, core]() { setConference(core); });
|
mCallModelConnection->invokeToCore([this, core]() { setConference(core); });
|
||||||
});
|
});
|
||||||
|
|
@ -398,23 +388,23 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
auto codecType = playloadType ? playloadType->getMimeType() : "";
|
auto codecType = playloadType ? playloadType->getMimeType() : "";
|
||||||
auto codecRate = playloadType ? playloadType->getClockRate() / 1000 : 0;
|
auto codecRate = playloadType ? playloadType->getClockRate() / 1000 : 0;
|
||||||
audioStats.mCodec =
|
audioStats.mCodec =
|
||||||
//: "Codec: %1 / %2 kHz"
|
//: "Codec: %1 / %2 kHz"
|
||||||
tr("call_stats_codec_label").arg(Utils::coreStringToAppString(codecType)).arg(codecRate);
|
tr("call_stats_codec_label").arg(Utils::coreStringToAppString(codecType)).arg(codecRate);
|
||||||
auto linAudioStats = call->getAudioStats();
|
auto linAudioStats = call->getAudioStats();
|
||||||
if (linAudioStats) {
|
if (linAudioStats) {
|
||||||
//: "Bande passante : %1 %2 kbits/s %3 %4 kbits/s"
|
//: "Bande passante : %1 %2 kbits/s %3 %4 kbits/s"
|
||||||
audioStats.mBandwidth = tr("call_stats_bandwidth_label")
|
audioStats.mBandwidth = tr("call_stats_bandwidth_label")
|
||||||
.arg("↑")
|
.arg("↑")
|
||||||
.arg(round(linAudioStats->getUploadBandwidth()))
|
.arg(round(linAudioStats->getUploadBandwidth()))
|
||||||
.arg("↓")
|
.arg("↓")
|
||||||
.arg(round(linAudioStats->getDownloadBandwidth()));
|
.arg(round(linAudioStats->getDownloadBandwidth()));
|
||||||
//: "Taux de perte: %1% %2%"
|
//: "Taux de perte: %1% %2%"
|
||||||
audioStats.mLossRate = tr("call_stats_loss_rate_label")
|
audioStats.mLossRate = tr("call_stats_loss_rate_label")
|
||||||
.arg(linAudioStats->getSenderLossRate())
|
.arg(linAudioStats->getSenderLossRate())
|
||||||
.arg(linAudioStats->getReceiverLossRate());
|
.arg(linAudioStats->getReceiverLossRate());
|
||||||
//: "Tampon de gigue: %1 ms"
|
//: "Tampon de gigue: %1 ms"
|
||||||
audioStats.mJitterBufferSize =
|
audioStats.mJitterBufferSize =
|
||||||
tr("call_stats_jitter_buffer_label").arg(linAudioStats->getJitterBufferSizeMs());
|
tr("call_stats_jitter_buffer_label").arg(linAudioStats->getJitterBufferSizeMs());
|
||||||
}
|
}
|
||||||
setAudioStats(audioStats);
|
setAudioStats(audioStats);
|
||||||
} else if (stats->getType() == linphone::StreamType::Video) {
|
} else if (stats->getType() == linphone::StreamType::Video) {
|
||||||
|
|
@ -424,15 +414,15 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
auto codecType = playloadType ? playloadType->getMimeType() : "";
|
auto codecType = playloadType ? playloadType->getMimeType() : "";
|
||||||
auto codecRate = playloadType ? playloadType->getClockRate() / 1000 : 0;
|
auto codecRate = playloadType ? playloadType->getClockRate() / 1000 : 0;
|
||||||
videoStats.mCodec =
|
videoStats.mCodec =
|
||||||
tr("call_stats_codec_label").arg(Utils::coreStringToAppString(codecType)).arg(codecRate);
|
tr("call_stats_codec_label").arg(Utils::coreStringToAppString(codecType)).arg(codecRate);
|
||||||
auto linVideoStats = call->getVideoStats();
|
auto linVideoStats = call->getVideoStats();
|
||||||
if (stats) {
|
if (stats) {
|
||||||
videoStats.mBandwidth = tr("call_stats_bandwidth_label")
|
videoStats.mBandwidth = tr("call_stats_bandwidth_label")
|
||||||
.arg("↑")
|
.arg("↑")
|
||||||
.arg(round(linVideoStats->getUploadBandwidth()))
|
.arg(round(linVideoStats->getUploadBandwidth()))
|
||||||
.arg("↓")
|
.arg("↓")
|
||||||
.arg(round(linVideoStats->getDownloadBandwidth()));
|
.arg(round(linVideoStats->getDownloadBandwidth()));
|
||||||
videoStats.mLossRate = tr("call_stats_loss_rate_label")
|
videoStats.mLossRate = tr("call_stats_loss_rate_label")
|
||||||
.arg(linVideoStats->getSenderLossRate())
|
.arg(linVideoStats->getSenderLossRate())
|
||||||
.arg(linVideoStats->getReceiverLossRate());
|
.arg(linVideoStats->getReceiverLossRate());
|
||||||
}
|
}
|
||||||
|
|
@ -440,55 +430,17 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
params->getSentVideoDefinition() ? params->getSentVideoDefinition()->getName() : "";
|
params->getSentVideoDefinition() ? params->getSentVideoDefinition()->getName() : "";
|
||||||
auto receivedResolution =
|
auto receivedResolution =
|
||||||
params->getReceivedVideoDefinition() ? params->getReceivedVideoDefinition()->getName() : "";
|
params->getReceivedVideoDefinition() ? params->getReceivedVideoDefinition()->getName() : "";
|
||||||
//: "Définition vidéo : %1 %2 %3 %4"
|
//: "Définition vidéo : %1 %2 %3 %4"
|
||||||
videoStats.mResolution = tr("call_stats_resolution_label")
|
videoStats.mResolution = tr("call_stats_resolution_label")
|
||||||
.arg("↑", Utils::coreStringToAppString(sentResolution), "↓",
|
.arg("↑", Utils::coreStringToAppString(sentResolution), "↓",
|
||||||
Utils::coreStringToAppString(receivedResolution));
|
Utils::coreStringToAppString(receivedResolution));
|
||||||
auto sentFps = params->getSentFramerate();
|
auto sentFps = params->getSentFramerate();
|
||||||
auto receivedFps = params->getReceivedFramerate();
|
auto receivedFps = params->getReceivedFramerate();
|
||||||
//: "FPS : %1 %2 %3 %4"
|
//: "FPS : %1 %2 %3 %4"
|
||||||
videoStats.mFps = tr("call_stats_fps_label").arg("↑").arg(sentFps).arg("↓").arg(receivedFps);
|
videoStats.mFps = tr("call_stats_fps_label").arg("↑").arg(sentFps).arg("↓").arg(receivedFps);
|
||||||
setVideoStats(videoStats);
|
setVideoStats(videoStats);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mCallModelConnection->makeConnectToModel(&CallModel::headsetAnswerCallRequested, [this]() {
|
|
||||||
mCallModelConnection->invokeToCore([this]() {
|
|
||||||
const auto callList = App::getInstance()->getCallList();
|
|
||||||
const auto currentPendingCall = callList->getFirstIncommingPendingCall();
|
|
||||||
if (!currentPendingCall.isNull()) {
|
|
||||||
const auto gui = new CallGui(currentPendingCall);
|
|
||||||
Utils::openCallsWindow(gui);
|
|
||||||
currentPendingCall->lAccept(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mCallModelConnection->makeConnectToModel(&CallModel::headsetEndCallRequested, [this]() {
|
|
||||||
mCallModelConnection->invokeToCore([this]() {
|
|
||||||
const auto window = Utils::getOrCreateCallsWindow();
|
|
||||||
window->setProperty("callTerminatedByUser", true);
|
|
||||||
lTerminate();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mCallModelConnection->makeConnectToModel(&CallModel::headsetHoldCallRequested, [this]() {
|
|
||||||
mCallModelConnection->invokeToCore([this]() { lSetPaused(true); });
|
|
||||||
});
|
|
||||||
mCallModelConnection->makeConnectToModel(&CallModel::headsetMicrophoneMuteToggled, [this](bool mute) {
|
|
||||||
mCallModelConnection->invokeToCore([this, mute]() { lSetMicrophoneMuted(mute); });
|
|
||||||
});
|
|
||||||
mCallModelConnection->makeConnectToModel(&CallModel::headsetRejectCallRequested, [this]() {
|
|
||||||
mCallModelConnection->invokeToCore([this]() {
|
|
||||||
const auto callList = App::getInstance()->getCallList();
|
|
||||||
const auto currentPendingCall = callList->getFirstIncommingPendingCall();
|
|
||||||
if (!currentPendingCall.isNull()) {
|
|
||||||
currentPendingCall->lDecline();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mCallModelConnection->makeConnectToModel(&CallModel::headsetResumeCallRequested, [this]() {
|
|
||||||
mCallModelConnection->invokeToCore([this]() { lSetPaused(false); });
|
|
||||||
});
|
|
||||||
|
|
||||||
if (mShouldFindRemoteFriend) findRemoteFriend(me);
|
if (mShouldFindRemoteFriend) findRemoteFriend(me);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -605,18 +557,6 @@ void CallCore::setLocalVideoEnabled(bool enabled) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallCore::getCameraEnabled() const {
|
|
||||||
return mCameraEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CallCore::setCameraEnabled(bool enabled) {
|
|
||||||
if (mCameraEnabled != enabled) {
|
|
||||||
mCameraEnabled = enabled;
|
|
||||||
lDebug() << "CameraEnabled: " << mCameraEnabled;
|
|
||||||
emit cameraEnabledChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CallCore::getPaused() const {
|
bool CallCore::getPaused() const {
|
||||||
return mPaused;
|
return mPaused;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -117,8 +117,8 @@ public:
|
||||||
Q_PROPERTY(QStringList remoteTokens WRITE setRemoteTokens MEMBER mRemoteTokens NOTIFY remoteTokensChanged)
|
Q_PROPERTY(QStringList remoteTokens WRITE setRemoteTokens MEMBER mRemoteTokens NOTIFY remoteTokensChanged)
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(
|
||||||
bool remoteVideoEnabled READ getRemoteVideoEnabled WRITE setRemoteVideoEnabled NOTIFY remoteVideoEnabledChanged)
|
bool remoteVideoEnabled READ getRemoteVideoEnabled WRITE setRemoteVideoEnabled NOTIFY remoteVideoEnabledChanged)
|
||||||
Q_PROPERTY(bool localVideoEnabled READ getLocalVideoEnabled NOTIFY localVideoEnabledChanged)
|
Q_PROPERTY(
|
||||||
Q_PROPERTY(bool cameraEnabled READ getCameraEnabled WRITE lSetCameraEnabled NOTIFY cameraEnabledChanged)
|
bool localVideoEnabled READ getLocalVideoEnabled WRITE lSetLocalVideoEnabled NOTIFY localVideoEnabledChanged)
|
||||||
Q_PROPERTY(bool recording READ getRecording WRITE setRecording NOTIFY recordingChanged)
|
Q_PROPERTY(bool recording READ getRecording WRITE setRecording NOTIFY recordingChanged)
|
||||||
Q_PROPERTY(bool remoteRecording READ getRemoteRecording WRITE setRemoteRecording NOTIFY remoteRecordingChanged)
|
Q_PROPERTY(bool remoteRecording READ getRemoteRecording WRITE setRemoteRecording NOTIFY remoteRecordingChanged)
|
||||||
Q_PROPERTY(bool recordable READ getRecordable WRITE setRecordable NOTIFY recordableChanged)
|
Q_PROPERTY(bool recordable READ getRecordable WRITE setRecordable NOTIFY recordableChanged)
|
||||||
|
|
@ -201,9 +201,6 @@ public:
|
||||||
bool getLocalVideoEnabled() const;
|
bool getLocalVideoEnabled() const;
|
||||||
void setLocalVideoEnabled(bool enabled);
|
void setLocalVideoEnabled(bool enabled);
|
||||||
|
|
||||||
bool getCameraEnabled() const;
|
|
||||||
void setCameraEnabled(bool enabled);
|
|
||||||
|
|
||||||
bool getRecording() const;
|
bool getRecording() const;
|
||||||
void setRecording(bool recording);
|
void setRecording(bool recording);
|
||||||
|
|
||||||
|
|
@ -258,7 +255,6 @@ signals:
|
||||||
void remoteTokensChanged();
|
void remoteTokensChanged();
|
||||||
void remoteVideoEnabledChanged(bool remoteVideoEnabled);
|
void remoteVideoEnabledChanged(bool remoteVideoEnabled);
|
||||||
void localVideoEnabledChanged();
|
void localVideoEnabledChanged();
|
||||||
void cameraEnabledChanged();
|
|
||||||
void recordingChanged();
|
void recordingChanged();
|
||||||
void remoteRecordingChanged();
|
void remoteRecordingChanged();
|
||||||
void recordableChanged();
|
void recordableChanged();
|
||||||
|
|
@ -279,7 +275,7 @@ signals:
|
||||||
void lTerminateAllCalls(); // Hangup all calls
|
void lTerminateAllCalls(); // Hangup all calls
|
||||||
void lSetSpeakerMuted(bool muted);
|
void lSetSpeakerMuted(bool muted);
|
||||||
void lSetMicrophoneMuted(bool isMuted);
|
void lSetMicrophoneMuted(bool isMuted);
|
||||||
void lSetCameraEnabled(bool enabled);
|
void lSetLocalVideoEnabled(bool enabled);
|
||||||
void lSetVideoEnabled(bool enabled);
|
void lSetVideoEnabled(bool enabled);
|
||||||
void lSetPaused(bool paused);
|
void lSetPaused(bool paused);
|
||||||
void lTransferCall(QString address);
|
void lTransferCall(QString address);
|
||||||
|
|
@ -335,7 +331,6 @@ private:
|
||||||
bool mSpeakerMuted = false;
|
bool mSpeakerMuted = false;
|
||||||
bool mMicrophoneMuted = false;
|
bool mMicrophoneMuted = false;
|
||||||
bool mLocalVideoEnabled = false;
|
bool mLocalVideoEnabled = false;
|
||||||
bool mCameraEnabled = false;
|
|
||||||
bool mVideoEnabled = false;
|
bool mVideoEnabled = false;
|
||||||
bool mPaused = false;
|
bool mPaused = false;
|
||||||
bool mRemoteVideoEnabled = false;
|
bool mRemoteVideoEnabled = false;
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@
|
||||||
#include "CallCore.hpp"
|
#include "CallCore.hpp"
|
||||||
#include "CallGui.hpp"
|
#include "CallGui.hpp"
|
||||||
#include "core/App.hpp"
|
#include "core/App.hpp"
|
||||||
#include "model/tool/ToolModel.hpp"
|
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <linphone++/linphone.hh>
|
#include <linphone++/linphone.hh>
|
||||||
|
|
||||||
|
|
@ -97,32 +96,40 @@ void CallList::setSelf(QSharedPointer<CallList> me) {
|
||||||
bool enablingVideo = false;
|
bool enablingVideo = false;
|
||||||
if (currentCall) enablingVideo = currentCall->getCurrentParams()->videoEnabled();
|
if (currentCall) enablingVideo = currentCall->getCurrentParams()->videoEnabled();
|
||||||
if (!conference) {
|
if (!conference) {
|
||||||
|
auto parameters = core->createConferenceParams(conference);
|
||||||
auto audioVideoConfFactoryUri =
|
auto audioVideoConfFactoryUri =
|
||||||
core->getDefaultAccount()->getParams()->getAudioVideoConferenceFactoryAddress();
|
core->getDefaultAccount()->getParams()->getAudioVideoConferenceFactoryAddress();
|
||||||
QString subject = audioVideoConfFactoryUri
|
if (audioVideoConfFactoryUri) {
|
||||||
//: Remote group call
|
parameters->setConferenceFactoryAddress(audioVideoConfFactoryUri);
|
||||||
? tr("remote_group_call")
|
parameters->setSubject("Meeting");
|
||||||
//: "Local group call"
|
|
||||||
: tr("local_group_call");
|
|
||||||
auto conference = ToolModel::createConference(subject, nullptr);
|
|
||||||
if (!conference) {
|
|
||||||
lWarning() << log().arg("Failed to merge calls");
|
|
||||||
mModelConnection->invokeToCore([] {
|
|
||||||
Utils::showInformationPopup(tr("info_popup_error_title"),
|
|
||||||
//: Failed to merge calls !
|
|
||||||
tr("info_popup_merge_calls_failed_message"), false);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
conference->addParticipants(currentCalls);
|
parameters->setSubject("Local meeting");
|
||||||
|
}
|
||||||
|
parameters->enableVideo(enablingVideo);
|
||||||
|
conference = core->createConferenceWithParams(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<std::shared_ptr<linphone::Address>> allLinphoneAddresses;
|
||||||
|
std::list<std::shared_ptr<linphone::Address>> newCalls;
|
||||||
|
std::list<std::shared_ptr<linphone::Call>> runningCallsToAdd;
|
||||||
|
|
||||||
|
for (auto call : currentCalls) {
|
||||||
|
if (!call->getConference()) {
|
||||||
|
runningCallsToAdd.push_back(call);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1) Add running calls
|
||||||
|
if (runningCallsToAdd.size() > 0) {
|
||||||
|
conference->addParticipants(runningCallsToAdd);
|
||||||
|
}
|
||||||
|
|
||||||
// emit lUpdate();
|
// emit lUpdate();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
mModelConnection->makeConnectToModel(&CoreModel::firstCallStarted,
|
mModelConnection->makeConnectToModel(&CoreModel::firstCallStarted,
|
||||||
[this]() { mModelConnection->invokeToCore([this]() { lUpdate(); }); });
|
[this]() { mModelConnection->invokeToCore([this]() { lUpdate(); }); });
|
||||||
mModelConnection->makeConnectToModel(&CoreModel::lastCallEnded, [this]() {
|
mModelConnection->makeConnectToModel(&CoreModel::lastCallEnded, [this]() {
|
||||||
mModelConnection->invokeToCore([this]() {
|
mModelConnection->invokeToCore([this]() {
|
||||||
setHaveCall(false);
|
setHaveCall(false);
|
||||||
|
|
@ -151,8 +158,12 @@ CallGui *CallList::getCurrentCall() const {
|
||||||
else return nullptr;
|
else return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallList::setCurrentCall(CallGui *callGui) {
|
void CallList::setCurrentCall(CallGui* callGui) {
|
||||||
setCurrentCallCore(callGui ? callGui->mCore : nullptr);
|
auto callCore = callGui ? callGui->mCore : nullptr;
|
||||||
|
if (mCurrentCall != callCore) {
|
||||||
|
mCurrentCall = callCore;
|
||||||
|
emit currentCallChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallList::setCurrentCallCore(QSharedPointer<CallCore> call) {
|
void CallList::setCurrentCallCore(QSharedPointer<CallCore> call) {
|
||||||
|
|
@ -173,21 +184,16 @@ void CallList::setHaveCall(bool haveCall) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<CallCore> CallList::getNextCall() {
|
QSharedPointer<CallCore> CallList::getNextCall() const {
|
||||||
|
QSharedPointer<CallCore> call;
|
||||||
auto currentCall = getCurrentCallCore();
|
auto currentCall = getCurrentCallCore();
|
||||||
for (auto &item : getSharedList<CallCore>()) {
|
for (auto it = mList.rbegin(); !call && it != mList.rend(); ++it) {
|
||||||
if (item != currentCall) return item;
|
if (*it != currentCall) {
|
||||||
|
call = it->objectCast<CallCore>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedPointer<CallCore> CallList::getFirstIncommingPendingCall() {
|
return call;
|
||||||
auto callList = getSharedList<CallCore>();
|
|
||||||
auto it = std::find_if(callList.begin(), callList.end(), [](const QSharedPointer<CallCore> call) {
|
|
||||||
return call->getState() == LinphoneEnums::CallState::IncomingReceived;
|
|
||||||
});
|
|
||||||
if (it == callList.end()) return nullptr;
|
|
||||||
return *it;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallList::onStateChanged() {
|
void CallList::onStateChanged() {
|
||||||
|
|
@ -196,26 +202,21 @@ void CallList::onStateChanged() {
|
||||||
case LinphoneEnums::CallState::StreamsRunning:
|
case LinphoneEnums::CallState::StreamsRunning:
|
||||||
case LinphoneEnums::CallState::Resuming: {
|
case LinphoneEnums::CallState::Resuming: {
|
||||||
auto sharedCall = get(call);
|
auto sharedCall = get(call);
|
||||||
setCurrentCallCore(sharedCall ? sharedCall.objectCast<CallCore>() : nullptr);
|
setCurrentCallCore(sharedCall.objectCast<CallCore>());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LinphoneEnums::CallState::Released: {
|
case LinphoneEnums::CallState::Released: {
|
||||||
auto sharedCall = get(call);
|
auto sharedCall = get(call);
|
||||||
if (sharedCall) {
|
auto currentCall = getCurrentCallCore();
|
||||||
auto currentCall = getCurrentCallCore();
|
// Update current call
|
||||||
sharedCall->disconnect(this);
|
if (sharedCall == currentCall) {
|
||||||
// Update current call
|
// Unpause the next call. The current call will change on resume.
|
||||||
if (currentCall == sharedCall) {
|
// Assumption: All calls that are not the current are paused.
|
||||||
auto nextCall = getNextCall();
|
auto nextCall = getNextCall();
|
||||||
if (nextCall) {
|
if (nextCall) nextCall->lSetPaused(false);
|
||||||
// Unpause the next call. The current call will change on resume.
|
|
||||||
// Assumption: All calls that are not the current are paused.
|
|
||||||
nextCall->lSetPaused(false);
|
|
||||||
}
|
|
||||||
setCurrentCallCore(nextCall);
|
|
||||||
}
|
|
||||||
bool removed = remove(sharedCall);
|
|
||||||
}
|
}
|
||||||
|
sharedCall->disconnect(this);
|
||||||
|
remove(sharedCall);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ class CoreModel;
|
||||||
|
|
||||||
class CallList : public ListProxy, public AbstractObject {
|
class CallList : public ListProxy, public AbstractObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(CallGui *currentCall READ getCurrentCall WRITE setCurrentCall NOTIFY currentCallChanged)
|
Q_PROPERTY(CallGui* currentCall READ getCurrentCall WRITE setCurrentCall NOTIFY currentCallChanged)
|
||||||
public:
|
public:
|
||||||
static QSharedPointer<CallList> create();
|
static QSharedPointer<CallList> create();
|
||||||
// Create a CallCore and make connections to List.
|
// Create a CallCore and make connections to List.
|
||||||
|
|
@ -45,7 +45,7 @@ public:
|
||||||
|
|
||||||
CallGui *getCurrentCall() const; // Used for Ui
|
CallGui *getCurrentCall() const; // Used for Ui
|
||||||
QSharedPointer<CallCore> getCurrentCallCore() const;
|
QSharedPointer<CallCore> getCurrentCallCore() const;
|
||||||
void setCurrentCall(CallGui *callGui);
|
void setCurrentCall(CallGui* callGui);
|
||||||
void setCurrentCallCore(QSharedPointer<CallCore> call);
|
void setCurrentCallCore(QSharedPointer<CallCore> call);
|
||||||
|
|
||||||
bool getHaveCall() const;
|
bool getHaveCall() const;
|
||||||
|
|
@ -53,9 +53,7 @@ public:
|
||||||
|
|
||||||
// Get the next call after the current one. Used to switch the current call.
|
// Get the next call after the current one. Used to switch the current call.
|
||||||
// At the moment, it select the last call in the list.
|
// At the moment, it select the last call in the list.
|
||||||
QSharedPointer<CallCore> getNextCall();
|
QSharedPointer<CallCore> getNextCall() const;
|
||||||
|
|
||||||
QSharedPointer<CallCore> getFirstIncommingPendingCall();
|
|
||||||
|
|
||||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
signals:
|
signals:
|
||||||
|
|
|
||||||
|
|
@ -25,32 +25,20 @@
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(CallProxy)
|
DEFINE_ABSTRACT_OBJECT(CallProxy)
|
||||||
|
|
||||||
CallProxy::CallProxy() : SortFilterProxy() {
|
CallProxy::CallProxy(QObject *parent) : LimitProxy(parent) {
|
||||||
mShowCurrentCall = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CallProxy::~CallProxy() {
|
CallProxy::~CallProxy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
CallGui *CallProxy::getCurrentCall() {
|
CallGui *CallProxy::getCurrentCall() {
|
||||||
auto model = qobject_cast<CallList *>(sourceModel());
|
auto model = getListModel<CallList>();
|
||||||
if (!mCurrentCall && model) mCurrentCall = model->getCurrentCall();
|
if (!mCurrentCall && model) mCurrentCall = model->getCurrentCall();
|
||||||
return mCurrentCall;
|
return mCurrentCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallProxy::setShowCurrentCall(bool show) {
|
|
||||||
if (mShowCurrentCall != show) {
|
|
||||||
mShowCurrentCall = show;
|
|
||||||
emit showCurrentCallChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CallProxy::showCurrentCall() const {
|
|
||||||
return mShowCurrentCall;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CallProxy::setCurrentCall(CallGui *call) {
|
void CallProxy::setCurrentCall(CallGui *call) {
|
||||||
qobject_cast<CallList *>(sourceModel())->setCurrentCall(call);
|
getListModel<CallList>()->setCurrentCall(call);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the default account to let UI build its new object if needed.
|
// Reset the default account to let UI build its new object if needed.
|
||||||
|
|
@ -60,12 +48,12 @@ void CallProxy::resetCurrentCall() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallProxy::getHaveCall() const {
|
bool CallProxy::getHaveCall() const {
|
||||||
auto model = qobject_cast<CallList *>(sourceModel());
|
auto model = getListModel<CallList>();
|
||||||
return model ? model->getHaveCall() : false;
|
return model ? model->getHaveCall() : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallProxy::setSourceModel(QAbstractItemModel *model) {
|
void CallProxy::setSourceModel(QAbstractItemModel *model) {
|
||||||
auto oldCallList = qobject_cast<CallList *>(sourceModel());
|
auto oldCallList = getListModel<CallList>();
|
||||||
if (oldCallList) {
|
if (oldCallList) {
|
||||||
disconnect(oldCallList);
|
disconnect(oldCallList);
|
||||||
}
|
}
|
||||||
|
|
@ -75,24 +63,24 @@ void CallProxy::setSourceModel(QAbstractItemModel *model) {
|
||||||
connect(newCallList, &CallList::haveCallChanged, this, &CallProxy::haveCallChanged, Qt::QueuedConnection);
|
connect(newCallList, &CallList::haveCallChanged, this, &CallProxy::haveCallChanged, Qt::QueuedConnection);
|
||||||
connect(this, &CallProxy::lMergeAll, newCallList, &CallList::lMergeAll);
|
connect(this, &CallProxy::lMergeAll, newCallList, &CallList::lMergeAll);
|
||||||
}
|
}
|
||||||
QSortFilterProxyModel::setSourceModel(model);
|
setSourceModels(new SortFilterList(model, Qt::AscendingOrder));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
bool CallProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
||||||
bool show = (mFilterText.isEmpty() || mFilterText == "*");
|
bool show = (mFilterText.isEmpty() || mFilterText == "*");
|
||||||
auto callList = qobject_cast<CallList *>(sourceModel());
|
|
||||||
auto call = callList->getAt<CallCore>(sourceRow);
|
|
||||||
if (!mShowCurrentCall && call == callList->getCurrentCallCore()) return false;
|
|
||||||
if (!show) {
|
if (!show) {
|
||||||
QRegularExpression search(QRegularExpression::escape(mFilterText),
|
QRegularExpression search(QRegularExpression::escape(mFilterText),
|
||||||
QRegularExpression::CaseInsensitiveOption |
|
QRegularExpression::CaseInsensitiveOption |
|
||||||
QRegularExpression::UseUnicodePropertiesOption);
|
QRegularExpression::UseUnicodePropertiesOption);
|
||||||
|
auto call = qobject_cast<CallList *>(sourceModel())->getAt<CallCore>(sourceRow);
|
||||||
|
|
||||||
show = call->getRemoteAddress().contains(search);
|
show = call->getRemoteAddress().contains(search);
|
||||||
}
|
}
|
||||||
|
|
||||||
return show;
|
return show;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallProxy::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const {
|
bool CallProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const {
|
||||||
auto l = getItemAtSource<CallList, CallCore>(sourceLeft.row());
|
auto l = getItemAtSource<CallList, CallCore>(sourceLeft.row());
|
||||||
auto r = getItemAtSource<CallList, CallCore>(sourceRight.row());
|
auto r = getItemAtSource<CallList, CallCore>(sourceRight.row());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,14 +28,15 @@
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
class CallProxy : public SortFilterProxy, public AbstractObject {
|
class CallProxy : public LimitProxy, public AbstractObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(CallGui *currentCall READ getCurrentCall WRITE setCurrentCall NOTIFY currentCallChanged)
|
Q_PROPERTY(CallGui *currentCall READ getCurrentCall WRITE setCurrentCall NOTIFY currentCallChanged)
|
||||||
Q_PROPERTY(bool haveCall READ getHaveCall NOTIFY haveCallChanged)
|
Q_PROPERTY(bool haveCall READ getHaveCall NOTIFY haveCallChanged)
|
||||||
Q_PROPERTY(bool showCurrentCall READ showCurrentCall WRITE setShowCurrentCall NOTIFY showCurrentCallChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CallProxy();
|
DECLARE_SORTFILTER_CLASS()
|
||||||
|
|
||||||
|
CallProxy(QObject *parent = Q_NULLPTR);
|
||||||
~CallProxy();
|
~CallProxy();
|
||||||
|
|
||||||
// Get a new object from List or give the stored one.
|
// Get a new object from List or give the stored one.
|
||||||
|
|
@ -47,23 +48,15 @@ public:
|
||||||
|
|
||||||
bool getHaveCall() const;
|
bool getHaveCall() const;
|
||||||
|
|
||||||
void setShowCurrentCall(bool show);
|
|
||||||
bool showCurrentCall() const;
|
|
||||||
|
|
||||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||||
|
|
||||||
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
|
||||||
virtual bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void lMergeAll();
|
void lMergeAll();
|
||||||
void currentCallChanged();
|
void currentCallChanged();
|
||||||
void haveCallChanged();
|
void haveCallChanged();
|
||||||
void showCurrentCallChanged();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CallGui *mCurrentCall = nullptr; // When null, a new UI object is build from List
|
CallGui *mCurrentCall = nullptr; // When null, a new UI object is build from List
|
||||||
bool mShowCurrentCall = false;
|
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -71,12 +71,10 @@ QQuickFramebufferObject::Renderer *PreviewManager::subscribe(const CameraGui *ca
|
||||||
App::postModelBlock([&renderer, isFirst = (itCandidate == mCandidates.begin()),
|
App::postModelBlock([&renderer, isFirst = (itCandidate == mCandidates.begin()),
|
||||||
name = itCandidate->first->getQmlName()]() {
|
name = itCandidate->first->getQmlName()]() {
|
||||||
renderer =
|
renderer =
|
||||||
(QQuickFramebufferObject::Renderer *)CoreModel::getInstance()->getCore()->createNativePreviewWindowId(
|
(QQuickFramebufferObject::Renderer *)CoreModel::getInstance()->getCore()->createNativePreviewWindowId();
|
||||||
nullptr);
|
|
||||||
if (!renderer) { // TODO debug
|
if (!renderer) { // TODO debug
|
||||||
renderer =
|
renderer =
|
||||||
(QQuickFramebufferObject::Renderer *)CoreModel::getInstance()->getCore()->createNativePreviewWindowId(
|
(QQuickFramebufferObject::Renderer *)CoreModel::getInstance()->getCore()->createNativePreviewWindowId();
|
||||||
nullptr);
|
|
||||||
}
|
}
|
||||||
if (isFirst) {
|
if (isFirst) {
|
||||||
lDebug() << "[PreviewManager] " << name << " Set Native Preview Id with " << renderer;
|
lDebug() << "[PreviewManager] " << name << " Set Native Preview Id with " << renderer;
|
||||||
|
|
|
||||||
|
|
@ -1,686 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ChatCore.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "core/chat/message/content/ChatMessageContentGui.hpp"
|
|
||||||
#include "core/friend/FriendCore.hpp"
|
|
||||||
#include "core/setting/SettingsCore.hpp"
|
|
||||||
#include "model/chat/message/EventLogModel.hpp"
|
|
||||||
#include "model/core/CoreModel.hpp"
|
|
||||||
#include "model/friend/FriendModel.hpp"
|
|
||||||
#include "model/tool/ToolModel.hpp"
|
|
||||||
#include "tool/Utils.hpp"
|
|
||||||
|
|
||||||
#include <QQuickWindow>
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ChatCore)
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
|
|
||||||
QSharedPointer<ChatCore> ChatCore::create(const std::shared_ptr<linphone::ChatRoom> &chatRoom) {
|
|
||||||
auto sharedPointer = QSharedPointer<ChatCore>(new ChatCore(chatRoom), &QObject::deleteLater);
|
|
||||||
sharedPointer->setSelf(sharedPointer);
|
|
||||||
sharedPointer->moveToThread(App::getInstance()->thread());
|
|
||||||
return sharedPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatCore::ChatCore(const std::shared_ptr<linphone::ChatRoom> &chatRoom) : QObject(nullptr) {
|
|
||||||
// lDebug() << "[ChatCore] new" << this;
|
|
||||||
mustBeInLinphoneThread(getClassName());
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
|
||||||
mLastUpdatedTime = QDateTime::fromSecsSinceEpoch(chatRoom->getLastUpdateTime());
|
|
||||||
auto chatRoomAddress = chatRoom->getPeerAddress();
|
|
||||||
mChatRoomAddress = Utils::coreStringToAppString(chatRoomAddress->asStringUriOnly());
|
|
||||||
if (chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::Basic)) {
|
|
||||||
mTitle = ToolModel::getDisplayName(chatRoomAddress);
|
|
||||||
mAvatarUri = ToolModel::getDisplayName(chatRoomAddress);
|
|
||||||
mParticipantAddress = Utils::coreStringToAppString(chatRoomAddress->asStringUriOnly());
|
|
||||||
mIsGroupChat = false;
|
|
||||||
mIsBasic = true;
|
|
||||||
mConferenceJoined = true;
|
|
||||||
} else {
|
|
||||||
mIsBasic = false;
|
|
||||||
auto participants = chatRoom->getParticipants();
|
|
||||||
if (chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::OneToOne)) {
|
|
||||||
if (participants.size() > 0) {
|
|
||||||
auto peer = participants.front();
|
|
||||||
auto peerAddress = peer->getAddress();
|
|
||||||
if (peer) mTitle = ToolModel::getDisplayName(peerAddress);
|
|
||||||
mAvatarUri = ToolModel::getDisplayName(peerAddress);
|
|
||||||
if (participants.size() == 1) {
|
|
||||||
if (peerAddress) mParticipantAddress = Utils::coreStringToAppString(peerAddress->asStringUriOnly());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mIsGroupChat = false;
|
|
||||||
} else if (chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::Conference)) {
|
|
||||||
mTitle = Utils::coreStringToAppString(chatRoom->getSubject());
|
|
||||||
mAvatarUri = Utils::coreStringToAppString(chatRoom->getSubject());
|
|
||||||
mIsGroupChat = true;
|
|
||||||
mMeAdmin = chatRoom->getMe() && chatRoom->getMe()->isAdmin();
|
|
||||||
}
|
|
||||||
mConferenceJoined = participants.size() != 0;
|
|
||||||
}
|
|
||||||
mUnreadMessagesCount = chatRoom->getUnreadMessagesCount();
|
|
||||||
connect(this, &ChatCore::unreadMessagesCountChanged, this, [this] {
|
|
||||||
if (mUnreadMessagesCount == 0) emit lMarkAsRead();
|
|
||||||
});
|
|
||||||
mChatModel = Utils::makeQObject_ptr<ChatModel>(chatRoom);
|
|
||||||
mChatModel->setSelf(mChatModel);
|
|
||||||
auto lastMessage = chatRoom->getLastMessageInHistory();
|
|
||||||
mLastMessage = lastMessage ? ChatMessageCore::create(lastMessage) : nullptr;
|
|
||||||
|
|
||||||
int filter = mIsGroupChat ? static_cast<int>(linphone::ChatRoom::HistoryFilter::ChatMessage) |
|
|
||||||
static_cast<int>(linphone::ChatRoom::HistoryFilter::InfoNoDevice)
|
|
||||||
: static_cast<int>(linphone::ChatRoom::HistoryFilter::ChatMessage);
|
|
||||||
|
|
||||||
mIdentifier = Utils::coreStringToAppString(chatRoom->getIdentifier());
|
|
||||||
mChatRoomState = LinphoneEnums::fromLinphone(chatRoom->getState());
|
|
||||||
mIsEncrypted = chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::Encrypted);
|
|
||||||
auto localAccount = ToolModel::findAccount(chatRoom->getLocalAddress());
|
|
||||||
mLocalAddress = Utils::coreStringToAppString(chatRoom->getLocalAddress()->asStringUriOnly());
|
|
||||||
bool associatedAccountHasIMEncryptionMandatory =
|
|
||||||
localAccount && localAccount->getParams() &&
|
|
||||||
localAccount->getParams()->getInstantMessagingEncryptionMandatory();
|
|
||||||
mIsReadOnly = chatRoom->isReadOnly() || (!mIsEncrypted && associatedAccountHasIMEncryptionMandatory);
|
|
||||||
|
|
||||||
connect(this, &ChatCore::eventsInserted, this, &ChatCore::lUpdateLastMessage);
|
|
||||||
|
|
||||||
mEphemeralEnabled = chatRoom->ephemeralEnabled();
|
|
||||||
mEphemeralLifetime = chatRoom->ephemeralEnabled() ? chatRoom->getEphemeralLifetime() : 0;
|
|
||||||
mIsMuted = chatRoom->getMuted();
|
|
||||||
mParticipants = buildParticipants(chatRoom);
|
|
||||||
|
|
||||||
connect(this, &ChatCore::participantsChanged, this, [this] {
|
|
||||||
// refresh secured status of the chatroom
|
|
||||||
setIsSecured(computeSecuredStatus());
|
|
||||||
});
|
|
||||||
mIsSecured = computeSecuredStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatCore::~ChatCore() {
|
|
||||||
lDebug() << "[ChatCore] delete" << this;
|
|
||||||
mustBeInMainThread("~" + getClassName());
|
|
||||||
if (mChatModelConnection) mChatModelConnection->disconnect();
|
|
||||||
emit mChatModel->removeListener();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setSelf(QSharedPointer<ChatCore> me) {
|
|
||||||
mChatModelConnection = SafeConnection<ChatCore, ChatModel>::create(me, mChatModel);
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lDeleteHistory, [this]() {
|
|
||||||
mChatModelConnection->invokeToModel([this]() { mChatModel->deleteHistory(); });
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lDeleteMessage, [this](ChatMessageGui *message) {
|
|
||||||
mChatModelConnection->invokeToModel([this, core = message ? message->mCore : nullptr]() {
|
|
||||||
auto messageModel = core ? core->getModel() : nullptr;
|
|
||||||
if (messageModel) {
|
|
||||||
mChatModel->deleteMessage(messageModel->getMonitor());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatModelConnection->makeConnectToCore(
|
|
||||||
&ChatCore::lLeave, [this]() { mChatModelConnection->invokeToModel([this]() { mChatModel->leave(); }); });
|
|
||||||
mChatModelConnection->makeConnectToModel(&ChatModel::historyDeleted, [this]() {
|
|
||||||
mChatModelConnection->invokeToCore([this]() {
|
|
||||||
emit eventListCleared();
|
|
||||||
//: Deleted
|
|
||||||
Utils::showInformationPopup(tr("info_toast_deleted_title"),
|
|
||||||
//: Message history has been deleted
|
|
||||||
tr("info_toast_deleted_message_history"), true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lUpdateUnreadCount, [this]() {
|
|
||||||
mChatModelConnection->invokeToModel([this]() {
|
|
||||||
auto count = mChatModel->getUnreadMessagesCount();
|
|
||||||
mChatModelConnection->invokeToCore([this, count] { setUnreadMessagesCount(count); });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lUpdateLastUpdatedTime, [this]() {
|
|
||||||
mChatModelConnection->invokeToModel([this]() {
|
|
||||||
auto time = mChatModel->getLastUpdateTime();
|
|
||||||
mChatModelConnection->invokeToCore([this, time]() { setLastUpdatedTime(time); });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lDelete, [this]() {
|
|
||||||
mChatModelConnection->invokeToModel([this]() { mChatModel->deleteChatRoom(); });
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatModelConnection->makeConnectToModel(
|
|
||||||
&ChatModel::stateChanged,
|
|
||||||
[this](const std::shared_ptr<linphone::ChatRoom> &chatRoom, linphone::ChatRoom::State newState) {
|
|
||||||
auto state = LinphoneEnums::fromLinphone(newState);
|
|
||||||
bool isReadOnly = chatRoom->isReadOnly();
|
|
||||||
if (newState == linphone::ChatRoom::State::Deleted) emit deleted();
|
|
||||||
mChatModelConnection->invokeToCore([this, state, isReadOnly]() {
|
|
||||||
setChatRoomState(state);
|
|
||||||
setIsReadOnly(isReadOnly);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToModel(
|
|
||||||
&ChatModel::conferenceJoined, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
|
||||||
auto participants = buildParticipants(chatRoom);
|
|
||||||
if (chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::OneToOne)) {
|
|
||||||
QString title, avatarUri;
|
|
||||||
auto linParticipants = chatRoom->getParticipants();
|
|
||||||
if (linParticipants.size() > 0) {
|
|
||||||
auto peer = linParticipants.front();
|
|
||||||
if (peer) title = ToolModel::getDisplayName(peer->getAddress());
|
|
||||||
avatarUri = ToolModel::getDisplayName(peer->getAddress());
|
|
||||||
if (linParticipants.size() == 1) {
|
|
||||||
auto peerAddress = peer->getAddress();
|
|
||||||
if (peerAddress)
|
|
||||||
mParticipantAddress = Utils::coreStringToAppString(peerAddress->asStringUriOnly());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mChatModelConnection->invokeToCore([this, title, avatarUri]() {
|
|
||||||
setTitle(title);
|
|
||||||
setAvatarUri(avatarUri);
|
|
||||||
mConferenceJoined = true;
|
|
||||||
emit conferenceJoined();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
mChatModelConnection->invokeToCore([this, participants]() { setParticipants(participants); });
|
|
||||||
});
|
|
||||||
|
|
||||||
// Events (excluding messages)
|
|
||||||
mChatModelConnection->makeConnectToModel(
|
|
||||||
&ChatModel::newEvent, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
|
||||||
if (mChatModel->getMonitor() != chatRoom) return;
|
|
||||||
lDebug() << "EVENT LOG RECEIVED IN CHATROOM" << mChatModel->getTitle();
|
|
||||||
auto event = EventLogCore::create(eventLog, chatRoom);
|
|
||||||
if (event->isHandled()) {
|
|
||||||
mChatModelConnection->invokeToCore([this, event]() { emit eventsInserted({event}); });
|
|
||||||
}
|
|
||||||
mChatModelConnection->invokeToCore([this, event]() { emit lUpdateLastUpdatedTime(); });
|
|
||||||
});
|
|
||||||
|
|
||||||
// Chat messages
|
|
||||||
mChatModelConnection->makeConnectToModel(
|
|
||||||
&ChatModel::chatMessagesReceived, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::list<std::shared_ptr<linphone::EventLog>> &eventsLog) {
|
|
||||||
if (mChatModel->getMonitor() != chatRoom) return;
|
|
||||||
lDebug() << "CHAT MESSAGE RECEIVED IN CHATROOM" << mChatModel->getTitle();
|
|
||||||
QList<QSharedPointer<EventLogCore>> list;
|
|
||||||
for (auto &e : eventsLog) {
|
|
||||||
auto event = EventLogCore::create(e, chatRoom);
|
|
||||||
list.push_back(event);
|
|
||||||
}
|
|
||||||
mChatModelConnection->invokeToCore([this, list]() {
|
|
||||||
emit eventsInserted(list);
|
|
||||||
emit lUpdateUnreadCount();
|
|
||||||
emit lUpdateLastUpdatedTime();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lMarkAsRead, [this]() {
|
|
||||||
auto lastActiveWindow = Utils::getLastActiveWindow();
|
|
||||||
if (lastActiveWindow && lastActiveWindow->isActive())
|
|
||||||
mChatModelConnection->invokeToModel([this]() { mChatModel->markAsRead(); });
|
|
||||||
else {
|
|
||||||
connect(lastActiveWindow, &QQuickWindow::activeChanged, this, [this, lastActiveWindow] {
|
|
||||||
if (lastActiveWindow->isActive()) {
|
|
||||||
disconnect(lastActiveWindow, &QQuickWindow::activeChanged, this, nullptr);
|
|
||||||
mChatModelConnection->invokeToModel([this, lastActiveWindow] { mChatModel->markAsRead(); });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToModel(&ChatModel::messagesRead, [this]() {
|
|
||||||
auto unread = mChatModel->getUnreadMessagesCount();
|
|
||||||
mChatModelConnection->invokeToCore([this, unread]() { setUnreadMessagesCount(unread); });
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lUpdateLastMessage, [this]() {
|
|
||||||
auto lastMessageModel = mLastMessage ? mLastMessage->getModel() : nullptr;
|
|
||||||
mChatModelConnection->invokeToModel([this, lastMessageModel]() {
|
|
||||||
auto linphoneMessage = mChatModel->getLastChatMessage();
|
|
||||||
if (linphoneMessage && (!lastMessageModel || lastMessageModel->getMonitor() != linphoneMessage)) {
|
|
||||||
auto chatMessageCore = ChatMessageCore::create(linphoneMessage);
|
|
||||||
mChatModelConnection->invokeToCore([this, chatMessageCore]() { setLastMessage(chatMessageCore); });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lSendTextMessage, [this](QString message) {
|
|
||||||
if (Utils::isEmptyMessage(message)) return;
|
|
||||||
mChatModelConnection->invokeToModel([this, message]() {
|
|
||||||
auto linMessage = mChatModel->createTextMessageFromText(message);
|
|
||||||
linMessage->send();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lSendMessage, [this](QString message, QVariantList files) {
|
|
||||||
if (Utils::isEmptyMessage(message) && files.size() == 0) return;
|
|
||||||
QList<std::shared_ptr<ChatMessageContentModel>> filesContent;
|
|
||||||
for (auto &file : files) {
|
|
||||||
auto contentGui = qvariant_cast<ChatMessageContentGui *>(file);
|
|
||||||
if (contentGui) {
|
|
||||||
auto contentCore = contentGui->mCore;
|
|
||||||
filesContent.append(contentCore->getContentModel());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mChatModelConnection->invokeToModel([this, message, filesContent]() {
|
|
||||||
auto linMessage = mChatModel->createMessage(message, filesContent);
|
|
||||||
linMessage->send();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToModel(
|
|
||||||
&ChatModel::chatMessageSending, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
|
||||||
auto event = EventLogCore::create(eventLog, chatRoom);
|
|
||||||
mChatModelConnection->invokeToCore([this, event]() { emit eventsInserted({event}); });
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToCore(
|
|
||||||
&ChatCore::lCompose, [this]() { mChatModelConnection->invokeToModel([this]() { mChatModel->compose(); }); });
|
|
||||||
mChatModelConnection->makeConnectToModel(
|
|
||||||
&ChatModel::isComposingReceived,
|
|
||||||
[this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<const linphone::Address> &remoteAddress, bool isComposing) {
|
|
||||||
if (mChatModel->getMonitor() != chatRoom) return;
|
|
||||||
QString name = isComposing ? ToolModel::getDisplayName(remoteAddress) : QString();
|
|
||||||
auto remoteAddr = remoteAddress;
|
|
||||||
// remoteAddr->clean();
|
|
||||||
mChatModelConnection->invokeToCore(
|
|
||||||
[this, name, address = Utils::coreStringToAppString(remoteAddr->asStringUriOnly())]() {
|
|
||||||
setComposingName(name);
|
|
||||||
setComposingAddress(address);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lSetMuted, [this](bool muted) {
|
|
||||||
mChatModelConnection->invokeToModel([this, muted]() { mChatModel->setMuted(muted); });
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToModel(&ChatModel::mutedChanged, [this](bool muted) {
|
|
||||||
mChatModelConnection->invokeToCore([this, muted]() {
|
|
||||||
if (mIsMuted != muted) {
|
|
||||||
mIsMuted = muted;
|
|
||||||
emit mutedChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lEnableEphemeral, [this](bool enable) {
|
|
||||||
mChatModelConnection->invokeToModel([this, enable]() { mChatModel->enableEphemeral(enable); });
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToModel(&ChatModel::ephemeralEnableChanged, [this](bool enable) {
|
|
||||||
mChatModelConnection->invokeToCore([this, enable]() {
|
|
||||||
if (mEphemeralEnabled != enable) {
|
|
||||||
mEphemeralEnabled = enable;
|
|
||||||
emit ephemeralEnabledChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lSetEphemeralLifetime, [this](int time) {
|
|
||||||
mChatModelConnection->invokeToModel([this, time]() { mChatModel->setEphemeralLifetime(time); });
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToModel(&ChatModel::ephemeralLifetimeChanged, [this](int time) {
|
|
||||||
mChatModelConnection->invokeToCore([this, time]() {
|
|
||||||
if (mEphemeralLifetime != time) {
|
|
||||||
mEphemeralLifetime = time;
|
|
||||||
emit ephemeralLifetimeChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lSetSubject, [this](QString subject) {
|
|
||||||
mChatModelConnection->invokeToModel([this, subject]() { mChatModel->setSubject(subject); });
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToModel(
|
|
||||||
&ChatModel::subjectChanged, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
|
||||||
QString subject = Utils::coreStringToAppString(chatRoom->getSubject());
|
|
||||||
mChatModelConnection->invokeToCore([this, subject]() { setTitle(subject); });
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatModelConnection->makeConnectToModel(
|
|
||||||
&ChatModel::participantAdded, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
|
||||||
auto participants = buildParticipants(chatRoom);
|
|
||||||
mChatModelConnection->invokeToCore([this, participants]() { setParticipants(participants); });
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToModel(
|
|
||||||
&ChatModel::participantRemoved, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
|
||||||
auto participants = buildParticipants(chatRoom);
|
|
||||||
mChatModelConnection->invokeToCore([this, participants]() { setParticipants(participants); });
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToModel(&ChatModel::participantAdminStatusChanged,
|
|
||||||
[this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
|
||||||
auto participants = buildParticipants(chatRoom);
|
|
||||||
bool meAdmin = chatRoom->getMe()->isAdmin();
|
|
||||||
mChatModelConnection->invokeToCore([this, participants, meAdmin]() {
|
|
||||||
setParticipants(participants);
|
|
||||||
setMeAdmin(meAdmin);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lRemoveParticipantAtIndex, [this](int index) {
|
|
||||||
mChatModelConnection->invokeToModel([this, index]() { mChatModel->removeParticipantAtIndex(index); });
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lSetParticipantsAddresses, [this](QStringList addresses) {
|
|
||||||
mChatModelConnection->invokeToModel([this, addresses]() { mChatModel->setParticipantAddresses(addresses); });
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatModelConnection->makeConnectToCore(&ChatCore::lToggleParticipantAdminStatusAtIndex, [this](int index) {
|
|
||||||
mChatModelConnection->invokeToModel(
|
|
||||||
[this, index]() { mChatModel->toggleParticipantAdminStatusAtIndex(index); });
|
|
||||||
});
|
|
||||||
|
|
||||||
mCoreModelConnection = SafeConnection<ChatCore, CoreModel>::create(me, CoreModel::getInstance());
|
|
||||||
if (!ToolModel::findFriendByAddress(mParticipantAddress))
|
|
||||||
mCoreModelConnection->makeConnectToModel(&CoreModel::friendCreated,
|
|
||||||
[this](std::shared_ptr<linphone::Friend> f) { updateInfo(f); });
|
|
||||||
mCoreModelConnection->makeConnectToModel(&CoreModel::friendUpdated,
|
|
||||||
[this](std::shared_ptr<linphone::Friend> f) { updateInfo(f); });
|
|
||||||
mCoreModelConnection->makeConnectToModel(&CoreModel::friendRemoved,
|
|
||||||
[this](std::shared_ptr<linphone::Friend> f) { updateInfo(f, true); });
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QDateTime ChatCore::getLastUpdatedTime() const {
|
|
||||||
return mLastUpdatedTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setLastUpdatedTime(QDateTime time) {
|
|
||||||
if (mLastUpdatedTime != time) {
|
|
||||||
mLastUpdatedTime = time;
|
|
||||||
emit lastUpdatedTimeChanged(time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatCore::getTitle() const {
|
|
||||||
return mTitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setTitle(QString title) {
|
|
||||||
if (mTitle != title) {
|
|
||||||
mTitle = title;
|
|
||||||
emit titleChanged(title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatCore::getSendingText() const {
|
|
||||||
return mSendingText;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setSendingText(const QString &text) {
|
|
||||||
if (mSendingText != text) {
|
|
||||||
mSendingText = text;
|
|
||||||
emit sendingTextChanged(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatCore::isGroupChat() const {
|
|
||||||
return mIsGroupChat;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatCore::isEncrypted() const {
|
|
||||||
return mIsEncrypted;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatCore::getIdentifier() const {
|
|
||||||
return mIdentifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatCore::getParticipantAddress() const {
|
|
||||||
return mParticipantAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatCore::getChatRoomAddress() const {
|
|
||||||
return mChatRoomAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatCore::getAvatarUri() const {
|
|
||||||
return mAvatarUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setAvatarUri(QString avatarUri) {
|
|
||||||
if (mAvatarUri != avatarUri) {
|
|
||||||
mAvatarUri = avatarUri;
|
|
||||||
emit avatarUriChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatCore::getLastMessageText() const {
|
|
||||||
return mLastMessage ? mLastMessage->getText() : QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
LinphoneEnums::ChatMessageState ChatCore::getLastMessageState() const {
|
|
||||||
return mLastMessage ? mLastMessage->getMessageState() : LinphoneEnums::ChatMessageState::StateIdle;
|
|
||||||
}
|
|
||||||
|
|
||||||
LinphoneEnums::ChatRoomState ChatCore::getChatRoomState() const {
|
|
||||||
return mChatRoomState;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setChatRoomState(LinphoneEnums::ChatRoomState state) {
|
|
||||||
if (mChatRoomState != state) {
|
|
||||||
mChatRoomState = state;
|
|
||||||
emit chatRoomStateChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setIsReadOnly(bool readOnly) {
|
|
||||||
if (mIsReadOnly != readOnly) {
|
|
||||||
mIsReadOnly = readOnly;
|
|
||||||
emit readOnlyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatCore::getIsReadOnly() const {
|
|
||||||
return mIsReadOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageGui *ChatCore::getLastMessage() const {
|
|
||||||
return mLastMessage ? new ChatMessageGui(mLastMessage) : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setLastMessage(QSharedPointer<ChatMessageCore> lastMessage) {
|
|
||||||
if (mLastMessage != lastMessage) {
|
|
||||||
if (mLastMessage) disconnect(mLastMessage.get(), &ChatMessageCore::messageStateChanged, this, nullptr);
|
|
||||||
mLastMessage = lastMessage;
|
|
||||||
connect(mLastMessage.get(), &ChatMessageCore::messageStateChanged, this, &ChatCore::lastMessageChanged);
|
|
||||||
emit lastMessageChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int ChatCore::getUnreadMessagesCount() const {
|
|
||||||
return mUnreadMessagesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setUnreadMessagesCount(int count) {
|
|
||||||
if (mUnreadMessagesCount != count) {
|
|
||||||
mUnreadMessagesCount = count;
|
|
||||||
emit unreadMessagesCountChanged(count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatCore::getComposingName() const {
|
|
||||||
return mComposingName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setComposingName(QString composingName) {
|
|
||||||
if (mComposingAddress != composingName) {
|
|
||||||
mComposingName = composingName;
|
|
||||||
emit composingUserChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setComposingAddress(QString composingAddress) {
|
|
||||||
if (mComposingAddress != composingAddress) {
|
|
||||||
mComposingAddress = composingAddress;
|
|
||||||
emit composingUserChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatCore::getComposingAddress() const {
|
|
||||||
return mComposingAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QSharedPointer<ChatMessageContentCore>> ChatCore::getFileList() const {
|
|
||||||
return mFileList;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::resetFileList(QList<QSharedPointer<ChatMessageContentCore>> list) {
|
|
||||||
mFileList = list;
|
|
||||||
emit fileListChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<ChatModel> ChatCore::getModel() const {
|
|
||||||
return mChatModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatCore::isMuted() const {
|
|
||||||
return mIsMuted;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatCore::isEphemeralEnabled() const {
|
|
||||||
return mEphemeralEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ChatCore::getEphemeralLifetime() const {
|
|
||||||
return mEphemeralLifetime;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setMeAdmin(bool admin) {
|
|
||||||
if (mMeAdmin != admin) {
|
|
||||||
mMeAdmin = admin;
|
|
||||||
emit meAdminChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatCore::getMeAdmin() const {
|
|
||||||
return mMeAdmin;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatCore::isSecured() const {
|
|
||||||
return mIsSecured;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setIsSecured(bool secured) {
|
|
||||||
if (mIsSecured != secured) {
|
|
||||||
mIsSecured = secured;
|
|
||||||
emit isSecuredChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatCore::computeSecuredStatus() const {
|
|
||||||
if (mParticipants.size() == 0) return false;
|
|
||||||
for (auto &participant : mParticipants) {
|
|
||||||
if (participant->getSecurityLevel() != LinphoneEnums::SecurityLevel::EndToEndEncryptedAndVerified) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantList ChatCore::getParticipantsGui() const {
|
|
||||||
QVariantList result;
|
|
||||||
for (auto participantCore : mParticipants) {
|
|
||||||
auto participantGui = new ParticipantGui(participantCore);
|
|
||||||
result.append(QVariant::fromValue(participantGui));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList ChatCore::getParticipantsAddresses() const {
|
|
||||||
QStringList result;
|
|
||||||
for (auto participantCore : mParticipants) {
|
|
||||||
result.append(participantCore->getSipAddress());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::setParticipants(QList<QSharedPointer<ParticipantCore>> participants) {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
mParticipants = participants;
|
|
||||||
emit participantsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QSharedPointer<ParticipantCore>>
|
|
||||||
ChatCore::buildParticipants(const std::shared_ptr<linphone::ChatRoom> &chatRoom) const {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
QList<QSharedPointer<ParticipantCore>> result;
|
|
||||||
for (auto participant : chatRoom->getParticipants()) {
|
|
||||||
auto participantCore = ParticipantCore::create(participant);
|
|
||||||
result.append(participantCore);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QSharedPointer<ParticipantCore>> ChatCore::getParticipants() const {
|
|
||||||
return mParticipants;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatCore::getLocalAddress() const {
|
|
||||||
return mLocalAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatCore::updateInfo(const std::shared_ptr<linphone::Friend> &updatedFriend, bool isRemoval) {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
auto fAddress = ToolModel::interpretUrl(mParticipantAddress);
|
|
||||||
bool isThisFriend = mFriendModel && updatedFriend == mFriendModel->getFriend();
|
|
||||||
if (!isThisFriend)
|
|
||||||
for (auto f : updatedFriend->getAddresses()) {
|
|
||||||
if (f->weakEqual(fAddress)) {
|
|
||||||
isThisFriend = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isThisFriend) {
|
|
||||||
if (isRemoval) {
|
|
||||||
mFriendModel = nullptr;
|
|
||||||
}
|
|
||||||
int capabilities = mChatModel->getCapabilities();
|
|
||||||
auto chatroom = mChatModel->getMonitor();
|
|
||||||
auto chatRoomAddress = chatroom->getPeerAddress();
|
|
||||||
if (mChatModel->hasCapability((int)linphone::ChatRoom::Capabilities::Basic)) {
|
|
||||||
auto title = ToolModel::getDisplayName(chatRoomAddress);
|
|
||||||
auto avatarUri = ToolModel::getDisplayName(chatRoomAddress);
|
|
||||||
mChatModelConnection->invokeToCore([this, title, avatarUri] {
|
|
||||||
setTitle(title);
|
|
||||||
setAvatarUri(avatarUri);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (mChatModel->hasCapability((int)linphone::ChatRoom::Capabilities::OneToOne)) {
|
|
||||||
auto participants = chatroom->getParticipants();
|
|
||||||
if (participants.size() > 0) {
|
|
||||||
auto peer = participants.front();
|
|
||||||
if (peer) {
|
|
||||||
auto title = ToolModel::getDisplayName(peer->getAddress());
|
|
||||||
auto avatarUri = ToolModel::getDisplayName(peer->getAddress());
|
|
||||||
mChatModelConnection->invokeToCore([this, title, avatarUri] {
|
|
||||||
setTitle(title);
|
|
||||||
setAvatarUri(avatarUri);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (mChatModel->hasCapability((int)linphone::ChatRoom::Capabilities::Conference)) {
|
|
||||||
auto title = Utils::coreStringToAppString(chatroom->getSubject());
|
|
||||||
auto avatarUri = Utils::coreStringToAppString(chatroom->getSubject());
|
|
||||||
mChatModelConnection->invokeToCore([this, title, avatarUri] {
|
|
||||||
setTitle(title);
|
|
||||||
setAvatarUri(avatarUri);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,236 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHAT_CORE_H_
|
|
||||||
#define CHAT_CORE_H_
|
|
||||||
|
|
||||||
#include "core/chat/message/EventLogGui.hpp"
|
|
||||||
#include "core/participant/ParticipantCore.hpp"
|
|
||||||
#include "message/ChatMessageGui.hpp"
|
|
||||||
#include "model/chat/ChatModel.hpp"
|
|
||||||
#include "model/search/MagicSearchModel.hpp"
|
|
||||||
#include "tool/LinphoneEnums.hpp"
|
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
|
||||||
#include <QObject>
|
|
||||||
#include <QSharedPointer>
|
|
||||||
#include <linphone++/linphone.hh>
|
|
||||||
|
|
||||||
class EventLogCore;
|
|
||||||
class FriendModel;
|
|
||||||
class AccountCore;
|
|
||||||
|
|
||||||
class ChatCore : public QObject, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
Q_PROPERTY(QString title READ getTitle WRITE setTitle NOTIFY titleChanged)
|
|
||||||
Q_PROPERTY(QString identifier READ getIdentifier CONSTANT)
|
|
||||||
Q_PROPERTY(QString peerAddress READ getParticipantAddress CONSTANT)
|
|
||||||
Q_PROPERTY(QString chatRoomAddress READ getChatRoomAddress CONSTANT)
|
|
||||||
Q_PROPERTY(QString avatarUri READ getAvatarUri WRITE setAvatarUri NOTIFY avatarUriChanged)
|
|
||||||
Q_PROPERTY(QDateTime lastUpdatedTime READ getLastUpdatedTime WRITE setLastUpdatedTime NOTIFY lastUpdatedTimeChanged)
|
|
||||||
Q_PROPERTY(QString lastMessageText READ getLastMessageText NOTIFY lastMessageChanged)
|
|
||||||
Q_PROPERTY(ChatMessageGui *lastMessage READ getLastMessage NOTIFY lastMessageChanged)
|
|
||||||
Q_PROPERTY(LinphoneEnums::ChatMessageState lastMessageState READ getLastMessageState NOTIFY lastMessageChanged)
|
|
||||||
Q_PROPERTY(LinphoneEnums::ChatRoomState state READ getChatRoomState NOTIFY chatRoomStateChanged)
|
|
||||||
Q_PROPERTY(int unreadMessagesCount READ getUnreadMessagesCount WRITE setUnreadMessagesCount NOTIFY
|
|
||||||
unreadMessagesCountChanged)
|
|
||||||
Q_PROPERTY(QString composingName READ getComposingName WRITE setComposingName NOTIFY composingUserChanged)
|
|
||||||
Q_PROPERTY(QString composingAddress READ getComposingAddress WRITE setComposingAddress NOTIFY composingUserChanged)
|
|
||||||
Q_PROPERTY(bool isGroupChat READ isGroupChat CONSTANT)
|
|
||||||
Q_PROPERTY(bool isEncrypted READ isEncrypted CONSTANT)
|
|
||||||
Q_PROPERTY(bool isReadOnly READ getIsReadOnly WRITE setIsReadOnly NOTIFY readOnlyChanged)
|
|
||||||
Q_PROPERTY(bool isSecured READ isSecured WRITE setIsSecured NOTIFY isSecuredChanged)
|
|
||||||
Q_PROPERTY(bool isBasic MEMBER mIsBasic CONSTANT)
|
|
||||||
Q_PROPERTY(QString sendingText READ getSendingText WRITE setSendingText NOTIFY sendingTextChanged)
|
|
||||||
Q_PROPERTY(bool ephemeralEnabled READ isEphemeralEnabled WRITE lEnableEphemeral NOTIFY ephemeralEnabledChanged)
|
|
||||||
Q_PROPERTY(
|
|
||||||
int ephemeralLifetime READ getEphemeralLifetime WRITE lSetEphemeralLifetime NOTIFY ephemeralLifetimeChanged)
|
|
||||||
Q_PROPERTY(bool muted READ isMuted WRITE lSetMuted NOTIFY mutedChanged)
|
|
||||||
Q_PROPERTY(bool meAdmin READ getMeAdmin WRITE setMeAdmin NOTIFY meAdminChanged)
|
|
||||||
Q_PROPERTY(QVariantList participants READ getParticipantsGui NOTIFY participantsChanged)
|
|
||||||
Q_PROPERTY(QStringList participantsAddresses READ getParticipantsAddresses WRITE lSetParticipantsAddresses NOTIFY
|
|
||||||
participantsChanged)
|
|
||||||
Q_PROPERTY(QList<QSharedPointer<ChatMessageContentCore>> fileList READ getFileList NOTIFY fileListChanged)
|
|
||||||
|
|
||||||
// Should be call from model Thread. Will be automatically in App thread after initialization
|
|
||||||
static QSharedPointer<ChatCore> create(const std::shared_ptr<linphone::ChatRoom> &chatRoom);
|
|
||||||
ChatCore(const std::shared_ptr<linphone::ChatRoom> &chatRoom);
|
|
||||||
~ChatCore();
|
|
||||||
void setSelf(QSharedPointer<ChatCore> me);
|
|
||||||
|
|
||||||
QDateTime getLastUpdatedTime() const;
|
|
||||||
void setLastUpdatedTime(QDateTime time);
|
|
||||||
|
|
||||||
QString getTitle() const;
|
|
||||||
void setTitle(QString title);
|
|
||||||
|
|
||||||
bool isGroupChat() const;
|
|
||||||
|
|
||||||
bool isEncrypted() const;
|
|
||||||
|
|
||||||
bool isMuted() const;
|
|
||||||
|
|
||||||
bool isEphemeralEnabled() const;
|
|
||||||
int getEphemeralLifetime() const;
|
|
||||||
|
|
||||||
QString getIdentifier() const;
|
|
||||||
|
|
||||||
QString getSendingText() const;
|
|
||||||
void setSendingText(const QString &text);
|
|
||||||
|
|
||||||
ChatMessageGui *getLastMessage() const;
|
|
||||||
QString getLastMessageText() const;
|
|
||||||
|
|
||||||
QList<QSharedPointer<ChatMessageContentCore>> getFileList() const;
|
|
||||||
void resetFileList(QList<QSharedPointer<ChatMessageContentCore>> list);
|
|
||||||
|
|
||||||
LinphoneEnums::ChatMessageState getLastMessageState() const;
|
|
||||||
|
|
||||||
LinphoneEnums::ChatRoomState getChatRoomState() const;
|
|
||||||
void setChatRoomState(LinphoneEnums::ChatRoomState state);
|
|
||||||
|
|
||||||
bool getIsReadOnly() const;
|
|
||||||
void setIsReadOnly(bool readOnly);
|
|
||||||
|
|
||||||
QSharedPointer<ChatMessageCore> getLastMessageCore() const;
|
|
||||||
void setLastMessage(QSharedPointer<ChatMessageCore> lastMessage);
|
|
||||||
|
|
||||||
int getUnreadMessagesCount() const;
|
|
||||||
void setUnreadMessagesCount(int count);
|
|
||||||
|
|
||||||
QString getChatRoomAddress() const;
|
|
||||||
QString getParticipantAddress() const;
|
|
||||||
|
|
||||||
bool getMeAdmin() const;
|
|
||||||
void setMeAdmin(bool admin);
|
|
||||||
|
|
||||||
bool isSecured() const;
|
|
||||||
void setIsSecured(bool secured);
|
|
||||||
bool computeSecuredStatus() const;
|
|
||||||
|
|
||||||
// void resetEventLogList(QList<QSharedPointer<EventLogCore>> list);
|
|
||||||
// void appendEventLogToEventLogList(QSharedPointer<EventLogCore> event);
|
|
||||||
// void appendEventLogsToEventLogList(QList<QSharedPointer<EventLogCore>> list);
|
|
||||||
// void removeEventLogsFromEventLogList(QList<QSharedPointer<EventLogCore>> list);
|
|
||||||
// void clearEventLogList();
|
|
||||||
|
|
||||||
QString getAvatarUri() const;
|
|
||||||
void setAvatarUri(QString avatarUri);
|
|
||||||
|
|
||||||
QString getComposingName() const;
|
|
||||||
QString getComposingAddress() const;
|
|
||||||
void setComposingName(QString composingName);
|
|
||||||
void setComposingAddress(QString composingAddress);
|
|
||||||
|
|
||||||
std::shared_ptr<ChatModel> getModel() const;
|
|
||||||
|
|
||||||
void setParticipants(QList<QSharedPointer<ParticipantCore>> participants);
|
|
||||||
QList<QSharedPointer<ParticipantCore>> buildParticipants(const std::shared_ptr<linphone::ChatRoom> &chatRoom) const;
|
|
||||||
QList<QSharedPointer<ParticipantCore>> getParticipants() const;
|
|
||||||
QVariantList getParticipantsGui() const;
|
|
||||||
QStringList getParticipantsAddresses() const;
|
|
||||||
|
|
||||||
QString getLocalAddress() const;
|
|
||||||
|
|
||||||
void updateInfo(const std::shared_ptr<linphone::Friend> &updatedFriend, bool isRemoval = false);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
// used to close all the notifications when one is clicked
|
|
||||||
void messageOpen();
|
|
||||||
void lastUpdatedTimeChanged(QDateTime time);
|
|
||||||
void lastMessageChanged();
|
|
||||||
void titleChanged(QString title);
|
|
||||||
void unreadMessagesCountChanged(int count);
|
|
||||||
void eventListCleared();
|
|
||||||
void eventsInserted(QList<QSharedPointer<EventLogCore>> list);
|
|
||||||
void avatarUriChanged();
|
|
||||||
void deleted();
|
|
||||||
void composingUserChanged();
|
|
||||||
void chatRoomStateChanged();
|
|
||||||
void readOnlyChanged();
|
|
||||||
void sendingTextChanged(QString text);
|
|
||||||
void mutedChanged();
|
|
||||||
void ephemeralEnabledChanged();
|
|
||||||
void ephemeralLifetimeChanged();
|
|
||||||
void meAdminChanged();
|
|
||||||
void participantsChanged();
|
|
||||||
void fileListChanged();
|
|
||||||
void isSecuredChanged();
|
|
||||||
void conferenceJoined();
|
|
||||||
|
|
||||||
void lDeleteMessage(ChatMessageGui *message);
|
|
||||||
void lDelete();
|
|
||||||
void lDeleteHistory();
|
|
||||||
void lMarkAsRead();
|
|
||||||
void lUpdateLastMessage();
|
|
||||||
void lUpdateUnreadCount();
|
|
||||||
void lUpdateLastUpdatedTime();
|
|
||||||
void lSendTextMessage(QString message);
|
|
||||||
void lSendMessage(QString message, QVariantList files);
|
|
||||||
void lSendVoiceMessage();
|
|
||||||
void lCompose();
|
|
||||||
void lLeave();
|
|
||||||
void lSetMuted(bool muted);
|
|
||||||
void lEnableEphemeral(bool enable);
|
|
||||||
void lSetEphemeralLifetime(int time);
|
|
||||||
void lSetSubject(QString subject);
|
|
||||||
void lRemoveParticipantAtIndex(int index);
|
|
||||||
void lSetParticipantsAddresses(QStringList addresses);
|
|
||||||
void lToggleParticipantAdminStatusAtIndex(int index);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString id;
|
|
||||||
QDateTime mLastUpdatedTime;
|
|
||||||
QString mParticipantAddress;
|
|
||||||
QString mChatRoomAddress;
|
|
||||||
QString mTitle;
|
|
||||||
QString mIdentifier;
|
|
||||||
QString mAvatarUri;
|
|
||||||
QString mSendingText;
|
|
||||||
int mUnreadMessagesCount;
|
|
||||||
QString mComposingName;
|
|
||||||
QString mComposingAddress;
|
|
||||||
QString mLocalAddress;
|
|
||||||
bool mIsGroupChat = false;
|
|
||||||
bool mIsEncrypted = false;
|
|
||||||
bool mIsReadOnly = false;
|
|
||||||
bool mEphemeralEnabled = false;
|
|
||||||
// ChatRoom is secured if all its participants are
|
|
||||||
// EndToEndEncryptedAndVerified friends
|
|
||||||
bool mIsSecured = false;
|
|
||||||
bool mIsBasic = false;
|
|
||||||
int mEphemeralLifetime = 0;
|
|
||||||
QList<QSharedPointer<ChatMessageContentCore>> mFileList;
|
|
||||||
bool mIsMuted = false;
|
|
||||||
bool mMeAdmin = false;
|
|
||||||
bool mConferenceJoined = false;
|
|
||||||
QList<QSharedPointer<ParticipantCore>> mParticipants;
|
|
||||||
LinphoneEnums::ChatRoomState mChatRoomState;
|
|
||||||
std::shared_ptr<ChatModel> mChatModel;
|
|
||||||
QSharedPointer<ChatMessageCore> mLastMessage;
|
|
||||||
std::shared_ptr<FriendModel> mFriendModel;
|
|
||||||
QSharedPointer<SafeConnection<ChatCore, ChatModel>> mChatModelConnection;
|
|
||||||
QSharedPointer<SafeConnection<ChatCore, CoreModel>> mCoreModelConnection;
|
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
Q_DECLARE_METATYPE(ChatCore *)
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ChatGui.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ChatGui)
|
|
||||||
|
|
||||||
ChatGui::ChatGui(QSharedPointer<ChatCore> core) {
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
|
|
||||||
mCore = core;
|
|
||||||
if (isInLinphoneThread()) moveToThread(App::getInstance()->thread());
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatGui::~ChatGui() {
|
|
||||||
mustBeInMainThread("~" + getClassName());
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatCore *ChatGui::getCore() const {
|
|
||||||
return mCore.get();
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHAT_GUI_H_
|
|
||||||
#define CHAT_GUI_H_
|
|
||||||
|
|
||||||
#include "ChatCore.hpp"
|
|
||||||
#include <QObject>
|
|
||||||
#include <QSharedPointer>
|
|
||||||
|
|
||||||
class ChatGui : public QObject, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(ChatCore *core READ getCore CONSTANT)
|
|
||||||
|
|
||||||
public:
|
|
||||||
ChatGui(QSharedPointer<ChatCore> core);
|
|
||||||
~ChatGui();
|
|
||||||
ChatCore *getCore() const;
|
|
||||||
QSharedPointer<ChatCore> mCore;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,209 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ChatList.hpp"
|
|
||||||
#include "ChatCore.hpp"
|
|
||||||
#include "ChatGui.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "model/tool/ToolModel.hpp"
|
|
||||||
|
|
||||||
#include <QSharedPointer>
|
|
||||||
#include <linphone++/linphone.hh>
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ChatList)
|
|
||||||
|
|
||||||
QSharedPointer<ChatList> ChatList::create() {
|
|
||||||
auto model = QSharedPointer<ChatList>(new ChatList(), &QObject::deleteLater);
|
|
||||||
model->moveToThread(App::getInstance()->thread());
|
|
||||||
model->setSelf(model);
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedPointer<ChatCore> ChatList::createChatCore(const std::shared_ptr<linphone::ChatRoom> &chatroom) {
|
|
||||||
auto chatCore = ChatCore::create(chatroom);
|
|
||||||
return chatCore;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatList::ChatList(QObject *parent) : ListProxy(parent) {
|
|
||||||
mustBeInMainThread(getClassName());
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatList::~ChatList() {
|
|
||||||
mustBeInMainThread("~" + getClassName());
|
|
||||||
mModelConnection = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatList::connectItem(QSharedPointer<ChatCore> chat) {
|
|
||||||
connect(
|
|
||||||
chat.get(), &ChatCore::deleted, this,
|
|
||||||
[this, chat] {
|
|
||||||
disconnect(chat.get(), &ChatCore::unreadMessagesCountChanged, this, nullptr);
|
|
||||||
disconnect(chat.get(), &ChatCore::lastUpdatedTimeChanged, this, nullptr);
|
|
||||||
disconnect(chat.get(), &ChatCore::lastMessageChanged, this, nullptr);
|
|
||||||
remove(chat);
|
|
||||||
},
|
|
||||||
Qt::SingleShotConnection);
|
|
||||||
auto dataChange = [this, chat] {
|
|
||||||
int i = -1;
|
|
||||||
get(chat.get(), &i);
|
|
||||||
if (i != -1) {
|
|
||||||
auto modelIndex = index(i);
|
|
||||||
emit dataChanged(modelIndex, modelIndex);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
connect(chat.get(), &ChatCore::unreadMessagesCountChanged, this, [this, dataChange] {
|
|
||||||
dataChange();
|
|
||||||
auto defaultAccount = App::getInstance()->getAccountList()->getDefaultAccountCore();
|
|
||||||
if (defaultAccount) emit defaultAccount->lRefreshNotifications();
|
|
||||||
});
|
|
||||||
connect(chat.get(), &ChatCore::lastUpdatedTimeChanged, this, dataChange);
|
|
||||||
connect(chat.get(), &ChatCore::lastMessageChanged, this, dataChange);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatList::setSelf(QSharedPointer<ChatList> me) {
|
|
||||||
mModelConnection = SafeConnection<ChatList, CoreModel>::create(me, CoreModel::getInstance());
|
|
||||||
mModelConnection->makeConnectToCore(&ChatList::lUpdate, [this]() {
|
|
||||||
if (mIsUpdating) {
|
|
||||||
connect(this, &ChatList::isUpdatingChanged, this, [this] {
|
|
||||||
if (!mIsUpdating) {
|
|
||||||
disconnect(this, &ChatList::isUpdatingChanged, this, nullptr);
|
|
||||||
lUpdate();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setIsUpdating(true);
|
|
||||||
mModelConnection->invokeToModel([this]() {
|
|
||||||
mustBeInLinphoneThread(getClassName());
|
|
||||||
beginResetModel();
|
|
||||||
// Avoid copy to lambdas
|
|
||||||
QList<QSharedPointer<ChatCore>> *chats = new QList<QSharedPointer<ChatCore>>();
|
|
||||||
auto currentAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
|
|
||||||
if (!currentAccount) {
|
|
||||||
setIsUpdating(false);
|
|
||||||
endResetModel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto linphoneChatRooms = currentAccount->filterChatRooms(Utils::appStringToCoreString(mFilter));
|
|
||||||
for (auto it : linphoneChatRooms) {
|
|
||||||
auto model = createChatCore(it);
|
|
||||||
chats->push_back(model);
|
|
||||||
}
|
|
||||||
mModelConnection->invokeToCore([this, chats]() {
|
|
||||||
mustBeInMainThread(getClassName());
|
|
||||||
for (auto &chat : getSharedList<ChatCore>()) {
|
|
||||||
if (chat) {
|
|
||||||
disconnect(chat.get(), &ChatCore::deleted, this, nullptr);
|
|
||||||
disconnect(chat.get(), &ChatCore::unreadMessagesCountChanged, this, nullptr);
|
|
||||||
disconnect(chat.get(), &ChatCore::lastUpdatedTimeChanged, this, nullptr);
|
|
||||||
disconnect(chat.get(), &ChatCore::lastMessageChanged, this, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mList.clear();
|
|
||||||
for (auto &chat : *chats) {
|
|
||||||
connectItem(chat);
|
|
||||||
}
|
|
||||||
add(*chats);
|
|
||||||
endResetModel();
|
|
||||||
setIsUpdating(false);
|
|
||||||
delete chats;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
mModelConnection->makeConnectToModel(
|
|
||||||
&CoreModel::defaultAccountChanged,
|
|
||||||
[this](std::shared_ptr<linphone::Core> core, std::shared_ptr<linphone::Account> account) { lUpdate(); });
|
|
||||||
|
|
||||||
auto addChatToList = [this](const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
|
||||||
const std::shared_ptr<linphone::ChatMessage> &message) {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
if (!message) return;
|
|
||||||
if (room->getAccount() != core->getDefaultAccount()) {
|
|
||||||
qWarning() << log().arg("Chat room does not refer to current account, return");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto chatCore = ChatCore::create(room);
|
|
||||||
mModelConnection->invokeToCore([this, chatCore] { addChatInList(chatCore); });
|
|
||||||
};
|
|
||||||
mModelConnection->makeConnectToModel(&CoreModel::messageReceived,
|
|
||||||
[this, addChatToList](const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
|
||||||
const std::shared_ptr<linphone::ChatMessage> &message) {
|
|
||||||
addChatToList(core, room, message);
|
|
||||||
});
|
|
||||||
mModelConnection->makeConnectToModel(
|
|
||||||
&CoreModel::messagesReceived,
|
|
||||||
[this, addChatToList](const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
|
||||||
const std::list<std::shared_ptr<linphone::ChatMessage>> &messages) {
|
|
||||||
addChatToList(core, room, messages.front());
|
|
||||||
});
|
|
||||||
mModelConnection->makeConnectToModel(
|
|
||||||
&CoreModel::newMessageReaction,
|
|
||||||
[this, addChatToList](const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
|
||||||
const std::shared_ptr<linphone::ChatMessage> &message,
|
|
||||||
const std::shared_ptr<const linphone::ChatMessageReaction> &reaction) {
|
|
||||||
addChatToList(core, room, message);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(this, &ChatList::filterChanged, [this](QString filter) {
|
|
||||||
mFilter = filter;
|
|
||||||
lUpdate();
|
|
||||||
});
|
|
||||||
lUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
int ChatList::findChatIndex(ChatGui *chatGui) {
|
|
||||||
if (!chatGui) return -1;
|
|
||||||
auto core = chatGui->mCore;
|
|
||||||
auto chatList = getSharedList<ChatCore>();
|
|
||||||
auto it = std::find_if(chatList.begin(), chatList.end(), [core](const QSharedPointer<ChatCore> item) {
|
|
||||||
return item->getIdentifier() == core->getIdentifier();
|
|
||||||
});
|
|
||||||
return it == chatList.end() ? -1 : std::distance(chatList.begin(), it);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatList::addChatInList(QSharedPointer<ChatCore> chatCore) {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
auto chatList = getSharedList<ChatCore>();
|
|
||||||
auto it = std::find_if(chatList.begin(), chatList.end(), [chatCore](const QSharedPointer<ChatCore> item) {
|
|
||||||
return item && chatCore && item->getIdentifier() == chatCore->getIdentifier();
|
|
||||||
});
|
|
||||||
if (it == chatList.end()) {
|
|
||||||
connectItem(chatCore);
|
|
||||||
add(chatCore);
|
|
||||||
emit chatAdded();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant ChatList::data(const QModelIndex &index, int role) const {
|
|
||||||
int row = index.row();
|
|
||||||
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
|
||||||
if (role == Qt::DisplayRole) return QVariant::fromValue(new ChatGui(mList[row].objectCast<ChatCore>()));
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHAT_LIST_H_
|
|
||||||
#define CHAT_LIST_H_
|
|
||||||
|
|
||||||
#include "../proxy/ListProxy.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
|
||||||
#include <QLocale>
|
|
||||||
|
|
||||||
class ChatGui;
|
|
||||||
class ChatCore;
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class ChatList : public ListProxy, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
static QSharedPointer<ChatList> create();
|
|
||||||
// Create a ChatCore and make connections to List.
|
|
||||||
QSharedPointer<ChatCore> createChatCore(const std::shared_ptr<linphone::ChatRoom> &chatroom);
|
|
||||||
ChatList(QObject *parent = Q_NULLPTR);
|
|
||||||
~ChatList();
|
|
||||||
void setSelf(QSharedPointer<ChatList> me);
|
|
||||||
void connectItem(QSharedPointer<ChatCore> chat);
|
|
||||||
|
|
||||||
int findChatIndex(ChatGui *chat);
|
|
||||||
bool addChatInList(QSharedPointer<ChatCore> chatCore);
|
|
||||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void lUpdate();
|
|
||||||
void filterChanged(QString filter);
|
|
||||||
void chatAdded();
|
|
||||||
void chatUpdated();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString mFilter;
|
|
||||||
QSharedPointer<SafeConnection<ChatList, CoreModel>> mModelConnection;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ChatProxy.hpp"
|
|
||||||
#include "ChatGui.hpp"
|
|
||||||
#include "ChatList.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ChatProxy)
|
|
||||||
|
|
||||||
ChatProxy::ChatProxy(QObject *parent) {
|
|
||||||
mList = ChatList::create();
|
|
||||||
setSourceModel(mList.get());
|
|
||||||
setDynamicSortFilter(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatProxy::~ChatProxy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatProxy::setSourceModel(QAbstractItemModel *model) {
|
|
||||||
auto oldChatList = dynamic_cast<ChatList *>(sourceModel());
|
|
||||||
if (oldChatList) {
|
|
||||||
disconnect(this, &ChatProxy::filterTextChanged, oldChatList, nullptr);
|
|
||||||
disconnect(oldChatList, &ChatList::chatAdded, this, nullptr);
|
|
||||||
disconnect(oldChatList, &ChatList::dataChanged, this, nullptr);
|
|
||||||
}
|
|
||||||
auto newChatList = dynamic_cast<ChatList *>(model);
|
|
||||||
if (newChatList) {
|
|
||||||
connect(this, &ChatProxy::filterTextChanged, newChatList,
|
|
||||||
[this, newChatList] { emit newChatList->filterChanged(getFilterText()); });
|
|
||||||
connect(newChatList, &ChatList::chatAdded, this, [this] { invalidate(); });
|
|
||||||
connect(newChatList, &ChatList::dataChanged, this, [this] { invalidate(); });
|
|
||||||
}
|
|
||||||
QSortFilterProxyModel::setSourceModel(newChatList);
|
|
||||||
sort(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ChatProxy::findChatIndex(ChatGui *chatGui) {
|
|
||||||
auto chatList = dynamic_cast<ChatList *>(sourceModel());
|
|
||||||
if (chatList) {
|
|
||||||
auto listIndex = chatList->findChatIndex(chatGui);
|
|
||||||
if (listIndex != -1) {
|
|
||||||
listIndex = mapFromSource(chatList->index(listIndex, 0)).row();
|
|
||||||
return listIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatProxy::addChatInList(ChatGui *chatGui) {
|
|
||||||
auto chatList = dynamic_cast<ChatList *>(sourceModel());
|
|
||||||
if (chatList && chatGui) {
|
|
||||||
return chatList->addChatInList(chatGui->mCore);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatProxy::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const {
|
|
||||||
if (!mFilterText.isEmpty()) return false;
|
|
||||||
auto l = getItemAtSource<ChatList, ChatCore>(sourceLeft.row());
|
|
||||||
auto r = getItemAtSource<ChatList, ChatCore>(sourceRight.row());
|
|
||||||
if (l && r) return l->getLastUpdatedTime() > r->getLastUpdatedTime();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHAT_PROXY_H_
|
|
||||||
#define CHAT_PROXY_H_
|
|
||||||
|
|
||||||
#include "../proxy/SortFilterProxy.hpp"
|
|
||||||
#include "core/chat/ChatGui.hpp"
|
|
||||||
#include "core/chat/ChatList.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class ChatProxy : public SortFilterProxy, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
ChatProxy(QObject *parent = Q_NULLPTR);
|
|
||||||
~ChatProxy();
|
|
||||||
|
|
||||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
|
||||||
|
|
||||||
bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override;
|
|
||||||
|
|
||||||
Q_INVOKABLE int findChatIndex(ChatGui *chatGui);
|
|
||||||
Q_INVOKABLE bool addChatInList(ChatGui *chatGui);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QSharedPointer<ChatList> mList;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,127 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ChatMessageFileList.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "core/chat/message/content/ChatMessageContentCore.hpp"
|
|
||||||
|
|
||||||
#include <QSharedPointer>
|
|
||||||
|
|
||||||
#include <linphone++/linphone.hh>
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ChatMessageFileList)
|
|
||||||
|
|
||||||
QSharedPointer<ChatMessageFileList> ChatMessageFileList::create() {
|
|
||||||
auto model = QSharedPointer<ChatMessageFileList>(new ChatMessageFileList(), &QObject::deleteLater);
|
|
||||||
model->setSelf(model);
|
|
||||||
model->moveToThread(App::getInstance()->thread());
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageFileList::ChatMessageFileList(QObject *parent) : ListProxy(parent) {
|
|
||||||
mustBeInMainThread(getClassName());
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageFileList::~ChatMessageFileList() {
|
|
||||||
mustBeInMainThread("~" + getClassName());
|
|
||||||
mList.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageFileList::setSelf(QSharedPointer<ChatMessageFileList> me) {
|
|
||||||
mCoreModelConnection = SafeConnection<ChatMessageFileList, CoreModel>::create(me, CoreModel::getInstance());
|
|
||||||
mCoreModelConnection->makeConnectToCore(&ChatMessageFileList::lUpdate, [this]() {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
beginResetModel();
|
|
||||||
mList.clear();
|
|
||||||
if (!mChat) {
|
|
||||||
endResetModel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto chatModel = mChat->getModel();
|
|
||||||
if (!chatModel) {
|
|
||||||
endResetModel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mCoreModelConnection->invokeToModel([this, chatModel]() {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
std::list<std::shared_ptr<linphone::Content>> medias;
|
|
||||||
std::list<std::shared_ptr<linphone::Content>> docs;
|
|
||||||
QList<QSharedPointer<ChatMessageContentCore>> *contents =
|
|
||||||
new QList<QSharedPointer<ChatMessageContentCore>>();
|
|
||||||
if (mFilterType == (int)FilterContentType::Medias) {
|
|
||||||
medias = chatModel->getSharedMedias();
|
|
||||||
} else if (mFilterType == (int)FilterContentType::Documents) {
|
|
||||||
docs = chatModel->getSharedDocuments();
|
|
||||||
} else {
|
|
||||||
medias = chatModel->getSharedMedias();
|
|
||||||
docs = chatModel->getSharedDocuments();
|
|
||||||
}
|
|
||||||
for (auto it : medias) {
|
|
||||||
auto model = ChatMessageContentCore::create(it, nullptr);
|
|
||||||
contents->push_back(model);
|
|
||||||
}
|
|
||||||
for (auto it : docs) {
|
|
||||||
auto model = ChatMessageContentCore::create(it, nullptr);
|
|
||||||
contents->push_back(model);
|
|
||||||
}
|
|
||||||
mCoreModelConnection->invokeToCore([this, contents] {
|
|
||||||
for (auto i : *contents)
|
|
||||||
mList << i.template objectCast<QObject>();
|
|
||||||
endResetModel();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedPointer<ChatCore> ChatMessageFileList::getChatCore() const {
|
|
||||||
return mChat;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageFileList::setChatCore(QSharedPointer<ChatCore> chatCore) {
|
|
||||||
if (mChat != chatCore) {
|
|
||||||
// if (mChat) disconnect(mChat.get());
|
|
||||||
mChat = chatCore;
|
|
||||||
// if (mChat) connect(mChat.get(), &ChatCore::fileListChanged, this, lUpdate);
|
|
||||||
lUpdate();
|
|
||||||
emit chatChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int ChatMessageFileList::getFilterType() const {
|
|
||||||
return mFilterType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageFileList::setFilterType(int filterType) {
|
|
||||||
if (mFilterType != filterType) {
|
|
||||||
mFilterType = filterType;
|
|
||||||
lUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant ChatMessageFileList::data(const QModelIndex &index, int role) const {
|
|
||||||
int row = index.row();
|
|
||||||
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
|
||||||
if (role == Qt::DisplayRole)
|
|
||||||
return QVariant::fromValue(new ChatMessageContentGui(mList[row].objectCast<ChatMessageContentCore>()));
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHAT_MESSAGE_FILE_LIST_H_
|
|
||||||
#define CHAT_MESSAGE_FILE_LIST_H_
|
|
||||||
|
|
||||||
#include "core/chat/ChatCore.hpp"
|
|
||||||
#include "core/proxy/ListProxy.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
|
||||||
#include <QLocale>
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class ChatMessageFileList : public ListProxy, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
enum class FilterContentType { All = 0, Medias = 1, Documents = 2 };
|
|
||||||
static QSharedPointer<ChatMessageFileList> create();
|
|
||||||
ChatMessageFileList(QObject *parent = Q_NULLPTR);
|
|
||||||
~ChatMessageFileList();
|
|
||||||
|
|
||||||
void setSelf(QSharedPointer<ChatMessageFileList> me);
|
|
||||||
|
|
||||||
QSharedPointer<ChatCore> getChatCore() const;
|
|
||||||
void setChatCore(QSharedPointer<ChatCore> chatCore);
|
|
||||||
int getFilterType() const;
|
|
||||||
void setFilterType(int filterType);
|
|
||||||
|
|
||||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void chatChanged();
|
|
||||||
void lUpdate();
|
|
||||||
void filterTypeChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
int mFilterType;
|
|
||||||
QSharedPointer<ChatCore> mChat;
|
|
||||||
QSharedPointer<SafeConnection<ChatMessageFileList, CoreModel>> mCoreModelConnection;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ChatMessageFileProxy.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "core/chat/ChatGui.hpp"
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ChatMessageFileProxy)
|
|
||||||
|
|
||||||
ChatMessageFileProxy::ChatMessageFileProxy(QObject *parent) : LimitProxy(parent) {
|
|
||||||
mList = ChatMessageFileList::create();
|
|
||||||
connect(mList.get(), &ChatMessageFileList::chatChanged, this, &ChatMessageFileProxy::chatGuiChanged);
|
|
||||||
connect(this, &ChatMessageFileProxy::filterTypeChanged, this, [this] { invalidate(); });
|
|
||||||
setSourceModels(new SortFilterList(mList.get()));
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageFileProxy::~ChatMessageFileProxy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatGui *ChatMessageFileProxy::getChatGui() const {
|
|
||||||
return mList && mList->getChatCore() ? new ChatGui(mList->getChatCore()) : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageFileProxy::setChatGui(ChatGui *chat) const {
|
|
||||||
if (mList) mList->setChatCore(chat ? chat->mCore : nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageFileProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
|
||||||
if (getFilterType() == (int)FilterContentType::All) return true;
|
|
||||||
else {
|
|
||||||
auto contentCore = getItemAtSource<ChatMessageFileList, ChatMessageContentCore>(sourceRow);
|
|
||||||
if (!contentCore) return false;
|
|
||||||
bool isMedia = Utils::isVideo(contentCore->getFilePath()) || Utils::isImage(contentCore->getFilePath()) ||
|
|
||||||
Utils::isAnimatedImage(contentCore->getFilePath());
|
|
||||||
if (getFilterType() == (int)FilterContentType::Medias) {
|
|
||||||
return isMedia;
|
|
||||||
} else {
|
|
||||||
return !isMedia;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageFileProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft,
|
|
||||||
const QModelIndex &sourceRight) const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHAT_MESSAGE_FILE_PROXY_H_
|
|
||||||
#define CHAT_MESSAGE_FILE_PROXY_H_
|
|
||||||
|
|
||||||
#include "ChatMessageFileList.hpp"
|
|
||||||
#include "core/chat/message/ChatMessageCore.hpp"
|
|
||||||
#include "core/proxy/LimitProxy.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class ChatMessageFileProxy : public LimitProxy, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(ChatGui *chat READ getChatGui WRITE setChatGui NOTIFY chatGuiChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum class FilterContentType { All = 0, Medias = 1, Documents = 2 };
|
|
||||||
Q_ENUM(FilterContentType)
|
|
||||||
|
|
||||||
DECLARE_SORTFILTER_CLASS()
|
|
||||||
ChatMessageFileProxy(QObject *parent = Q_NULLPTR);
|
|
||||||
~ChatMessageFileProxy();
|
|
||||||
|
|
||||||
ChatGui *getChatGui() const;
|
|
||||||
void setChatGui(ChatGui *chat) const;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void chatGuiChanged();
|
|
||||||
void filterChanged();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QSharedPointer<ChatMessageFileList> mList;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,694 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ChatMessageCore.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "model/tool/ToolModel.hpp"
|
|
||||||
|
|
||||||
#include <QQuickWindow>
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ChatMessageCore)
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
|
|
||||||
ImdnStatus ImdnStatus::operator=(ImdnStatus r) {
|
|
||||||
mAddress = r.mAddress;
|
|
||||||
mState = r.mState;
|
|
||||||
mLastUpdatedTime = r.mLastUpdatedTime;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImdnStatus::operator==(const ImdnStatus &r) const {
|
|
||||||
return r.mState == mState && r.mAddress == mAddress && r.mLastUpdatedTime == mLastUpdatedTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImdnStatus::operator!=(ImdnStatus r) {
|
|
||||||
return r.mState != mState || r.mAddress != mAddress || r.mLastUpdatedTime != mLastUpdatedTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImdnStatus::ImdnStatus() {
|
|
||||||
}
|
|
||||||
|
|
||||||
ImdnStatus::ImdnStatus(const QString &address,
|
|
||||||
const LinphoneEnums::ChatMessageState &state,
|
|
||||||
QDateTime lastUpdatedTime) {
|
|
||||||
mState = state;
|
|
||||||
mAddress = address;
|
|
||||||
mLastUpdatedTime = lastUpdatedTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImdnStatus ImdnStatus::createMessageImdnStatusVariant(const QString &address,
|
|
||||||
const LinphoneEnums::ChatMessageState &state,
|
|
||||||
QDateTime lastUpdatedTime) {
|
|
||||||
ImdnStatus s;
|
|
||||||
s.mState = state;
|
|
||||||
s.mAddress = address;
|
|
||||||
s.mLastUpdatedTime = lastUpdatedTime;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant createImdnStatusSingletonVariant(const LinphoneEnums::ChatMessageState &state, int count = 1) {
|
|
||||||
QVariantMap map;
|
|
||||||
map.insert("state", QVariant::fromValue(state));
|
|
||||||
map.insert("count", count);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
|
|
||||||
Reaction Reaction::operator=(Reaction r) {
|
|
||||||
mAddress = r.mAddress;
|
|
||||||
mBody = r.mBody;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
bool Reaction::operator==(const Reaction &r) const {
|
|
||||||
return r.mBody == mBody && r.mAddress == mAddress;
|
|
||||||
}
|
|
||||||
bool Reaction::operator!=(Reaction r) {
|
|
||||||
return r.mBody != mBody || r.mAddress != mAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
Reaction Reaction::createMessageReactionVariant(const QString &body, const QString &address) {
|
|
||||||
Reaction r;
|
|
||||||
r.mBody = body;
|
|
||||||
r.mAddress = address;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant createReactionSingletonVariant(const QString &body, int count = 1) {
|
|
||||||
QVariantMap map;
|
|
||||||
map.insert("body", body);
|
|
||||||
map.insert("count", count);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
|
|
||||||
QSharedPointer<ChatMessageCore> ChatMessageCore::create(const std::shared_ptr<linphone::ChatMessage> &chatmessage) {
|
|
||||||
auto sharedPointer = QSharedPointer<ChatMessageCore>(new ChatMessageCore(chatmessage), &QObject::deleteLater);
|
|
||||||
sharedPointer->setSelf(sharedPointer);
|
|
||||||
sharedPointer->moveToThread(App::getInstance()->thread());
|
|
||||||
return sharedPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageCore::ChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &chatmessage) {
|
|
||||||
// lDebug() << "[ChatMessageCore] new" << this;
|
|
||||||
mustBeInLinphoneThread(getClassName());
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
|
||||||
if (chatmessage) {
|
|
||||||
mChatMessageModel = Utils::makeQObject_ptr<ChatMessageModel>(chatmessage);
|
|
||||||
mChatMessageModel->setSelf(mChatMessageModel);
|
|
||||||
mText = ToolModel::getMessageFromMessage(chatmessage);
|
|
||||||
mUtf8Text = mChatMessageModel->getUtf8Text();
|
|
||||||
mHasTextContent = mChatMessageModel->getHasTextContent();
|
|
||||||
mTimestamp = QDateTime::fromSecsSinceEpoch(chatmessage->getTime());
|
|
||||||
mIsOutgoing = chatmessage->isOutgoing();
|
|
||||||
mIsRetractable =
|
|
||||||
chatmessage->isOutgoing() && chatmessage->isRetractable() && !chatmessage->getChatRoom()->isReadOnly();
|
|
||||||
mIsRetracted = chatmessage->isRetracted();
|
|
||||||
mIsEditable =
|
|
||||||
chatmessage->isOutgoing() && chatmessage->isEditable() && !chatmessage->getChatRoom()->isReadOnly();
|
|
||||||
mIsEdited = chatmessage->isEdited();
|
|
||||||
mIsRemoteMessage = !chatmessage->isOutgoing();
|
|
||||||
mPeerAddress = Utils::coreStringToAppString(chatmessage->getPeerAddress()->asStringUriOnly());
|
|
||||||
mPeerName = ToolModel::getDisplayName(chatmessage->getPeerAddress());
|
|
||||||
auto fromAddress = chatmessage->getFromAddress();
|
|
||||||
// fromAddress->clean();
|
|
||||||
mFromAddress = Utils::coreStringToAppString(fromAddress->asStringUriOnly());
|
|
||||||
mFromName = ToolModel::getDisplayName(chatmessage->getFromAddress());
|
|
||||||
mToName = ToolModel::getDisplayName(chatmessage->getToAddress());
|
|
||||||
auto chatroom = chatmessage->getChatRoom();
|
|
||||||
mIsFromChatGroup = chatroom->hasCapability((int)linphone::ChatRoom::Capabilities::Conference) &&
|
|
||||||
!chatroom->hasCapability((int)linphone::ChatRoom::Capabilities::OneToOne);
|
|
||||||
mIsRead = chatmessage->isRead();
|
|
||||||
mMessageState = LinphoneEnums::fromLinphone(chatmessage->getState());
|
|
||||||
mIsEphemeral = chatmessage->isEphemeral();
|
|
||||||
|
|
||||||
if (mIsEphemeral) {
|
|
||||||
auto now = QDateTime::currentDateTime();
|
|
||||||
mEphemeralDuration = chatmessage->getEphemeralExpireTime() == 0
|
|
||||||
? chatmessage->getEphemeralLifetime()
|
|
||||||
: now.secsTo(QDateTime::fromSecsSinceEpoch(chatmessage->getEphemeralExpireTime()));
|
|
||||||
}
|
|
||||||
mMessageId = Utils::coreStringToAppString(chatmessage->getMessageId());
|
|
||||||
for (auto content : chatmessage->getContents()) {
|
|
||||||
auto contentCore = ChatMessageContentCore::create(content, mChatMessageModel);
|
|
||||||
mChatMessageContentList.push_back(contentCore);
|
|
||||||
if ((content->isFile() || content->isFileTransfer()) && !content->isVoiceRecording())
|
|
||||||
mHasFileContent = true;
|
|
||||||
if (content->isIcalendar()) mIsCalendarInvite = true;
|
|
||||||
if (content->isVoiceRecording()) {
|
|
||||||
mIsVoiceRecording = true;
|
|
||||||
mVoiceRecordingContent = contentCore;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//: "Reactions": all reactions for one message label
|
|
||||||
mTotalReactionsLabel = tr("all_reactions_label");
|
|
||||||
auto reac = chatmessage->getOwnReaction();
|
|
||||||
mOwnReaction = reac ? Utils::coreStringToAppString(reac->getBody()) : QString();
|
|
||||||
for (auto &reaction : chatmessage->getReactions()) {
|
|
||||||
if (reaction) {
|
|
||||||
auto fromAddr = reaction->getFromAddress()->clone();
|
|
||||||
fromAddr->clean();
|
|
||||||
auto reac =
|
|
||||||
Reaction::createMessageReactionVariant(Utils::coreStringToAppString(reaction->getBody()),
|
|
||||||
Utils::coreStringToAppString(fromAddr->asStringUriOnly()));
|
|
||||||
mReactions.append(reac);
|
|
||||||
|
|
||||||
auto it = std::find_if(mReactionsSingletonMap.begin(), mReactionsSingletonMap.end(),
|
|
||||||
[body = reac.mBody](QVariant data) {
|
|
||||||
auto dataBody = data.toMap()["body"].toString();
|
|
||||||
return body == dataBody;
|
|
||||||
});
|
|
||||||
if (it == mReactionsSingletonMap.end())
|
|
||||||
mReactionsSingletonMap.push_back(createReactionSingletonVariant(reac.mBody, 1));
|
|
||||||
else {
|
|
||||||
auto map = it->toMap();
|
|
||||||
auto count = map["count"].toInt();
|
|
||||||
++count;
|
|
||||||
map.remove("count");
|
|
||||||
map.insert("count", count);
|
|
||||||
mReactionsSingletonMap.erase(it);
|
|
||||||
mReactionsSingletonMap.push_back(map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
connect(this, &ChatMessageCore::messageReactionChanged, this, &ChatMessageCore::resetReactionsSingleton);
|
|
||||||
|
|
||||||
mIsForward = chatmessage->isForward();
|
|
||||||
mIsReply = chatmessage->isReply();
|
|
||||||
if (mIsReply) {
|
|
||||||
auto replymessage = chatmessage->getReplyMessage();
|
|
||||||
if (replymessage) {
|
|
||||||
mReplyText = ToolModel::getMessageFromMessage(replymessage);
|
|
||||||
if (mIsFromChatGroup) mRepliedToName = ToolModel::getDisplayName(replymessage->getFromAddress());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mImdnStatusList = computeDeliveryStatus(chatmessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageCore::~ChatMessageCore() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageCore::setSelf(QSharedPointer<ChatMessageCore> me) {
|
|
||||||
mChatMessageModelConnection = SafeConnection<ChatMessageCore, ChatMessageModel>::create(me, mChatMessageModel);
|
|
||||||
mChatMessageModelConnection->makeConnectToCore(&ChatMessageCore::lDelete, [this] {
|
|
||||||
mChatMessageModelConnection->invokeToModel([this] { mChatMessageModel->deleteMessageFromChatRoom(true); });
|
|
||||||
});
|
|
||||||
mChatMessageModelConnection->makeConnectToCore(&ChatMessageCore::lRetract, [this] {
|
|
||||||
mChatMessageModelConnection->invokeToModel([this] { mChatMessageModel->retractMessageFromChatRoom(); });
|
|
||||||
});
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(&ChatMessageModel::messageDeleted, [this](bool deletedByUser) {
|
|
||||||
mChatMessageModelConnection->invokeToCore([this, deletedByUser] {
|
|
||||||
//: Deleted
|
|
||||||
if (deletedByUser)
|
|
||||||
Utils::showInformationPopup(tr("info_toast_deleted_title"),
|
|
||||||
//: The message has been deleted
|
|
||||||
tr("info_toast_deleted_message"), true);
|
|
||||||
emit deleted();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatMessageModelConnection->makeConnectToCore(&ChatMessageCore::lMarkAsRead, [this] {
|
|
||||||
auto mainWindow = Utils::getMainWindow();
|
|
||||||
if (mainWindow->isActive())
|
|
||||||
mChatMessageModelConnection->invokeToModel([this] { mChatMessageModel->markAsRead(); });
|
|
||||||
else {
|
|
||||||
connect(mainWindow, &QQuickWindow::activeChanged, this, [this, mainWindow] {
|
|
||||||
if (mainWindow->isActive()) {
|
|
||||||
disconnect(mainWindow, &QQuickWindow::activeChanged, this, nullptr);
|
|
||||||
mChatMessageModelConnection->invokeToModel([this, mainWindow] { mChatMessageModel->markAsRead(); });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(&ChatMessageModel::messageRead, [this]() {
|
|
||||||
mChatMessageModelConnection->invokeToCore([this] { setIsRead(true); });
|
|
||||||
});
|
|
||||||
mChatMessageModelConnection->makeConnectToCore(&ChatMessageCore::lSendReaction, [this](const QString &reaction) {
|
|
||||||
mChatMessageModelConnection->invokeToModel([this, reaction] { mChatMessageModel->sendReaction(reaction); });
|
|
||||||
});
|
|
||||||
mChatMessageModelConnection->makeConnectToCore(&ChatMessageCore::lRemoveReaction, [this]() {
|
|
||||||
mChatMessageModelConnection->invokeToModel([this] { mChatMessageModel->removeReaction(); });
|
|
||||||
});
|
|
||||||
mChatMessageModelConnection->makeConnectToCore(&ChatMessageCore::lSend, [this]() {
|
|
||||||
mChatMessageModelConnection->invokeToModel([this] { mChatMessageModel->send(); });
|
|
||||||
});
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageModel::newMessageReaction,
|
|
||||||
[this](const std::shared_ptr<linphone::ChatMessage> &message,
|
|
||||||
const std::shared_ptr<const linphone::ChatMessageReaction> &reaction) {
|
|
||||||
auto ownReac = message->getOwnReaction();
|
|
||||||
auto own = ownReac ? Utils::coreStringToAppString(message->getOwnReaction()->getBody()) : QString();
|
|
||||||
// We must reset all the reactions each time cause reactionRemoved is not emitted
|
|
||||||
// when someone change its current reaction
|
|
||||||
QList<Reaction> reactions;
|
|
||||||
for (auto &reaction : message->getReactions()) {
|
|
||||||
if (reaction) {
|
|
||||||
auto fromAddr = reaction->getFromAddress()->clone();
|
|
||||||
fromAddr->clean();
|
|
||||||
reactions.append(Reaction::createMessageReactionVariant(
|
|
||||||
Utils::coreStringToAppString(reaction->getBody()),
|
|
||||||
Utils::coreStringToAppString(fromAddr->asStringUriOnly())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mChatMessageModelConnection->invokeToCore([this, own, reactions] {
|
|
||||||
setOwnReaction(own);
|
|
||||||
setReactions(reactions);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageModel::reactionRemoved, [this](const std::shared_ptr<linphone::ChatMessage> &message,
|
|
||||||
const std::shared_ptr<const linphone::Address> &address) {
|
|
||||||
auto reac = message->getOwnReaction();
|
|
||||||
auto own = reac ? Utils::coreStringToAppString(message->getOwnReaction()->getBody()) : QString();
|
|
||||||
auto addr = address->clone();
|
|
||||||
addr->clean();
|
|
||||||
QString addressString = Utils::coreStringToAppString(addr->asStringUriOnly());
|
|
||||||
mChatMessageModelConnection->invokeToCore([this, own, addressString] {
|
|
||||||
removeReaction(addressString);
|
|
||||||
setOwnReaction(own);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageModel::msgStateChanged,
|
|
||||||
[this](const std::shared_ptr<linphone::ChatMessage> &message, linphone::ChatMessage::State state) {
|
|
||||||
auto imdnStatusList = computeDeliveryStatus(message);
|
|
||||||
auto msgState = LinphoneEnums::fromLinphone(state);
|
|
||||||
mChatMessageModelConnection->invokeToCore([this, msgState, imdnStatusList] {
|
|
||||||
setImdnStatusList(imdnStatusList);
|
|
||||||
setMessageState(msgState);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageModel::fileTransferProgressIndication,
|
|
||||||
[this](const std::shared_ptr<linphone::ChatMessage> &message, const std::shared_ptr<linphone::Content> &content,
|
|
||||||
size_t offset, size_t total) {
|
|
||||||
mChatMessageModelConnection->invokeToCore([this, content, offset, total] {
|
|
||||||
auto it =
|
|
||||||
std::find_if(mChatMessageContentList.begin(), mChatMessageContentList.end(),
|
|
||||||
[content](QSharedPointer<ChatMessageContentCore> item) {
|
|
||||||
return item->getContentModel()->getContent()->getName() == content->getName();
|
|
||||||
});
|
|
||||||
if (it != mChatMessageContentList.end()) {
|
|
||||||
auto contentCore = mChatMessageContentList.at(std::distance(mChatMessageContentList.begin(), it));
|
|
||||||
assert(contentCore);
|
|
||||||
contentCore->setFileOffset(offset);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageModel::fileTransferTerminated, [this](const std::shared_ptr<linphone::ChatMessage> &message,
|
|
||||||
const std::shared_ptr<linphone::Content> &content) {
|
|
||||||
mChatMessageModelConnection->invokeToCore([this, content] {
|
|
||||||
auto it =
|
|
||||||
std::find_if(mChatMessageContentList.begin(), mChatMessageContentList.end(),
|
|
||||||
[content](QSharedPointer<ChatMessageContentCore> item) {
|
|
||||||
return item->getContentModel()->getContent()->getName() == content->getName();
|
|
||||||
});
|
|
||||||
if (it != mChatMessageContentList.end()) {
|
|
||||||
auto contentCore = mChatMessageContentList.at(std::distance(mChatMessageContentList.begin(), it));
|
|
||||||
assert(contentCore);
|
|
||||||
contentCore->setWasDownloaded(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageModel::fileTransferRecv,
|
|
||||||
[this](const std::shared_ptr<linphone::ChatMessage> &message, const std::shared_ptr<linphone::Content> &content,
|
|
||||||
const std::shared_ptr<const linphone::Buffer> &buffer) { lInfo() << log().arg("transfer received"); });
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageModel::fileTransferSend,
|
|
||||||
[this](const std::shared_ptr<linphone::ChatMessage> &message, const std::shared_ptr<linphone::Content> &content,
|
|
||||||
size_t offset, size_t size) { lInfo() << log().arg("transfer send"); });
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageModel::fileTransferSendChunk,
|
|
||||||
[this](const std::shared_ptr<linphone::ChatMessage> &message, const std::shared_ptr<linphone::Content> &content,
|
|
||||||
size_t offset, size_t size,
|
|
||||||
const std::shared_ptr<linphone::Buffer> &buffer) { lInfo() << log().arg("transfer send chunk"); });
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageModel::participantImdnStateChanged,
|
|
||||||
[this](const std::shared_ptr<linphone::ChatMessage> &message,
|
|
||||||
const std::shared_ptr<const linphone::ParticipantImdnState> &state) {
|
|
||||||
auto imdnStatusList = computeDeliveryStatus(message);
|
|
||||||
mChatMessageModelConnection->invokeToCore([this, imdnStatusList] { setImdnStatusList(imdnStatusList); });
|
|
||||||
});
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageModel::ephemeralMessageTimeUpdated,
|
|
||||||
[this](const std::shared_ptr<linphone::ChatMessage> &message, int expireTime) {
|
|
||||||
auto now = QDateTime::currentDateTime();
|
|
||||||
int duration = now.secsTo(QDateTime::fromSecsSinceEpoch(expireTime));
|
|
||||||
mChatMessageModelConnection->invokeToCore([this, duration] { setEphemeralDuration(duration); });
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(&ChatMessageModel::retracted,
|
|
||||||
[this](const std::shared_ptr<linphone::ChatMessage> &message) {
|
|
||||||
QString text = ToolModel::getMessageFromMessage(message);
|
|
||||||
mChatMessageModelConnection->invokeToCore([this, text] {
|
|
||||||
setText(text);
|
|
||||||
setRetracted();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatMessageModelConnection->makeConnectToModel(&ChatMessageModel::contentEdited,
|
|
||||||
[this](const std::shared_ptr<linphone::ChatMessage> &message) {
|
|
||||||
mChatMessageModelConnection->invokeToCore([this] {
|
|
||||||
mIsEdited = true;
|
|
||||||
emit edited();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<ImdnStatus> ChatMessageCore::computeDeliveryStatus(const std::shared_ptr<linphone::ChatMessage> &message) {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
QList<ImdnStatus> imdnStatusList;
|
|
||||||
auto createImdnStatus = [this](std::shared_ptr<linphone::ParticipantImdnState> participant,
|
|
||||||
linphone::ChatMessage::State state) -> ImdnStatus {
|
|
||||||
auto address = participant->getParticipant() ? participant->getParticipant()->getAddress()->clone() : nullptr;
|
|
||||||
auto lastUpdated = QDateTime::fromSecsSinceEpoch(participant->getStateChangeTime());
|
|
||||||
if (address) {
|
|
||||||
address->clean();
|
|
||||||
auto addrString = Utils::coreStringToAppString(address->asStringUriOnly());
|
|
||||||
auto imdn =
|
|
||||||
ImdnStatus::createMessageImdnStatusVariant(addrString, LinphoneEnums::fromLinphone(state), lastUpdated);
|
|
||||||
return imdn;
|
|
||||||
}
|
|
||||||
return ImdnStatus();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Read
|
|
||||||
for (auto &participant : message->getParticipantsByImdnState(linphone::ChatMessage::State::Displayed)) {
|
|
||||||
auto imdn = createImdnStatus(participant, linphone::ChatMessage::State::Displayed);
|
|
||||||
imdnStatusList.append(imdn);
|
|
||||||
}
|
|
||||||
// Received
|
|
||||||
for (auto &participant : message->getParticipantsByImdnState(linphone::ChatMessage::State::DeliveredToUser)) {
|
|
||||||
auto imdn = createImdnStatus(participant, linphone::ChatMessage::State::DeliveredToUser);
|
|
||||||
imdnStatusList.append(imdn);
|
|
||||||
}
|
|
||||||
// Sent
|
|
||||||
for (auto &participant : message->getParticipantsByImdnState(linphone::ChatMessage::State::Delivered)) {
|
|
||||||
auto imdn = createImdnStatus(participant, linphone::ChatMessage::State::Delivered);
|
|
||||||
imdnStatusList.append(imdn);
|
|
||||||
}
|
|
||||||
// Error
|
|
||||||
for (auto &participant : message->getParticipantsByImdnState(linphone::ChatMessage::State::NotDelivered)) {
|
|
||||||
auto imdn = createImdnStatus(participant, linphone::ChatMessage::State::NotDelivered);
|
|
||||||
imdnStatusList.append(imdn);
|
|
||||||
}
|
|
||||||
return imdnStatusList;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDateTime ChatMessageCore::getTimestamp() const {
|
|
||||||
return mTimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatMessageCore::getText() const {
|
|
||||||
return mText;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageCore::setText(QString text) {
|
|
||||||
if (mText != text) {
|
|
||||||
mText = text;
|
|
||||||
emit textChanged(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatMessageCore::getPeerAddress() const {
|
|
||||||
return mPeerAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatMessageCore::getPeerName() const {
|
|
||||||
return mPeerName;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatMessageCore::getFromAddress() const {
|
|
||||||
return mFromAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatMessageCore::getFromName() const {
|
|
||||||
return mFromName;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatMessageCore::getToAddress() const {
|
|
||||||
return mToAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatMessageCore::getToName() const {
|
|
||||||
return mToName;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatMessageCore::getMessageId() const {
|
|
||||||
return mMessageId;
|
|
||||||
}
|
|
||||||
bool ChatMessageCore::isRemoteMessage() const {
|
|
||||||
return mIsRemoteMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageCore::isFromChatGroup() const {
|
|
||||||
return mIsFromChatGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageCore::isEphemeral() const {
|
|
||||||
return mIsEphemeral;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ChatMessageCore::getEphemeralDuration() const {
|
|
||||||
return mEphemeralDuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageCore::setEphemeralDuration(int duration) {
|
|
||||||
if (mEphemeralDuration != duration) {
|
|
||||||
mEphemeralDuration = duration;
|
|
||||||
emit ephemeralDurationChanged(duration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageCore::hasFileContent() const {
|
|
||||||
return mHasFileContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageCore::isRead() const {
|
|
||||||
return mIsRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageCore::setIsRead(bool read) {
|
|
||||||
if (mIsRead != read) {
|
|
||||||
mIsRead = read;
|
|
||||||
emit isReadChanged(read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageCore::setRetracted() {
|
|
||||||
if (!mIsRetracted) {
|
|
||||||
mIsRetracted = true;
|
|
||||||
emit isRetractedChanged();
|
|
||||||
emit messageStateChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageCore::isRetracted() const {
|
|
||||||
return mIsRetracted;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageCore::isEdited() const {
|
|
||||||
return mIsEdited;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatMessageCore::getOwnReaction() const {
|
|
||||||
return mOwnReaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageCore::setOwnReaction(const QString &reaction) {
|
|
||||||
if (mOwnReaction != reaction) {
|
|
||||||
mOwnReaction = reaction;
|
|
||||||
emit messageReactionChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatMessageCore::getTotalReactionsLabel() const {
|
|
||||||
return mTotalReactionsLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<Reaction> ChatMessageCore::getReactions() const {
|
|
||||||
return mReactions;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QVariant> ChatMessageCore::getReactionsSingleton() const {
|
|
||||||
return mReactionsSingletonMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList ChatMessageCore::getReactionsSingletonAsStrings() const {
|
|
||||||
QStringList reacStringList;
|
|
||||||
int totalCount = 0;
|
|
||||||
for (auto &reac : mReactionsSingletonMap) {
|
|
||||||
auto map = reac.toMap();
|
|
||||||
auto count = map["count"].toInt();
|
|
||||||
totalCount += count;
|
|
||||||
reacStringList.append(QString("%1 %2").arg(map["body"].toString()).arg(count));
|
|
||||||
}
|
|
||||||
reacStringList.prepend(QString("%1 %2").arg(mTotalReactionsLabel).arg(totalCount));
|
|
||||||
return reacStringList;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QSharedPointer<ChatMessageContentCore>> ChatMessageCore::getChatMessageContentList() const {
|
|
||||||
return mChatMessageContentList;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageCore::setReactions(const QList<Reaction> &reactions) {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
mReactions = reactions;
|
|
||||||
emit messageReactionChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageCore::resetReactionsSingleton() {
|
|
||||||
mReactionsSingletonMap.clear();
|
|
||||||
for (auto &reac : mReactions) {
|
|
||||||
auto it = std::find_if(mReactionsSingletonMap.begin(), mReactionsSingletonMap.end(),
|
|
||||||
[body = reac.mBody](QVariant data) {
|
|
||||||
auto dataBody = data.toMap()["body"].toString();
|
|
||||||
return body == dataBody;
|
|
||||||
});
|
|
||||||
if (it == mReactionsSingletonMap.end())
|
|
||||||
mReactionsSingletonMap.push_back(createReactionSingletonVariant(reac.mBody, 1));
|
|
||||||
else {
|
|
||||||
auto map = it->toMap();
|
|
||||||
auto count = map["count"].toInt();
|
|
||||||
++count;
|
|
||||||
map.remove("count");
|
|
||||||
map.insert("count", count);
|
|
||||||
mReactionsSingletonMap.erase(it);
|
|
||||||
mReactionsSingletonMap.push_back(map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
emit singletonReactionMapChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageCore::removeReaction(const Reaction &reaction) {
|
|
||||||
int i = 0;
|
|
||||||
for (const auto &r : mReactions) {
|
|
||||||
if (reaction == r) {
|
|
||||||
mReactions.removeAt(i);
|
|
||||||
emit messageReactionChanged();
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageCore::removeOneReactionFromSingletonMap(const QString &body) {
|
|
||||||
auto it = std::find_if(mReactionsSingletonMap.begin(), mReactionsSingletonMap.end(), [body](QVariant data) {
|
|
||||||
auto dataBody = data.toMap()["body"].toString();
|
|
||||||
return body == dataBody;
|
|
||||||
});
|
|
||||||
if (it != mReactionsSingletonMap.end()) {
|
|
||||||
auto map = it->toMap();
|
|
||||||
auto count = map["count"].toInt();
|
|
||||||
if (count <= 1) mReactionsSingletonMap.erase(it);
|
|
||||||
else {
|
|
||||||
--count;
|
|
||||||
map.remove("count");
|
|
||||||
map.insert("count", count);
|
|
||||||
}
|
|
||||||
emit messageReactionChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageCore::removeReaction(const QString &address) {
|
|
||||||
int n = mReactions.removeIf([address, this](Reaction r) {
|
|
||||||
if (r.mAddress == address) {
|
|
||||||
removeOneReactionFromSingletonMap(r.mBody);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
if (n > 0) emit messageReactionChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
LinphoneEnums::ChatMessageState ChatMessageCore::getMessageState() const {
|
|
||||||
return mMessageState;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageCore::setMessageState(LinphoneEnums::ChatMessageState state) {
|
|
||||||
if (mMessageState != state) {
|
|
||||||
mMessageState = state;
|
|
||||||
emit messageStateChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<ImdnStatus> ChatMessageCore::getImdnStatusList() const {
|
|
||||||
return mImdnStatusList;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageCore::setImdnStatusList(QList<ImdnStatus> status) {
|
|
||||||
mImdnStatusList = status;
|
|
||||||
emit imdnStatusListChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList ChatMessageCore::getImdnStatusListLabels() const {
|
|
||||||
QStringList statusList;
|
|
||||||
int count = 0;
|
|
||||||
auto imdnSingletons = getImdnStatusAsSingletons();
|
|
||||||
for (auto &status : imdnSingletons) {
|
|
||||||
auto map = status.toMap();
|
|
||||||
auto val = map["state"].value<LinphoneEnums::ChatMessageState>();
|
|
||||||
auto count = map["count"].toInt();
|
|
||||||
statusList.append(QString("%1 %2").arg(LinphoneEnums::toString(val)).arg(count));
|
|
||||||
}
|
|
||||||
return statusList;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantList ChatMessageCore::getImdnStatusAsSingletons() const {
|
|
||||||
QVariantList statusSingletons;
|
|
||||||
statusSingletons.append(createImdnStatusSingletonVariant(LinphoneEnums::ChatMessageState::StateDisplayed, 0));
|
|
||||||
statusSingletons.append(createImdnStatusSingletonVariant(LinphoneEnums::ChatMessageState::StateDeliveredToUser, 0));
|
|
||||||
statusSingletons.append(createImdnStatusSingletonVariant(LinphoneEnums::ChatMessageState::StateDelivered, 0));
|
|
||||||
statusSingletons.append(createImdnStatusSingletonVariant(LinphoneEnums::ChatMessageState::StateNotDelivered, 0));
|
|
||||||
for (auto &stat : mImdnStatusList) {
|
|
||||||
auto it = std::find_if(statusSingletons.begin(), statusSingletons.end(), [state = stat.mState](QVariant data) {
|
|
||||||
auto dataState = data.toMap()["state"].value<LinphoneEnums::ChatMessageState>();
|
|
||||||
return state == dataState;
|
|
||||||
});
|
|
||||||
if (it == statusSingletons.end()) {
|
|
||||||
if (!stat.mAddress.isEmpty()) statusSingletons.append(createImdnStatusSingletonVariant(stat.mState, 1));
|
|
||||||
} else {
|
|
||||||
auto map = it->toMap();
|
|
||||||
auto count = map["count"].toInt();
|
|
||||||
++count;
|
|
||||||
map.remove("count");
|
|
||||||
map.insert("count", count);
|
|
||||||
int index = std::distance(statusSingletons.begin(), it);
|
|
||||||
statusSingletons.replace(index, map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return statusSingletons;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<ChatMessageModel> ChatMessageCore::getModel() const {
|
|
||||||
return mChatMessageModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConferenceInfoGui *ChatMessageCore::getConferenceInfoGui() const {
|
|
||||||
// return mConferenceInfo ? new ConferenceInfoGui(mConferenceInfo) : nullptr;
|
|
||||||
// }
|
|
||||||
|
|
||||||
ChatMessageContentGui *ChatMessageCore::getVoiceRecordingContent() const {
|
|
||||||
return new ChatMessageContentGui(mVoiceRecordingContent);
|
|
||||||
}
|
|
||||||
|
|
@ -1,246 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHAT_MESSAGE_CORE_H_
|
|
||||||
#define CHAT_MESSAGE_CORE_H_
|
|
||||||
|
|
||||||
#include "EventLogCore.hpp"
|
|
||||||
#include "core/chat/message/content/ChatMessageContentGui.hpp"
|
|
||||||
#include "core/chat/message/content/ChatMessageContentProxy.hpp"
|
|
||||||
#include "core/conference/ConferenceInfoCore.hpp"
|
|
||||||
#include "core/conference/ConferenceInfoGui.hpp"
|
|
||||||
#include "model/chat/message/ChatMessageModel.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QSharedPointer>
|
|
||||||
|
|
||||||
#include <linphone++/linphone.hh>
|
|
||||||
|
|
||||||
struct ImdnStatus {
|
|
||||||
Q_GADGET
|
|
||||||
|
|
||||||
Q_PROPERTY(QString address MEMBER mAddress)
|
|
||||||
Q_PROPERTY(LinphoneEnums::ChatMessageState state MEMBER mState)
|
|
||||||
Q_PROPERTY(QDateTime lastUpdatedTime MEMBER mLastUpdatedTime)
|
|
||||||
|
|
||||||
public:
|
|
||||||
QString mAddress;
|
|
||||||
LinphoneEnums::ChatMessageState mState;
|
|
||||||
QDateTime mLastUpdatedTime;
|
|
||||||
|
|
||||||
ImdnStatus(const QString &address, const LinphoneEnums::ChatMessageState &state, QDateTime mLastUpdatedTime);
|
|
||||||
ImdnStatus();
|
|
||||||
ImdnStatus operator=(ImdnStatus r);
|
|
||||||
bool operator==(const ImdnStatus &r) const;
|
|
||||||
bool operator!=(ImdnStatus r);
|
|
||||||
static ImdnStatus createMessageImdnStatusVariant(const QString &address,
|
|
||||||
const LinphoneEnums::ChatMessageState &state,
|
|
||||||
QDateTime mLastUpdatedTime);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Reaction {
|
|
||||||
Q_GADGET
|
|
||||||
|
|
||||||
Q_PROPERTY(QString body MEMBER mBody)
|
|
||||||
Q_PROPERTY(QString address MEMBER mAddress)
|
|
||||||
|
|
||||||
public:
|
|
||||||
QString mBody;
|
|
||||||
QString mAddress;
|
|
||||||
|
|
||||||
Reaction operator=(Reaction r);
|
|
||||||
bool operator==(const Reaction &r) const;
|
|
||||||
bool operator!=(Reaction r);
|
|
||||||
static Reaction createMessageReactionVariant(const QString &body, const QString &address);
|
|
||||||
};
|
|
||||||
|
|
||||||
class ChatCore;
|
|
||||||
class EventLogCore;
|
|
||||||
|
|
||||||
class ChatMessageCore : public QObject, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(QDateTime timestamp READ getTimestamp CONSTANT)
|
|
||||||
Q_PROPERTY(QString text READ getText WRITE setText NOTIFY textChanged)
|
|
||||||
Q_PROPERTY(QString utf8Text MEMBER mUtf8Text CONSTANT)
|
|
||||||
Q_PROPERTY(bool hasTextContent MEMBER mHasTextContent CONSTANT)
|
|
||||||
Q_PROPERTY(QString peerAddress READ getPeerAddress CONSTANT)
|
|
||||||
Q_PROPERTY(QString fromAddress READ getFromAddress CONSTANT)
|
|
||||||
Q_PROPERTY(QString toAddress READ getToAddress CONSTANT)
|
|
||||||
Q_PROPERTY(QString peerName READ getPeerName CONSTANT)
|
|
||||||
Q_PROPERTY(QString fromName READ getFromName CONSTANT)
|
|
||||||
Q_PROPERTY(QString totalReactionsLabel READ getTotalReactionsLabel CONSTANT)
|
|
||||||
Q_PROPERTY(LinphoneEnums::ChatMessageState messageState READ getMessageState WRITE setMessageState NOTIFY
|
|
||||||
messageStateChanged)
|
|
||||||
Q_PROPERTY(bool isRemoteMessage READ isRemoteMessage CONSTANT)
|
|
||||||
Q_PROPERTY(bool isFromChatGroup READ isFromChatGroup CONSTANT)
|
|
||||||
Q_PROPERTY(bool isEphemeral READ isEphemeral CONSTANT)
|
|
||||||
Q_PROPERTY(
|
|
||||||
int ephemeralDuration READ getEphemeralDuration WRITE setEphemeralDuration NOTIFY ephemeralDurationChanged)
|
|
||||||
Q_PROPERTY(bool isRead READ isRead WRITE setIsRead NOTIFY isReadChanged)
|
|
||||||
Q_PROPERTY(QString ownReaction READ getOwnReaction WRITE setOwnReaction NOTIFY messageReactionChanged)
|
|
||||||
Q_PROPERTY(QStringList imdnStatusListAsString READ getImdnStatusListLabels NOTIFY imdnStatusListChanged)
|
|
||||||
Q_PROPERTY(QList<ImdnStatus> imdnStatusList READ getImdnStatusList NOTIFY imdnStatusListChanged)
|
|
||||||
Q_PROPERTY(QVariantList imdnStatusAsSingletons READ getImdnStatusAsSingletons NOTIFY imdnStatusListChanged)
|
|
||||||
Q_PROPERTY(QList<Reaction> reactions READ getReactions WRITE setReactions NOTIFY messageReactionChanged)
|
|
||||||
Q_PROPERTY(QList<QVariant> reactionsSingleton READ getReactionsSingleton NOTIFY singletonReactionMapChanged)
|
|
||||||
Q_PROPERTY(
|
|
||||||
QStringList reactionsSingletonAsStrings READ getReactionsSingletonAsStrings NOTIFY singletonReactionMapChanged)
|
|
||||||
Q_PROPERTY(bool isForward MEMBER mIsForward CONSTANT)
|
|
||||||
Q_PROPERTY(bool isReply MEMBER mIsReply CONSTANT)
|
|
||||||
Q_PROPERTY(QString replyText MEMBER mReplyText CONSTANT)
|
|
||||||
Q_PROPERTY(QString repliedToName MEMBER mRepliedToName CONSTANT)
|
|
||||||
Q_PROPERTY(bool hasFileContent MEMBER mHasFileContent CONSTANT)
|
|
||||||
Q_PROPERTY(bool isVoiceRecording MEMBER mIsVoiceRecording CONSTANT)
|
|
||||||
Q_PROPERTY(bool isCalendarInvite MEMBER mIsCalendarInvite CONSTANT)
|
|
||||||
Q_PROPERTY(bool isOutgoing MEMBER mIsOutgoing CONSTANT)
|
|
||||||
Q_PROPERTY(bool isRetractable MEMBER mIsRetractable CONSTANT)
|
|
||||||
Q_PROPERTY(bool isRetracted READ isRetracted NOTIFY isRetractedChanged)
|
|
||||||
Q_PROPERTY(bool isEditable MEMBER mIsEditable CONSTANT)
|
|
||||||
Q_PROPERTY(bool isEdited READ isEdited NOTIFY edited)
|
|
||||||
|
|
||||||
public:
|
|
||||||
static QSharedPointer<ChatMessageCore> create(const std::shared_ptr<linphone::ChatMessage> &chatmessage);
|
|
||||||
ChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &chatmessage);
|
|
||||||
~ChatMessageCore();
|
|
||||||
void setSelf(QSharedPointer<ChatMessageCore> me);
|
|
||||||
|
|
||||||
QList<ImdnStatus> computeDeliveryStatus(const std::shared_ptr<linphone::ChatMessage> &message);
|
|
||||||
|
|
||||||
QString getText() const;
|
|
||||||
void setText(QString text);
|
|
||||||
|
|
||||||
QString getPeerAddress() const;
|
|
||||||
QString getPeerName() const;
|
|
||||||
QString getFromAddress() const;
|
|
||||||
QString getFromName() const;
|
|
||||||
QString getToAddress() const;
|
|
||||||
QString getToName() const;
|
|
||||||
QString getMessageId() const;
|
|
||||||
|
|
||||||
bool isRemoteMessage() const;
|
|
||||||
bool isFromChatGroup() const;
|
|
||||||
bool isEphemeral() const;
|
|
||||||
int getEphemeralDuration() const;
|
|
||||||
void setEphemeralDuration(int duration);
|
|
||||||
QDateTime getTimestamp() const;
|
|
||||||
|
|
||||||
bool hasFileContent() const;
|
|
||||||
|
|
||||||
bool isRead() const;
|
|
||||||
void setIsRead(bool read);
|
|
||||||
|
|
||||||
bool isRetracted() const;
|
|
||||||
void setRetracted();
|
|
||||||
bool isEdited() const;
|
|
||||||
|
|
||||||
QString getOwnReaction() const;
|
|
||||||
void setOwnReaction(const QString &reaction);
|
|
||||||
QString getTotalReactionsLabel() const;
|
|
||||||
QList<Reaction> getReactions() const;
|
|
||||||
QList<QVariant> getReactionsSingleton() const;
|
|
||||||
QStringList getReactionsSingletonAsStrings() const;
|
|
||||||
QList<QSharedPointer<ChatMessageContentCore>> getChatMessageContentList() const;
|
|
||||||
void removeOneReactionFromSingletonMap(const QString &body);
|
|
||||||
void resetReactionsSingleton();
|
|
||||||
void setReactions(const QList<Reaction> &reactions);
|
|
||||||
void removeReaction(const Reaction &reaction);
|
|
||||||
void removeReaction(const QString &address);
|
|
||||||
|
|
||||||
LinphoneEnums::ChatMessageState getMessageState() const;
|
|
||||||
void setMessageState(LinphoneEnums::ChatMessageState state);
|
|
||||||
QList<ImdnStatus> getImdnStatusList() const;
|
|
||||||
void setImdnStatusList(QList<ImdnStatus> status);
|
|
||||||
QVariantList getImdnStatusAsSingletons() const;
|
|
||||||
QStringList getImdnStatusListLabels() const;
|
|
||||||
|
|
||||||
std::shared_ptr<ChatMessageModel> getModel() const;
|
|
||||||
Q_INVOKABLE ChatMessageContentGui *getVoiceRecordingContent() const;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void textChanged(QString text);
|
|
||||||
void utf8TextChanged(QString text);
|
|
||||||
void isReadChanged(bool read);
|
|
||||||
void isRemoteMessageChanged(bool isRemote);
|
|
||||||
void messageStateChanged();
|
|
||||||
void imdnStatusListChanged();
|
|
||||||
void messageReactionChanged();
|
|
||||||
void singletonReactionMapChanged();
|
|
||||||
void ephemeralDurationChanged(int duration);
|
|
||||||
void isRetractedChanged();
|
|
||||||
void edited();
|
|
||||||
|
|
||||||
void lDelete();
|
|
||||||
void deleted();
|
|
||||||
void lRetract();
|
|
||||||
void lMarkAsRead();
|
|
||||||
void readChanged();
|
|
||||||
void lSendReaction(const QString &reaction);
|
|
||||||
void lRemoveReaction();
|
|
||||||
void lSend();
|
|
||||||
|
|
||||||
private:
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
QString mText;
|
|
||||||
QString mUtf8Text;
|
|
||||||
bool mHasTextContent;
|
|
||||||
QString mPeerAddress;
|
|
||||||
QString mFromAddress;
|
|
||||||
QString mToAddress;
|
|
||||||
QString mFromName;
|
|
||||||
QString mToName;
|
|
||||||
QString mPeerName;
|
|
||||||
QString mMessageId;
|
|
||||||
QString mOwnReaction;
|
|
||||||
QList<Reaction> mReactions;
|
|
||||||
QList<ImdnStatus> mImdnStatusList;
|
|
||||||
QList<QVariant> mReactionsSingletonMap;
|
|
||||||
QDateTime mTimestamp;
|
|
||||||
bool mIsRemoteMessage = false;
|
|
||||||
bool mIsFromChatGroup = false;
|
|
||||||
bool mIsRead = false;
|
|
||||||
bool mIsForward = false;
|
|
||||||
bool mIsReply = false;
|
|
||||||
QString mReplyText;
|
|
||||||
QString mRepliedToName;
|
|
||||||
bool mHasFileContent = false;
|
|
||||||
bool mIsCalendarInvite = false;
|
|
||||||
bool mIsVoiceRecording = false;
|
|
||||||
bool mIsEphemeral = false;
|
|
||||||
int mEphemeralDuration = 0;
|
|
||||||
bool mIsRetractable = false;
|
|
||||||
bool mIsRetracted = false;
|
|
||||||
bool mIsEditable = false;
|
|
||||||
bool mIsEdited = false;
|
|
||||||
|
|
||||||
bool mIsOutgoing = false;
|
|
||||||
QString mTotalReactionsLabel;
|
|
||||||
LinphoneEnums::ChatMessageState mMessageState;
|
|
||||||
QList<QSharedPointer<ChatMessageContentCore>> mChatMessageContentList;
|
|
||||||
// for voice recording creation message
|
|
||||||
QSharedPointer<ChatMessageContentCore> mVoiceRecordingContent;
|
|
||||||
// QSharedPointer<ConferenceInfoCore> mConferenceInfo = nullptr;
|
|
||||||
|
|
||||||
std::shared_ptr<ChatMessageModel> mChatMessageModel;
|
|
||||||
QSharedPointer<SafeConnection<ChatMessageCore, ChatMessageModel>> mChatMessageModelConnection;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CHAT_MESSAGE_CORE_H_
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ChatMessageGui.hpp"
|
|
||||||
#include "ChatMessageCore.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ChatMessageGui)
|
|
||||||
|
|
||||||
ChatMessageGui::ChatMessageGui(QSharedPointer<ChatMessageCore> core) {
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
|
|
||||||
mCore = core;
|
|
||||||
if (isInLinphoneThread()) moveToThread(App::getInstance()->thread());
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageGui::~ChatMessageGui() {
|
|
||||||
mustBeInMainThread("~" + getClassName());
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageCore *ChatMessageGui::getCore() const {
|
|
||||||
return mCore.get();
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHAT_MESSAGE_GUI_H_
|
|
||||||
#define CHAT_MESSAGE_GUI_H_
|
|
||||||
|
|
||||||
#include "ChatMessageCore.hpp"
|
|
||||||
#include <QObject>
|
|
||||||
#include <QSharedPointer>
|
|
||||||
|
|
||||||
class ChatMessageGui : public QObject, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(ChatMessageCore *core READ getCore CONSTANT)
|
|
||||||
|
|
||||||
public:
|
|
||||||
ChatMessageGui(QSharedPointer<ChatMessageCore> core);
|
|
||||||
~ChatMessageGui();
|
|
||||||
ChatMessageCore *getCore() const;
|
|
||||||
QSharedPointer<ChatMessageCore> mCore;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,173 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "EventLogCore.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "core/chat/ChatCore.hpp"
|
|
||||||
#include "model/chat/message/EventLogModel.hpp"
|
|
||||||
#include "model/tool/ToolModel.hpp"
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(EventLogCore)
|
|
||||||
|
|
||||||
QSharedPointer<EventLogCore> EventLogCore::create(const std::shared_ptr<const linphone::EventLog> &eventLog,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom) {
|
|
||||||
auto sharedPointer = QSharedPointer<EventLogCore>(new EventLogCore(eventLog, chatRoom), &QObject::deleteLater);
|
|
||||||
sharedPointer->setSelf(sharedPointer);
|
|
||||||
sharedPointer->moveToThread(App::getInstance()->thread());
|
|
||||||
return sharedPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventLogCore::EventLogCore(const std::shared_ptr<const linphone::EventLog> &eventLog,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom) {
|
|
||||||
mustBeInLinphoneThread(getClassName());
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
|
||||||
mEventLogType = LinphoneEnums::fromLinphone(eventLog->getType());
|
|
||||||
mEventLogModel = Utils::makeQObject_ptr<EventLogModel>(eventLog);
|
|
||||||
mTimestamp = QDateTime::fromMSecsSinceEpoch(eventLog->getCreationTime() * 1000);
|
|
||||||
auto chatmessage = eventLog->getChatMessage();
|
|
||||||
if (chatmessage) {
|
|
||||||
mChatMessageCore = ChatMessageCore::create(chatmessage);
|
|
||||||
mEventId = Utils::coreStringToAppString(chatmessage->getMessageId());
|
|
||||||
mTimestamp = QDateTime::fromSecsSinceEpoch(chatmessage->getTime());
|
|
||||||
} else if (eventLog->getCallLog()) {
|
|
||||||
mCallHistoryCore = CallHistoryCore::create(eventLog->getCallLog());
|
|
||||||
mEventId = Utils::coreStringToAppString(eventLog->getCallLog()->getCallId());
|
|
||||||
}
|
|
||||||
if (mEventId.isEmpty()) { // getNotifyId
|
|
||||||
QString type = QString::fromLatin1(
|
|
||||||
QMetaEnum::fromType<LinphoneEnums::EventLogType>().valueToKey(static_cast<int>(mEventLogType)));
|
|
||||||
mEventId = type + QString::number(static_cast<qint64>(eventLog->getCreationTime()));
|
|
||||||
computeEvent(eventLog, chatRoom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EventLogCore::~EventLogCore() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogCore::setSelf(QSharedPointer<EventLogCore> me) {
|
|
||||||
}
|
|
||||||
|
|
||||||
QString EventLogCore::getEventLogId() {
|
|
||||||
return mEventId;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedPointer<ChatMessageCore> EventLogCore::getChatMessageCore() {
|
|
||||||
return mChatMessageCore;
|
|
||||||
}
|
|
||||||
ChatMessageGui *EventLogCore::getChatMessageGui() {
|
|
||||||
return mChatMessageCore ? new ChatMessageGui(mChatMessageCore) : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedPointer<CallHistoryCore> EventLogCore::getCallHistoryCore() {
|
|
||||||
return mCallHistoryCore;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageCore *EventLogCore::getChatMessageCorePointer() {
|
|
||||||
return mChatMessageCore.get();
|
|
||||||
}
|
|
||||||
CallHistoryCore *EventLogCore::getCallHistoryCorePointer() {
|
|
||||||
return mCallHistoryCore.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
QDateTime EventLogCore::getTimestamp() const {
|
|
||||||
return mTimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<EventLogModel> EventLogCore::getModel() const {
|
|
||||||
return mEventLogModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Events (other than ChatMessage and CallLog which are handled in their respective Core)
|
|
||||||
|
|
||||||
void EventLogCore::computeEvent(const std::shared_ptr<const linphone::EventLog> &eventLog,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom) {
|
|
||||||
mustBeInLinphoneThread(getClassName());
|
|
||||||
mHandled = true;
|
|
||||||
mImportant = false;
|
|
||||||
mEphemeralRelated = false;
|
|
||||||
|
|
||||||
auto participantAddress = eventLog->getParticipantAddress() ? eventLog->getParticipantAddress() : nullptr;
|
|
||||||
|
|
||||||
switch (eventLog->getType()) {
|
|
||||||
case linphone::EventLog::Type::ConferenceCreated:
|
|
||||||
if (chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::OneToOne) &&
|
|
||||||
!chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::Conference))
|
|
||||||
mHandled = false;
|
|
||||||
mEventDetails = tr("conference_created_event");
|
|
||||||
break;
|
|
||||||
case linphone::EventLog::Type::ConferenceTerminated:
|
|
||||||
if (chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::OneToOne) &&
|
|
||||||
!chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::Conference))
|
|
||||||
mHandled = false;
|
|
||||||
mEventDetails = tr("conference_created_terminated");
|
|
||||||
mImportant = true;
|
|
||||||
break;
|
|
||||||
case linphone::EventLog::Type::ConferenceParticipantAdded:
|
|
||||||
mEventDetails = tr("conference_participant_added_event").arg(ToolModel::getDisplayName(participantAddress));
|
|
||||||
break;
|
|
||||||
case linphone::EventLog::Type::ConferenceParticipantRemoved:
|
|
||||||
mEventDetails =
|
|
||||||
tr("conference_participant_removed_event").arg(ToolModel::getDisplayName(participantAddress));
|
|
||||||
mImportant = true;
|
|
||||||
break;
|
|
||||||
case linphone::EventLog::Type::ConferenceSecurityEvent: {
|
|
||||||
if (eventLog->getSecurityEventType() == linphone::EventLog::SecurityEventType::SecurityLevelDowngraded) {
|
|
||||||
auto faultyParticipant = eventLog->getSecurityEventFaultyDeviceAddress()
|
|
||||||
? eventLog->getSecurityEventFaultyDeviceAddress()
|
|
||||||
: nullptr;
|
|
||||||
if (faultyParticipant)
|
|
||||||
mEventDetails = tr("conference_security_event").arg(ToolModel::getDisplayName(faultyParticipant));
|
|
||||||
else if (participantAddress)
|
|
||||||
mEventDetails = tr("conference_security_event").arg(ToolModel::getDisplayName(participantAddress));
|
|
||||||
mImportant = true;
|
|
||||||
} else mHandled = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case linphone::EventLog::Type::ConferenceEphemeralMessageEnabled:
|
|
||||||
mEphemeralRelated = true;
|
|
||||||
mEventDetails = tr("conference_ephemeral_message_enabled_event")
|
|
||||||
.arg(Utils::getEphemeralFormatedTime(eventLog->getEphemeralMessageLifetime()));
|
|
||||||
break;
|
|
||||||
case linphone::EventLog::Type::ConferenceEphemeralMessageLifetimeChanged:
|
|
||||||
mEphemeralRelated = true;
|
|
||||||
mHandled = eventLog->getEphemeralMessageLifetime() != 0; // Disabled is sent in case of 0.
|
|
||||||
mEventDetails = tr("conference_ephemeral_message_lifetime_changed_event")
|
|
||||||
.arg(Utils::getEphemeralFormatedTime(eventLog->getEphemeralMessageLifetime()));
|
|
||||||
break;
|
|
||||||
case linphone::EventLog::Type::ConferenceEphemeralMessageDisabled:
|
|
||||||
mEphemeralRelated = true;
|
|
||||||
mEventDetails = tr("conference_ephemeral_message_disabled_event");
|
|
||||||
mImportant = true;
|
|
||||||
break;
|
|
||||||
case linphone::EventLog::Type::ConferenceSubjectChanged:
|
|
||||||
mEventDetails = tr("conference_subject_changed_event").arg(QString::fromStdString(eventLog->getSubject()));
|
|
||||||
break;
|
|
||||||
case linphone::EventLog::Type::ConferenceParticipantSetAdmin:
|
|
||||||
mEventDetails =
|
|
||||||
tr("conference_participant_set_admin_event").arg(ToolModel::getDisplayName(participantAddress));
|
|
||||||
break;
|
|
||||||
case linphone::EventLog::Type::ConferenceParticipantUnsetAdmin:
|
|
||||||
mEventDetails =
|
|
||||||
tr("conference_participant_unset_admin_event").arg(ToolModel::getDisplayName(participantAddress));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
mHandled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EVENT_LOG_CORE_H_
|
|
||||||
#define EVENT_LOG_CORE_H_
|
|
||||||
|
|
||||||
#include "ChatMessageCore.hpp"
|
|
||||||
#include "core/call-history/CallHistoryCore.hpp"
|
|
||||||
#include "core/conference/ConferenceInfoCore.hpp"
|
|
||||||
#include "core/conference/ConferenceInfoGui.hpp"
|
|
||||||
#include "model/chat/message/ChatMessageModel.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
#include "tool/LinphoneEnums.hpp"
|
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
|
||||||
#include <QObject>
|
|
||||||
#include <QSharedPointer>
|
|
||||||
|
|
||||||
#include <linphone++/linphone.hh>
|
|
||||||
|
|
||||||
class ChatMessageCore;
|
|
||||||
class ChatMessageGui;
|
|
||||||
class EventLogModel;
|
|
||||||
|
|
||||||
class EventLogCore : public QObject, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(LinphoneEnums::EventLogType type MEMBER mEventLogType CONSTANT)
|
|
||||||
Q_PROPERTY(ChatMessageGui *chatMessageGui READ getChatMessageGui CONSTANT)
|
|
||||||
// Q_PROPERTY(NotifyCore *notification MEMBER mNotifyCore CONSTANT)
|
|
||||||
Q_PROPERTY(CallHistoryCore *callLog READ getCallHistoryCorePointer CONSTANT)
|
|
||||||
Q_PROPERTY(bool important MEMBER mImportant CONSTANT)
|
|
||||||
Q_PROPERTY(bool handled MEMBER mHandled CONSTANT)
|
|
||||||
Q_PROPERTY(QString eventDetails MEMBER mEventDetails CONSTANT)
|
|
||||||
Q_PROPERTY(QDateTime timestamp READ getTimestamp CONSTANT)
|
|
||||||
|
|
||||||
public:
|
|
||||||
static QSharedPointer<EventLogCore> create(const std::shared_ptr<const linphone::EventLog> &eventLog,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom);
|
|
||||||
EventLogCore(const std::shared_ptr<const linphone::EventLog> &eventLog,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom);
|
|
||||||
~EventLogCore();
|
|
||||||
void setSelf(QSharedPointer<EventLogCore> me);
|
|
||||||
QString getEventLogId();
|
|
||||||
QSharedPointer<ChatMessageCore> getChatMessageCore();
|
|
||||||
ChatMessageGui *getChatMessageGui();
|
|
||||||
QSharedPointer<CallHistoryCore> getCallHistoryCore();
|
|
||||||
|
|
||||||
QDateTime getTimestamp() const;
|
|
||||||
|
|
||||||
bool isHandled() const {
|
|
||||||
return mHandled;
|
|
||||||
}
|
|
||||||
bool isEphemeralRelated() const {
|
|
||||||
return mEphemeralRelated;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<EventLogModel> getModel() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
QString mEventId;
|
|
||||||
|
|
||||||
QSharedPointer<ChatMessageCore> mChatMessageCore = nullptr;
|
|
||||||
QSharedPointer<CallHistoryCore> mCallHistoryCore = nullptr;
|
|
||||||
LinphoneEnums::EventLogType mEventLogType;
|
|
||||||
bool mHandled = false;
|
|
||||||
bool mImportant;
|
|
||||||
bool mEphemeralRelated;
|
|
||||||
QString mEventDetails;
|
|
||||||
QDateTime mTimestamp;
|
|
||||||
|
|
||||||
ChatMessageCore *getChatMessageCorePointer();
|
|
||||||
CallHistoryCore *getCallHistoryCorePointer();
|
|
||||||
std::shared_ptr<EventLogModel> mEventLogModel;
|
|
||||||
void computeEvent(const std::shared_ptr<const linphone::EventLog> &eventLog,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EventLogCore_H_
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "EventLogGui.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(EventLogGui)
|
|
||||||
|
|
||||||
EventLogGui::EventLogGui(QSharedPointer<EventLogCore> core) {
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
|
|
||||||
mCore = core;
|
|
||||||
if (isInLinphoneThread()) moveToThread(App::getInstance()->thread());
|
|
||||||
}
|
|
||||||
|
|
||||||
EventLogGui::~EventLogGui() {
|
|
||||||
mustBeInMainThread("~" + getClassName());
|
|
||||||
}
|
|
||||||
|
|
||||||
EventLogCore *EventLogGui::getCore() const {
|
|
||||||
return mCore.get();
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EVENT_LOG_GUI_H_
|
|
||||||
#define EVENT_LOG_GUI_H_
|
|
||||||
|
|
||||||
#include "EventLogCore.hpp"
|
|
||||||
#include <QObject>
|
|
||||||
#include <QSharedPointer>
|
|
||||||
|
|
||||||
class EventLogGui : public QObject, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(EventLogCore *core READ getCore CONSTANT)
|
|
||||||
|
|
||||||
public:
|
|
||||||
EventLogGui(QSharedPointer<EventLogCore> core);
|
|
||||||
~EventLogGui();
|
|
||||||
EventLogCore *getCore() const;
|
|
||||||
QSharedPointer<EventLogCore> mCore;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,391 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "EventLogList.hpp"
|
|
||||||
#include "ChatMessageCore.hpp"
|
|
||||||
#include "ChatMessageGui.hpp"
|
|
||||||
#include "EventLogGui.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "core/call-history/CallHistoryGui.hpp"
|
|
||||||
#include "core/chat/ChatCore.hpp"
|
|
||||||
#include "core/chat/ChatGui.hpp"
|
|
||||||
#include "model/chat/message/EventLogModel.hpp"
|
|
||||||
#include <QSharedPointer>
|
|
||||||
#include <linphone++/linphone.hh>
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(EventLogList)
|
|
||||||
|
|
||||||
QSharedPointer<EventLogList> EventLogList::create() {
|
|
||||||
auto model = QSharedPointer<EventLogList>(new EventLogList(), &QObject::deleteLater);
|
|
||||||
model->moveToThread(App::getInstance()->thread());
|
|
||||||
model->setSelf(model);
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventLogList::EventLogList(QObject *parent) : ListProxy(parent) {
|
|
||||||
mustBeInMainThread(getClassName());
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
|
||||||
}
|
|
||||||
|
|
||||||
EventLogList::~EventLogList() {
|
|
||||||
mustBeInMainThread("~" + getClassName());
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatGui *EventLogList::getChat() const {
|
|
||||||
if (mChatCore) return new ChatGui(mChatCore);
|
|
||||||
else return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedPointer<ChatCore> EventLogList::getChatCore() const {
|
|
||||||
return mChatCore;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogList::disconnectItem(const QSharedPointer<EventLogCore> &item) {
|
|
||||||
auto message = item->getChatMessageCore();
|
|
||||||
if (message) {
|
|
||||||
disconnect(message.get(), &ChatMessageCore::isReadChanged, this, nullptr);
|
|
||||||
disconnect(message.get(), &ChatMessageCore::deleted, this, nullptr);
|
|
||||||
disconnect(message.get(), &ChatMessageCore::edited, this, nullptr);
|
|
||||||
disconnect(message.get(), &ChatMessageCore::isRetractedChanged, this, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogList::connectItem(const QSharedPointer<EventLogCore> &item) {
|
|
||||||
auto message = item->getChatMessageCore();
|
|
||||||
if (message) {
|
|
||||||
connect(message.get(), &ChatMessageCore::isReadChanged, this, [this] {
|
|
||||||
if (mChatCore) emit mChatCore->lUpdateUnreadCount();
|
|
||||||
});
|
|
||||||
connect(message.get(), &ChatMessageCore::deleted, this, [this, item] {
|
|
||||||
if (mChatCore) emit mChatCore->lUpdateLastMessage();
|
|
||||||
remove(item);
|
|
||||||
});
|
|
||||||
connect(message.get(), &ChatMessageCore::isRetractedChanged, this, [this, item] {
|
|
||||||
if (mChatCore) emit mChatCore->lUpdateUnreadCount();
|
|
||||||
});
|
|
||||||
connect(message.get(), &ChatMessageCore::edited, this, [this, item] {
|
|
||||||
auto eventLogModel = item->getModel();
|
|
||||||
mCoreModelConnection->invokeToModel([this, eventLogModel, item]() {
|
|
||||||
auto chatRoom = mChatCore->getModel()->getMonitor();
|
|
||||||
auto newEventLog = EventLogCore::create(eventLogModel->getEventLog(), chatRoom);
|
|
||||||
bool wasLastMessage =
|
|
||||||
mChatCore->getModel()->getLastChatMessage() == eventLogModel->getEventLog()->getChatMessage();
|
|
||||||
mCoreModelConnection->invokeToCore([this, newEventLog, wasLastMessage, item] {
|
|
||||||
connectItem(newEventLog);
|
|
||||||
replace(item, newEventLog);
|
|
||||||
if (wasLastMessage) mChatCore->setLastMessage(newEventLog->getChatMessageCore());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogList::setChatCore(QSharedPointer<ChatCore> core) {
|
|
||||||
if (mChatCore != core) {
|
|
||||||
if (mChatCore) {
|
|
||||||
disconnect(mChatCore.get(), &ChatCore::eventsInserted, this, nullptr);
|
|
||||||
disconnect(mChatCore.get(), &ChatCore::eventListCleared, this, nullptr);
|
|
||||||
}
|
|
||||||
mChatCore = core;
|
|
||||||
if (mChatCore) {
|
|
||||||
connect(mChatCore.get(), &ChatCore::eventListCleared, this, [this] { resetData(); });
|
|
||||||
connect(mChatCore.get(), &ChatCore::eventsInserted, this, [this](QList<QSharedPointer<EventLogCore>> list) {
|
|
||||||
auto eventsList = getSharedList<EventLogCore>();
|
|
||||||
for (auto &event : list) {
|
|
||||||
auto it = std::find_if(eventsList.begin(), eventsList.end(),
|
|
||||||
[event](const QSharedPointer<EventLogCore> item) { return item == event; });
|
|
||||||
if (it == eventsList.end()) {
|
|
||||||
connectItem(event);
|
|
||||||
prepend(event);
|
|
||||||
int index;
|
|
||||||
get(event.get(), &index);
|
|
||||||
if (event->getChatMessageCore() && !event->getChatMessageCore()->isRemoteMessage()) {
|
|
||||||
emit eventInsertedByUser(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
lUpdate();
|
|
||||||
// setIsUpdating(false);
|
|
||||||
emit chatGuiChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogList::setChatGui(ChatGui *chat) {
|
|
||||||
auto chatCore = chat ? chat->mCore : nullptr;
|
|
||||||
setChatCore(chatCore);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogList::setDisplayItemsStep(int displayItemsStep) {
|
|
||||||
if (mDisplayItemsStep != displayItemsStep) {
|
|
||||||
mDisplayItemsStep = displayItemsStep;
|
|
||||||
emit displayItemsStepChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogList::markIndexAsRead(int index) {
|
|
||||||
if (index < mList.count()) {
|
|
||||||
auto eventLog = mList[index].objectCast<EventLogCore>();
|
|
||||||
if (eventLog && eventLog->getChatMessageCore()) eventLog->getChatMessageCore()->lMarkAsRead();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogList::displayMore() {
|
|
||||||
auto loadMoreItems = [this] {
|
|
||||||
if (!mChatCore) return;
|
|
||||||
auto chatModel = mChatCore->getModel();
|
|
||||||
if (!chatModel) return;
|
|
||||||
mCoreModelConnection->invokeToModel([this, chatModel]() {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
int maxSize = chatModel->getHistorySizeEvents();
|
|
||||||
int totalItemsCount = mList.count();
|
|
||||||
auto newCount = std::min(totalItemsCount + mDisplayItemsStep, maxSize);
|
|
||||||
if (newCount <= totalItemsCount) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto linphoneLogs = chatModel->getHistoryRange(totalItemsCount, newCount);
|
|
||||||
QList<QSharedPointer<EventLogCore>> *events = new QList<QSharedPointer<EventLogCore>>();
|
|
||||||
for (auto it : linphoneLogs) {
|
|
||||||
auto model = EventLogCore::create(it, chatModel->getMonitor());
|
|
||||||
if (it->getChatMessage() || model->isHandled()) events->push_front(model);
|
|
||||||
}
|
|
||||||
mCoreModelConnection->invokeToCore([this, events] {
|
|
||||||
int currentCount = mList.count();
|
|
||||||
if (!events->isEmpty()) {
|
|
||||||
for (int i = events->size() - 1; i >= 0; --i) {
|
|
||||||
const auto &ev = events->at(i);
|
|
||||||
connectItem(ev);
|
|
||||||
}
|
|
||||||
add(*events);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
if (mIsUpdating) {
|
|
||||||
connect(this, &EventLogList::isUpdatingChanged, this, [this, loadMoreItems] {
|
|
||||||
if (!mIsUpdating) {
|
|
||||||
disconnect(this, &EventLogList::isUpdatingChanged, this, nullptr);
|
|
||||||
loadMoreItems();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
} else loadMoreItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogList::loadMessagesUpTo(std::shared_ptr<linphone::EventLog> event) {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
auto oldestEventLoaded = mList.count() > 0 ? getAt<EventLogCore>(mList.count() - 1) : nullptr;
|
|
||||||
auto linOldest = oldestEventLoaded
|
|
||||||
? std::const_pointer_cast<linphone::EventLog>(oldestEventLoaded->getModel()->getEventLog())
|
|
||||||
: nullptr;
|
|
||||||
auto chatModel = mChatCore->getModel();
|
|
||||||
assert(chatModel);
|
|
||||||
if (!chatModel) return;
|
|
||||||
int filters = static_cast<int>(linphone::ChatRoom::HistoryFilter::ChatMessage) |
|
|
||||||
static_cast<int>(linphone::ChatRoom::HistoryFilter::InfoNoDevice);
|
|
||||||
auto beforeEvents = chatModel->getHistoryRangeNear(mItemsToLoadBeforeSearchResult, 0, event, filters);
|
|
||||||
auto linphoneLogs = chatModel->getHistoryRangeBetween(event, linOldest, filters);
|
|
||||||
QList<QSharedPointer<EventLogCore>> *events = new QList<QSharedPointer<EventLogCore>>();
|
|
||||||
const auto &linChatRoom = chatModel->getMonitor();
|
|
||||||
for (const auto &it : beforeEvents) {
|
|
||||||
auto model = EventLogCore::create(it, linChatRoom);
|
|
||||||
if (it->getChatMessage() || model->isHandled()) events->push_front(model);
|
|
||||||
}
|
|
||||||
for (const auto &it : linphoneLogs) {
|
|
||||||
auto model = EventLogCore::create(it, linChatRoom);
|
|
||||||
if (it->getChatMessage() || model->isHandled()) events->push_front(model);
|
|
||||||
}
|
|
||||||
mCoreModelConnection->invokeToCore([this, events, event] {
|
|
||||||
for (const auto &e : *events) {
|
|
||||||
connectItem(e);
|
|
||||||
}
|
|
||||||
add(*events);
|
|
||||||
emit messagesLoadedUpTo(event);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
int EventLogList::findFirstUnreadIndex() {
|
|
||||||
auto eventList = getSharedList<EventLogCore>();
|
|
||||||
auto it = std::find_if(eventList.rbegin(), eventList.rend(), [](const QSharedPointer<EventLogCore> item) {
|
|
||||||
auto chatmessage = item->getChatMessageCore();
|
|
||||||
return chatmessage && !chatmessage->isRead();
|
|
||||||
});
|
|
||||||
return it == eventList.rend() ? -1 : std::distance(it, eventList.rend()) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogList::findChatMessageWithFilter(QString filter, int startIndex, bool forward, bool isFirstResearch) {
|
|
||||||
if (mChatCore) {
|
|
||||||
if (isFirstResearch) mLastFoundResult.reset();
|
|
||||||
auto chatModel = mChatCore->getModel();
|
|
||||||
auto startEvent =
|
|
||||||
startIndex >= 0 && startIndex < mList.count() ? mList[startIndex].objectCast<EventLogCore>() : nullptr;
|
|
||||||
lInfo() << log().arg("searching event starting from index") << startIndex << "| event :"
|
|
||||||
<< (startEvent && startEvent->getChatMessageCore() ? startEvent->getChatMessageCore()->getText()
|
|
||||||
: "null")
|
|
||||||
<< "| filter :" << filter;
|
|
||||||
auto startEventModel = startEvent ? startEvent->getModel() : nullptr;
|
|
||||||
mCoreModelConnection->invokeToModel([this, chatModel, startEventModel, filter, forward, isFirstResearch] {
|
|
||||||
auto linStartEvent = startEventModel ? startEventModel->getEventLog() : nullptr;
|
|
||||||
auto eventLog = chatModel->searchMessageByText(filter, linStartEvent, forward);
|
|
||||||
if (!eventLog) {
|
|
||||||
// event not found, search in the entire history
|
|
||||||
lInfo() << log().arg("not found, search in entire history");
|
|
||||||
auto eventLog = chatModel->searchMessageByText(filter, nullptr, forward);
|
|
||||||
}
|
|
||||||
int index = -1;
|
|
||||||
if (eventLog) {
|
|
||||||
lInfo() << log().arg("event with filter found") << eventLog.get();
|
|
||||||
auto eventList = getSharedList<EventLogCore>();
|
|
||||||
auto it = std::find_if(eventList.begin(), eventList.end(),
|
|
||||||
[eventLog](const QSharedPointer<EventLogCore> item) {
|
|
||||||
return item->getModel()->getEventLog() == eventLog;
|
|
||||||
});
|
|
||||||
if (it != eventList.end()) {
|
|
||||||
int index = std::distance(eventList.begin(), it);
|
|
||||||
if (mLastFoundResult && mLastFoundResult == *it) index = -1;
|
|
||||||
mLastFoundResult = *it;
|
|
||||||
mCoreModelConnection->invokeToCore([this, index] { emit messageWithFilterFound(index); });
|
|
||||||
} else {
|
|
||||||
connect(this, &EventLogList::messagesLoadedUpTo, this,
|
|
||||||
[this](std::shared_ptr<linphone::EventLog> event) {
|
|
||||||
auto eventList = getSharedList<EventLogCore>();
|
|
||||||
auto it = std::find_if(eventList.begin(), eventList.end(),
|
|
||||||
[event](const QSharedPointer<EventLogCore> item) {
|
|
||||||
return item->getModel()->getEventLog() == event;
|
|
||||||
});
|
|
||||||
int index = it != eventList.end() ? std::distance(eventList.begin(), it) : -1;
|
|
||||||
if (mLastFoundResult && mLastFoundResult == *it) index = -1;
|
|
||||||
mLastFoundResult = *it;
|
|
||||||
mCoreModelConnection->invokeToCore(
|
|
||||||
[this, index] { emit messageWithFilterFound(index); });
|
|
||||||
});
|
|
||||||
loadMessagesUpTo(eventLog);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lInfo() << log().arg("event not found at all in history");
|
|
||||||
mCoreModelConnection->invokeToCore([this, index] { emit messageWithFilterFound(index); });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogList::setSelf(QSharedPointer<EventLogList> me) {
|
|
||||||
mCoreModelConnection = SafeConnection<EventLogList, CoreModel>::create(me, CoreModel::getInstance());
|
|
||||||
|
|
||||||
mCoreModelConnection->makeConnectToCore(&EventLogList::lUpdate, [this]() {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
if (mIsUpdating) {
|
|
||||||
connect(this, &EventLogList::isUpdatingChanged, this, [this] {
|
|
||||||
if (!mIsUpdating) {
|
|
||||||
disconnect(this, &EventLogList::isUpdatingChanged, this, nullptr);
|
|
||||||
lUpdate();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setIsUpdating(true);
|
|
||||||
beginResetModel();
|
|
||||||
for (auto &event : getSharedList<EventLogCore>()) {
|
|
||||||
disconnectItem(event);
|
|
||||||
}
|
|
||||||
mList.clear();
|
|
||||||
if (!mChatCore) {
|
|
||||||
endResetModel();
|
|
||||||
setIsUpdating(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto chatModel = mChatCore->getModel();
|
|
||||||
if (!chatModel) {
|
|
||||||
endResetModel();
|
|
||||||
setIsUpdating(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mCoreModelConnection->invokeToModel([this, chatModel]() {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
auto linphoneLogs = chatModel->getHistoryRange(0, mDisplayItemsStep);
|
|
||||||
QList<QSharedPointer<EventLogCore>> *events = new QList<QSharedPointer<EventLogCore>>();
|
|
||||||
for (auto it : linphoneLogs) {
|
|
||||||
auto model = EventLogCore::create(it, chatModel->getMonitor());
|
|
||||||
if (it->getChatMessage() || model->isHandled()) events->push_front(model);
|
|
||||||
}
|
|
||||||
mCoreModelConnection->invokeToCore([this, events] {
|
|
||||||
for (auto &event : *events) {
|
|
||||||
connectItem(event);
|
|
||||||
mList.append(event);
|
|
||||||
}
|
|
||||||
endResetModel();
|
|
||||||
setIsUpdating(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(this, &EventLogList::filterChanged, [this](QString filter) {
|
|
||||||
mFilter = filter;
|
|
||||||
lUpdate();
|
|
||||||
});
|
|
||||||
lUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant EventLogList::data(const QModelIndex &index, int role) const {
|
|
||||||
int row = index.row();
|
|
||||||
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
|
||||||
|
|
||||||
auto core = mList[row].objectCast<EventLogCore>();
|
|
||||||
if (core->getChatMessageCore()) {
|
|
||||||
switch (role) {
|
|
||||||
case Qt::DisplayRole:
|
|
||||||
return QVariant::fromValue(new EventLogGui(core));
|
|
||||||
case Qt::DisplayRole + 1:
|
|
||||||
return "chatMessage";
|
|
||||||
}
|
|
||||||
} else if (core->getCallHistoryCore()) {
|
|
||||||
switch (role) {
|
|
||||||
case Qt::DisplayRole:
|
|
||||||
return QVariant::fromValue(new EventLogGui(core));
|
|
||||||
case Qt::DisplayRole + 1:
|
|
||||||
return "callLog";
|
|
||||||
}
|
|
||||||
} else if (core->isEphemeralRelated()) {
|
|
||||||
switch (role) {
|
|
||||||
case Qt::DisplayRole:
|
|
||||||
return QVariant::fromValue(new EventLogGui(core));
|
|
||||||
case Qt::DisplayRole + 1:
|
|
||||||
return "ephemeralEvent";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (role) {
|
|
||||||
case Qt::DisplayRole:
|
|
||||||
return QVariant::fromValue(new EventLogGui(core));
|
|
||||||
case Qt::DisplayRole + 1:
|
|
||||||
return "event";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<int, QByteArray> EventLogList::roleNames() const {
|
|
||||||
QHash<int, QByteArray> roles;
|
|
||||||
roles[Qt::DisplayRole] = "modelData";
|
|
||||||
roles[Qt::DisplayRole + 1] = "eventType";
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EVENT_LOG_LIST_H_
|
|
||||||
#define EVENT_LOG_LIST_H_
|
|
||||||
|
|
||||||
#include "core/proxy/ListProxy.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
|
||||||
#include <QLocale>
|
|
||||||
|
|
||||||
class EventLogGui;
|
|
||||||
class EventLogCore;
|
|
||||||
class ChatCore;
|
|
||||||
class ChatGui;
|
|
||||||
class ChatModel;
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class EventLogList : public ListProxy, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
static QSharedPointer<EventLogList> create();
|
|
||||||
EventLogList(QObject *parent = Q_NULLPTR);
|
|
||||||
~EventLogList();
|
|
||||||
|
|
||||||
QSharedPointer<ChatCore> getChatCore() const;
|
|
||||||
ChatGui *getChat() const;
|
|
||||||
void setChatCore(QSharedPointer<ChatCore> core);
|
|
||||||
void setChatGui(ChatGui *chat);
|
|
||||||
|
|
||||||
void connectItem(const QSharedPointer<EventLogCore> &item);
|
|
||||||
void disconnectItem(const QSharedPointer<EventLogCore> &item);
|
|
||||||
|
|
||||||
void loadMessagesUpTo(std::shared_ptr<linphone::EventLog> event);
|
|
||||||
|
|
||||||
void setLastFoundResult(const QSharedPointer<EventLogCore> &eventLog);
|
|
||||||
|
|
||||||
int findFirstUnreadIndex();
|
|
||||||
|
|
||||||
void markIndexAsRead(int index);
|
|
||||||
|
|
||||||
void displayMore();
|
|
||||||
void setDisplayItemsStep(int displayItemsStep);
|
|
||||||
|
|
||||||
void findChatMessageWithFilter(QString filter, int startIndex, bool forward = true, bool isFirstResearch = true);
|
|
||||||
|
|
||||||
void setSelf(QSharedPointer<EventLogList> me);
|
|
||||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void lUpdate();
|
|
||||||
void filterChanged(QString filter);
|
|
||||||
void eventInsertedByUser(int index);
|
|
||||||
void messageWithFilterFound(int index);
|
|
||||||
void listAboutToBeReset();
|
|
||||||
void chatGuiChanged();
|
|
||||||
void displayItemsStepChanged();
|
|
||||||
void messagesLoadedUpTo(std::shared_ptr<linphone::EventLog> event);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString mFilter;
|
|
||||||
QSharedPointer<ChatCore> mChatCore;
|
|
||||||
QSharedPointer<SafeConnection<EventLogList, CoreModel>> mCoreModelConnection;
|
|
||||||
int mDisplayItemsStep = 0;
|
|
||||||
int mItemsToLoadBeforeSearchResult = 3;
|
|
||||||
QSharedPointer<EventLogCore> mLastFoundResult;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,208 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "EventLogProxy.hpp"
|
|
||||||
#include "EventLogGui.hpp"
|
|
||||||
#include "EventLogList.hpp"
|
|
||||||
// #include "core/chat/ChatGui.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(EventLogProxy)
|
|
||||||
|
|
||||||
EventLogProxy::EventLogProxy(QObject *parent) : QSortFilterProxyModel(parent) {
|
|
||||||
mList = EventLogList::create();
|
|
||||||
setSourceModel(mList.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
EventLogProxy::~EventLogProxy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogProxy::setSourceModel(QAbstractItemModel *model) {
|
|
||||||
auto oldEventLogList = dynamic_cast<EventLogList *>(sourceModel());
|
|
||||||
if (oldEventLogList) {
|
|
||||||
disconnect(oldEventLogList, &EventLogList::displayItemsStepChanged, this, nullptr);
|
|
||||||
disconnect(oldEventLogList, &EventLogList::messageWithFilterFound, this, nullptr);
|
|
||||||
disconnect(oldEventLogList, &EventLogList::eventInsertedByUser, this, nullptr);
|
|
||||||
}
|
|
||||||
auto newEventLogList = dynamic_cast<EventLogList *>(model);
|
|
||||||
if (newEventLogList) {
|
|
||||||
connect(this, &EventLogProxy::displayItemsStepChanged, newEventLogList,
|
|
||||||
[this, newEventLogList] { newEventLogList->setDisplayItemsStep(mDisplayItemsStep); });
|
|
||||||
connect(newEventLogList, &EventLogList::messageWithFilterFound, this, [this, newEventLogList](int i) {
|
|
||||||
auto model = dynamic_cast<EventLogList *>(sourceModel());
|
|
||||||
int proxyIndex = mapFromSource(newEventLogList->index(i, 0)).row();
|
|
||||||
if (i != -1) {
|
|
||||||
loadUntil(proxyIndex);
|
|
||||||
}
|
|
||||||
emit indexWithFilterFound(proxyIndex);
|
|
||||||
});
|
|
||||||
connect(newEventLogList, &EventLogList::eventInsertedByUser, this, [this, newEventLogList](int i) {
|
|
||||||
int proxyIndex = mapFromSource(newEventLogList->index(i, 0)).row();
|
|
||||||
emit eventInsertedByUser(proxyIndex);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
QSortFilterProxyModel::setSourceModel(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatGui *EventLogProxy::getChatGui() {
|
|
||||||
auto model = dynamic_cast<EventLogList *>(sourceModel());
|
|
||||||
if (!mChatGui && model) mChatGui = model->getChat();
|
|
||||||
return mChatGui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogProxy::setChatGui(ChatGui *chat) {
|
|
||||||
auto model = dynamic_cast<EventLogList *>(sourceModel());
|
|
||||||
if (model) model->setChatGui(chat);
|
|
||||||
}
|
|
||||||
|
|
||||||
EventLogGui *EventLogProxy::getEventAtIndex(int i) {
|
|
||||||
auto eventCore = getEventCoreAtIndex(i);
|
|
||||||
return eventCore == nullptr ? nullptr : new EventLogGui(eventCore);
|
|
||||||
}
|
|
||||||
|
|
||||||
int EventLogProxy::getCount() const {
|
|
||||||
return rowCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
int EventLogProxy::getInitialDisplayItems() const {
|
|
||||||
return mInitialDisplayItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogProxy::setInitialDisplayItems(int initialItems) {
|
|
||||||
if (mInitialDisplayItems != initialItems) {
|
|
||||||
mInitialDisplayItems = initialItems;
|
|
||||||
if (getMaxDisplayItems() <= mInitialDisplayItems) setMaxDisplayItems(initialItems);
|
|
||||||
if (getDisplayItemsStep() <= 0) setDisplayItemsStep(initialItems);
|
|
||||||
emit initialDisplayItemsChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int EventLogProxy::getDisplayCount(int listCount, int maxCount) {
|
|
||||||
return maxCount >= 0 ? qMin(listCount, maxCount) : listCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EventLogProxy::getDisplayCount(int listCount) const {
|
|
||||||
return getDisplayCount(listCount, mMaxDisplayItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedPointer<EventLogCore> EventLogProxy::getEventCoreAtIndex(int i) {
|
|
||||||
auto model = dynamic_cast<EventLogList *>(sourceModel());
|
|
||||||
if (model) {
|
|
||||||
return model->getAt<EventLogCore>(mapToSource(index(i, 0)).row());
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogProxy::displayMore() {
|
|
||||||
auto model = dynamic_cast<EventLogList *>(sourceModel());
|
|
||||||
if (model) {
|
|
||||||
model->displayMore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int EventLogProxy::getMaxDisplayItems() const {
|
|
||||||
return mMaxDisplayItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogProxy::setMaxDisplayItems(int maxItems) {
|
|
||||||
if (mMaxDisplayItems != maxItems) {
|
|
||||||
auto model = sourceModel();
|
|
||||||
int modelCount = model ? model->rowCount() : 0;
|
|
||||||
int oldCount = getDisplayCount(modelCount);
|
|
||||||
mMaxDisplayItems = maxItems;
|
|
||||||
if (getInitialDisplayItems() > mMaxDisplayItems) setInitialDisplayItems(maxItems);
|
|
||||||
if (getDisplayItemsStep() <= 0) setDisplayItemsStep(maxItems);
|
|
||||||
emit maxDisplayItemsChanged();
|
|
||||||
|
|
||||||
if (model && getDisplayCount(modelCount) != oldCount) {
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int EventLogProxy::getDisplayItemsStep() const {
|
|
||||||
return mDisplayItemsStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogProxy::setDisplayItemsStep(int step) {
|
|
||||||
if (step > 0 && mDisplayItemsStep != step) {
|
|
||||||
mDisplayItemsStep = step;
|
|
||||||
emit displayItemsStepChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogProxy::loadUntil(int index) {
|
|
||||||
if (mMaxDisplayItems < index) setMaxDisplayItems(index + mDisplayItemsStep);
|
|
||||||
}
|
|
||||||
|
|
||||||
int EventLogProxy::findFirstUnreadIndex() {
|
|
||||||
auto eventLogList = dynamic_cast<EventLogList *>(sourceModel());
|
|
||||||
if (eventLogList) {
|
|
||||||
auto listIndex = eventLogList->findFirstUnreadIndex();
|
|
||||||
if (listIndex != -1) {
|
|
||||||
listIndex = mapFromSource(eventLogList->index(listIndex, 0)).row();
|
|
||||||
if (mMaxDisplayItems <= listIndex) setMaxDisplayItems(listIndex + mDisplayItemsStep);
|
|
||||||
return listIndex;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString EventLogProxy::getFilterText() const {
|
|
||||||
return mFilterText;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogProxy::setFilterText(const QString &filter) {
|
|
||||||
if (mFilterText != filter) {
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
|
|
||||||
beginFilterChange();
|
|
||||||
mFilterText = filter;
|
|
||||||
endFilterChange();
|
|
||||||
#else
|
|
||||||
mFilterText = filter;
|
|
||||||
invalidateFilter();
|
|
||||||
#endif
|
|
||||||
emit filterTextChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedPointer<EventLogCore> EventLogProxy::getAt(int atIndex) const {
|
|
||||||
auto model = dynamic_cast<EventLogList *>(sourceModel());
|
|
||||||
if (model) {
|
|
||||||
return model->getAt<EventLogCore>(mapToSource(index(atIndex, 0)).row());
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogProxy::markIndexAsRead(int proxyIndex) {
|
|
||||||
auto event = getAt(proxyIndex);
|
|
||||||
if (event && event->getChatMessageCore()) event->getChatMessageCore()->lMarkAsRead();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLogProxy::findIndexCorrespondingToFilter(int startIndex, bool forward, bool isFirstResearch) {
|
|
||||||
auto filter = getFilterText();
|
|
||||||
if (filter.isEmpty()) return;
|
|
||||||
auto eventLogList = dynamic_cast<EventLogList *>(sourceModel());
|
|
||||||
if (eventLogList) {
|
|
||||||
auto listIndex = mapToSource(index(startIndex, 0)).row();
|
|
||||||
eventLogList->findChatMessageWithFilter(filter, listIndex, forward, isFirstResearch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EVENT_LIST_PROXY_H_
|
|
||||||
#define EVENT_LIST_PROXY_H_
|
|
||||||
|
|
||||||
#include "EventLogList.hpp"
|
|
||||||
// #include "core/proxy/LimitProxy.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
#include <QSortFilterProxyModel>
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class ChatGui;
|
|
||||||
|
|
||||||
class EventLogProxy : public QSortFilterProxyModel, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(int count READ getCount NOTIFY countChanged)
|
|
||||||
Q_PROPERTY(ChatGui *chatGui READ getChatGui WRITE setChatGui NOTIFY chatGuiChanged)
|
|
||||||
Q_PROPERTY(int initialDisplayItems READ getInitialDisplayItems WRITE setInitialDisplayItems NOTIFY
|
|
||||||
initialDisplayItemsChanged)
|
|
||||||
Q_PROPERTY(int maxDisplayItems READ getMaxDisplayItems WRITE setMaxDisplayItems NOTIFY maxDisplayItemsChanged)
|
|
||||||
Q_PROPERTY(int displayItemsStep READ getDisplayItemsStep WRITE setDisplayItemsStep NOTIFY displayItemsStepChanged)
|
|
||||||
Q_PROPERTY(QString filterText READ getFilterText WRITE setFilterText NOTIFY filterTextChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
// DECLARE_SORTFILTER_CLASS()
|
|
||||||
|
|
||||||
EventLogProxy(QObject *parent = Q_NULLPTR);
|
|
||||||
~EventLogProxy();
|
|
||||||
|
|
||||||
ChatGui *getChatGui();
|
|
||||||
void setChatGui(ChatGui *chat);
|
|
||||||
|
|
||||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
|
||||||
virtual int getCount() const;
|
|
||||||
static int getDisplayCount(int listCount, int maxCount);
|
|
||||||
int getDisplayCount(int listCount) const;
|
|
||||||
int getInitialDisplayItems() const;
|
|
||||||
void setInitialDisplayItems(int initialItems);
|
|
||||||
|
|
||||||
int getMaxDisplayItems() const;
|
|
||||||
void setMaxDisplayItems(int maxItems);
|
|
||||||
|
|
||||||
int getDisplayItemsStep() const;
|
|
||||||
void setDisplayItemsStep(int step);
|
|
||||||
|
|
||||||
QString getFilterText() const;
|
|
||||||
void setFilterText(const QString &filter);
|
|
||||||
|
|
||||||
// bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
|
||||||
// bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override;
|
|
||||||
|
|
||||||
QSharedPointer<EventLogCore> getAt(int atIndex) const;
|
|
||||||
|
|
||||||
Q_INVOKABLE void displayMore();
|
|
||||||
Q_INVOKABLE void loadUntil(int index);
|
|
||||||
Q_INVOKABLE EventLogGui *getEventAtIndex(int i);
|
|
||||||
QSharedPointer<EventLogCore> getEventCoreAtIndex(int i);
|
|
||||||
Q_INVOKABLE int findFirstUnreadIndex();
|
|
||||||
Q_INVOKABLE void markIndexAsRead(int proxyIndex);
|
|
||||||
Q_INVOKABLE void findIndexCorrespondingToFilter(int startIndex, bool forward = true, bool isFirstResearch = true);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void eventInsertedByUser(int index);
|
|
||||||
void indexWithFilterFound(int index);
|
|
||||||
void chatGuiChanged();
|
|
||||||
void countChanged();
|
|
||||||
void initialDisplayItemsChanged();
|
|
||||||
void maxDisplayItemsChanged();
|
|
||||||
void displayItemsStepChanged();
|
|
||||||
void filterTextChanged();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QSharedPointer<EventLogList> mList;
|
|
||||||
QSharedPointer<EventLogCore> mLastSearchStart;
|
|
||||||
ChatGui *mChatGui = nullptr;
|
|
||||||
int mInitialDisplayItems = -1;
|
|
||||||
int mMaxDisplayItems = -1;
|
|
||||||
int mDisplayItemsStep = 5;
|
|
||||||
QString mFilterText;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,272 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ChatMessageContentCore.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "core/chat/ChatCore.hpp"
|
|
||||||
#include "model/tool/ToolModel.hpp"
|
|
||||||
#include "tool/providers/ThumbnailProvider.hpp"
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ChatMessageContentCore)
|
|
||||||
|
|
||||||
QSharedPointer<ChatMessageContentCore>
|
|
||||||
ChatMessageContentCore::create(const std::shared_ptr<linphone::Content> &content,
|
|
||||||
std::shared_ptr<ChatMessageModel> chatMessageModel) {
|
|
||||||
auto sharedPointer = QSharedPointer<ChatMessageContentCore>(new ChatMessageContentCore(content, chatMessageModel),
|
|
||||||
&QObject::deleteLater);
|
|
||||||
sharedPointer->setSelf(sharedPointer);
|
|
||||||
sharedPointer->moveToThread(App::getInstance()->thread());
|
|
||||||
return sharedPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageContentCore::ChatMessageContentCore(const std::shared_ptr<linphone::Content> &content,
|
|
||||||
std::shared_ptr<ChatMessageModel> chatMessageModel) {
|
|
||||||
if (content) {
|
|
||||||
mName = Utils::coreStringToAppString(content->getName());
|
|
||||||
if (mName.isEmpty()) { // Try to find the name from file Path
|
|
||||||
QString fileName = Utils::coreStringToAppString(content->getFilePath());
|
|
||||||
if (!fileName.isEmpty()) {
|
|
||||||
mName = QFileInfo(fileName).baseName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mFilePath = QDir::fromNativeSeparators(Utils::coreStringToAppString(content->getFilePath()));
|
|
||||||
mIsFile = content->isFile();
|
|
||||||
mIsFileEncrypted = content->isFileEncrypted();
|
|
||||||
mIsFileTransfer = content->isFileTransfer();
|
|
||||||
mIsCalendar = content->isIcalendar();
|
|
||||||
if (content->isIcalendar()) {
|
|
||||||
auto conferenceInfo = linphone::Factory::get()->createConferenceInfoFromIcalendarContent(content);
|
|
||||||
mConferenceInfo = ConferenceInfoCore::create(conferenceInfo);
|
|
||||||
}
|
|
||||||
mIsMultipart = content->isMultipart();
|
|
||||||
mIsText = content->isText();
|
|
||||||
mIsVoiceRecording = content->isVoiceRecording();
|
|
||||||
mIsVideo = Utils::isVideo(mFilePath);
|
|
||||||
mFileSize = (quint64)content->getFileSize();
|
|
||||||
mFileDuration = content->getFileDuration();
|
|
||||||
mFileOffset = 0;
|
|
||||||
mUtf8Text = Utils::coreStringToAppString(content->getUtf8Text());
|
|
||||||
auto chatRoom = chatMessageModel ? chatMessageModel->getMonitor()->getChatRoom() : nullptr;
|
|
||||||
mRichFormatText = ToolModel::encodeTextToQmlRichFormat(mUtf8Text, {}, chatRoom);
|
|
||||||
mWasDownloaded = !mFilePath.isEmpty() && QFileInfo(mFilePath).isFile();
|
|
||||||
mThumbnail = mFilePath.isEmpty()
|
|
||||||
? QUrl()
|
|
||||||
: QUrl(QString("image://%1/%2").arg(ThumbnailProvider::ProviderId).arg(mFilePath));
|
|
||||||
mChatMessageContentModel = Utils::makeQObject_ptr<ChatMessageContentModel>(content, chatMessageModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageContentCore ::~ChatMessageContentCore() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentCore::setSelf(QSharedPointer<ChatMessageContentCore> me) {
|
|
||||||
mChatMessageContentModelConnection =
|
|
||||||
SafeConnection<ChatMessageContentCore, ChatMessageContentModel>::create(me, mChatMessageContentModel);
|
|
||||||
|
|
||||||
auto updateThumbnailType = [this] {
|
|
||||||
if (Utils::isVideo(mFilePath)) mIsVideo = true;
|
|
||||||
emit isVideoChanged();
|
|
||||||
};
|
|
||||||
|
|
||||||
mChatMessageContentModelConnection->makeConnectToCore(
|
|
||||||
&ChatMessageContentCore::lCreateThumbnail, [this](const bool &force = false) {
|
|
||||||
mChatMessageContentModelConnection->invokeToModel(
|
|
||||||
[this, force] { mChatMessageContentModel->createThumbnail(); });
|
|
||||||
});
|
|
||||||
mChatMessageContentModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageContentModel::thumbnailChanged, [this, updateThumbnailType](QString thumbnail) {
|
|
||||||
mChatMessageContentModelConnection->invokeToCore([this, thumbnail] { setThumbnail(QUrl(thumbnail)); });
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatMessageContentModelConnection->makeConnectToCore(&ChatMessageContentCore::lDownloadFile, [this]() {
|
|
||||||
mChatMessageContentModelConnection->invokeToModel([this] {
|
|
||||||
QString *error = new QString();
|
|
||||||
bool downloaded = mChatMessageContentModel->downloadFile(mName, error);
|
|
||||||
if (!downloaded) {
|
|
||||||
mChatMessageContentModelConnection->invokeToCore([this, error] {
|
|
||||||
//: Error downloading file %1
|
|
||||||
if (error->isEmpty()) *error = tr("download_file_default_error").arg(mName);
|
|
||||||
Utils::showInformationPopup(tr("info_popup_error_titile"), *error, false);
|
|
||||||
delete error;
|
|
||||||
});
|
|
||||||
} else delete error;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mChatMessageContentModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageContentModel::wasDownloadedChanged,
|
|
||||||
[this](const std::shared_ptr<linphone::Content> &content, bool downloaded) {
|
|
||||||
mChatMessageContentModelConnection->invokeToCore([this, downloaded] { setWasDownloaded(downloaded); });
|
|
||||||
});
|
|
||||||
mChatMessageContentModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageContentModel::filePathChanged,
|
|
||||||
[this](const std::shared_ptr<linphone::Content> &content, QString filePath) {
|
|
||||||
auto isFile = content->isFile();
|
|
||||||
auto isFileTransfer = content->isFileTransfer();
|
|
||||||
auto isFileEncrypted = content->isFileEncrypted();
|
|
||||||
mChatMessageContentModelConnection->invokeToCore([this, filePath, isFile, isFileTransfer, isFileEncrypted] {
|
|
||||||
setIsFile(isFile || QFileInfo(filePath).isFile());
|
|
||||||
setIsFileTransfer(isFileTransfer);
|
|
||||||
setIsFileEncrypted(isFileEncrypted);
|
|
||||||
setFilePath(filePath);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
mChatMessageContentModelConnection->makeConnectToCore(&ChatMessageContentCore::lCancelDownloadFile, [this]() {
|
|
||||||
mChatMessageContentModelConnection->invokeToModel([this] { mChatMessageContentModel->cancelDownloadFile(); });
|
|
||||||
});
|
|
||||||
mChatMessageContentModelConnection->makeConnectToCore(
|
|
||||||
&ChatMessageContentCore::lOpenFile, [this](bool showDirectory = false) {
|
|
||||||
if (!QFileInfo(mFilePath).exists()) {
|
|
||||||
//: Error
|
|
||||||
Utils::showInformationPopup(tr("popup_error_title"),
|
|
||||||
//: Could not open file : unknown path %1
|
|
||||||
tr("popup_open_file_error_does_not_exist_message").arg(mFilePath), false);
|
|
||||||
} else {
|
|
||||||
mChatMessageContentModelConnection->invokeToModel([this, showDirectory] {
|
|
||||||
mChatMessageContentModel->openFile(mName, mWasDownloaded, showDirectory);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mChatMessageContentModelConnection->makeConnectToModel(
|
|
||||||
&ChatMessageContentModel::messageStateChanged, [this](linphone::ChatMessage::State state) {
|
|
||||||
mChatMessageContentModelConnection->invokeToCore(
|
|
||||||
[this, msgState = LinphoneEnums::fromLinphone(state)] { emit msgStateChanged(msgState); });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageContentCore::isFile() const {
|
|
||||||
return mIsFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentCore::setIsFile(bool isFile) {
|
|
||||||
if (mIsFile != isFile) {
|
|
||||||
mIsFile = isFile;
|
|
||||||
emit isFileChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageContentCore::isVideo() const {
|
|
||||||
return mIsVideo;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageContentCore::isFileEncrypted() const {
|
|
||||||
return mIsFileEncrypted;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentCore::setIsFileEncrypted(bool isFileEncrypted) {
|
|
||||||
if (mIsFileEncrypted != isFileEncrypted) {
|
|
||||||
mIsFileEncrypted = isFileEncrypted;
|
|
||||||
emit isFileEncryptedChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageContentCore::isFileTransfer() const {
|
|
||||||
return mIsFileTransfer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentCore::setIsFileTransfer(bool isFileTransfer) {
|
|
||||||
if (mIsFileTransfer != isFileTransfer) {
|
|
||||||
mIsFileTransfer = isFileTransfer;
|
|
||||||
emit isFileTransferChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageContentCore::isCalendar() const {
|
|
||||||
return mIsCalendar;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageContentCore::isMultipart() const {
|
|
||||||
return mIsMultipart;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageContentCore::isText() const {
|
|
||||||
return mIsText;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageContentCore::isVoiceRecording() const {
|
|
||||||
return mIsVoiceRecording;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatMessageContentCore::getFilePath() const {
|
|
||||||
return mFilePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentCore::setFilePath(QString path) {
|
|
||||||
if (mFilePath != path) {
|
|
||||||
mFilePath = path;
|
|
||||||
emit filePathChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatMessageContentCore::getUtf8Text() const {
|
|
||||||
return mUtf8Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChatMessageContentCore::getName() const {
|
|
||||||
return mName;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 ChatMessageContentCore::getFileSize() const {
|
|
||||||
return mFileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 ChatMessageContentCore::getFileOffset() const {
|
|
||||||
return mFileOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentCore::setFileOffset(quint64 fileOffset) {
|
|
||||||
if (mFileOffset != fileOffset) {
|
|
||||||
mFileOffset = fileOffset;
|
|
||||||
emit fileOffsetChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int ChatMessageContentCore::getFileDuration() const {
|
|
||||||
return mFileDuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConferenceInfoGui *ChatMessageContentCore::getConferenceInfoGui() const {
|
|
||||||
return mConferenceInfo ? new ConferenceInfoGui(mConferenceInfo) : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageContentCore::wasDownloaded() const {
|
|
||||||
return mWasDownloaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
QUrl ChatMessageContentCore::getThumbnail() const {
|
|
||||||
return mThumbnail;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentCore::setThumbnail(const QUrl &data) {
|
|
||||||
if (mThumbnail != data) {
|
|
||||||
mThumbnail = data;
|
|
||||||
emit thumbnailChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void ChatMessageContentCore::setWasDownloaded(bool wasDownloaded) {
|
|
||||||
if (mWasDownloaded != wasDownloaded) {
|
|
||||||
mWasDownloaded = wasDownloaded;
|
|
||||||
emit wasDownloadedChanged(wasDownloaded);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::shared_ptr<ChatMessageContentModel> &ChatMessageContentCore::getContentModel() const {
|
|
||||||
return mChatMessageContentModel;
|
|
||||||
}
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHAT_MESSAGE_CONTENT_CORE_H_
|
|
||||||
#define CHAT_MESSAGE_CONTENT_CORE_H_
|
|
||||||
|
|
||||||
#include "core/conference/ConferenceInfoCore.hpp"
|
|
||||||
#include "core/conference/ConferenceInfoGui.hpp"
|
|
||||||
#include "model/chat/message/content/ChatMessageContentModel.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
|
||||||
#include <QObject>
|
|
||||||
#include <QSharedPointer>
|
|
||||||
|
|
||||||
#include <linphone++/linphone.hh>
|
|
||||||
|
|
||||||
class ChatMessageContentCore : public QObject, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(QString name READ getName CONSTANT)
|
|
||||||
Q_PROPERTY(quint64 fileOffset READ getFileOffset WRITE setFileOffset NOTIFY fileOffsetChanged)
|
|
||||||
|
|
||||||
Q_PROPERTY(QUrl thumbnail READ getThumbnail WRITE setThumbnail NOTIFY thumbnailChanged)
|
|
||||||
Q_PROPERTY(bool wasDownloaded READ wasDownloaded WRITE setWasDownloaded NOTIFY wasDownloadedChanged)
|
|
||||||
Q_PROPERTY(QString filePath READ getFilePath WRITE setFilePath NOTIFY filePathChanged)
|
|
||||||
Q_PROPERTY(QString utf8Text READ getUtf8Text CONSTANT)
|
|
||||||
Q_PROPERTY(QString richFormatText MEMBER mRichFormatText CONSTANT)
|
|
||||||
Q_PROPERTY(bool isFile READ isFile WRITE setIsFile NOTIFY isFileChanged)
|
|
||||||
Q_PROPERTY(bool isFileEncrypted READ isFileEncrypted WRITE setIsFileEncrypted NOTIFY isFileEncryptedChanged)
|
|
||||||
Q_PROPERTY(bool isFileTransfer READ isFileTransfer WRITE setIsFileTransfer NOTIFY isFileTransferChanged)
|
|
||||||
Q_PROPERTY(bool isCalendar READ isCalendar CONSTANT)
|
|
||||||
Q_PROPERTY(ConferenceInfoGui *conferenceInfo READ getConferenceInfoGui CONSTANT)
|
|
||||||
Q_PROPERTY(bool isMultipart READ isMultipart CONSTANT)
|
|
||||||
Q_PROPERTY(bool isText READ isText CONSTANT)
|
|
||||||
Q_PROPERTY(bool isVideo READ isVideo NOTIFY isVideoChanged)
|
|
||||||
Q_PROPERTY(bool isVoiceRecording READ isVoiceRecording CONSTANT)
|
|
||||||
Q_PROPERTY(int fileDuration READ getFileDuration CONSTANT)
|
|
||||||
Q_PROPERTY(quint64 fileSize READ getFileSize CONSTANT)
|
|
||||||
|
|
||||||
public:
|
|
||||||
static QSharedPointer<ChatMessageContentCore> create(const std::shared_ptr<linphone::Content> &content,
|
|
||||||
std::shared_ptr<ChatMessageModel> chatMessageModel);
|
|
||||||
ChatMessageContentCore(const std::shared_ptr<linphone::Content> &content,
|
|
||||||
std::shared_ptr<ChatMessageModel> chatMessageModel);
|
|
||||||
~ChatMessageContentCore();
|
|
||||||
void setSelf(QSharedPointer<ChatMessageContentCore> me);
|
|
||||||
|
|
||||||
bool isFile() const;
|
|
||||||
void setIsFile(bool isFile);
|
|
||||||
bool isFileEncrypted() const;
|
|
||||||
void setIsFileEncrypted(bool isFileEncrypted);
|
|
||||||
bool isFileTransfer() const;
|
|
||||||
void setIsFileTransfer(bool isFileTransfer);
|
|
||||||
|
|
||||||
bool isVideo() const;
|
|
||||||
bool isCalendar() const;
|
|
||||||
bool isMultipart() const;
|
|
||||||
bool isText() const;
|
|
||||||
bool isVoiceRecording() const;
|
|
||||||
|
|
||||||
QString getUtf8Text() const;
|
|
||||||
QString getName() const;
|
|
||||||
quint64 getFileSize() const;
|
|
||||||
quint64 getFileOffset() const;
|
|
||||||
void setFileOffset(quint64 fileOffset);
|
|
||||||
QString getFilePath() const;
|
|
||||||
void setFilePath(QString path);
|
|
||||||
int getFileDuration() const;
|
|
||||||
ConferenceInfoGui *getConferenceInfoGui() const;
|
|
||||||
|
|
||||||
void setThumbnail(const QUrl &data);
|
|
||||||
QUrl getThumbnail() const;
|
|
||||||
|
|
||||||
bool wasDownloaded() const;
|
|
||||||
void setWasDownloaded(bool downloaded);
|
|
||||||
|
|
||||||
const std::shared_ptr<ChatMessageContentModel> &getContentModel() const;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void msgStateChanged(LinphoneEnums::ChatMessageState state);
|
|
||||||
void thumbnailChanged();
|
|
||||||
void fileOffsetChanged();
|
|
||||||
void filePathChanged();
|
|
||||||
void isFileChanged();
|
|
||||||
void isFileTransferChanged();
|
|
||||||
void isFileEncryptedChanged();
|
|
||||||
void wasDownloadedChanged(bool downloaded);
|
|
||||||
void isVideoChanged();
|
|
||||||
|
|
||||||
void lCreateThumbnail(const bool &force = false);
|
|
||||||
void lRemoveDownloadedFile();
|
|
||||||
void lDownloadFile();
|
|
||||||
void lCancelDownloadFile();
|
|
||||||
void lOpenFile(bool showDirectory = false);
|
|
||||||
bool lSaveAs(const QString &path);
|
|
||||||
|
|
||||||
private:
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
bool mIsFile;
|
|
||||||
bool mIsVideo;
|
|
||||||
bool mIsFileEncrypted;
|
|
||||||
bool mIsFileTransfer;
|
|
||||||
bool mIsCalendar;
|
|
||||||
bool mIsMultipart;
|
|
||||||
bool mIsText;
|
|
||||||
bool mIsVoiceRecording;
|
|
||||||
int mFileDuration;
|
|
||||||
QUrl mThumbnail;
|
|
||||||
QString mUtf8Text;
|
|
||||||
QString mRichFormatText;
|
|
||||||
QString mFilePath;
|
|
||||||
QString mName;
|
|
||||||
quint64 mFileSize;
|
|
||||||
quint64 mFileOffset;
|
|
||||||
bool mWasDownloaded;
|
|
||||||
QSharedPointer<ConferenceInfoCore> mConferenceInfo = nullptr;
|
|
||||||
|
|
||||||
std::shared_ptr<ChatMessageContentModel> mChatMessageContentModel;
|
|
||||||
QSharedPointer<SafeConnection<ChatMessageContentCore, ChatMessageContentModel>> mChatMessageContentModelConnection;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CHAT_MESSAGE_CONTENT_CORE_H_
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ChatMessageContentGui.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ChatMessageContentGui)
|
|
||||||
|
|
||||||
ChatMessageContentGui::ChatMessageContentGui(QSharedPointer<ChatMessageContentCore> core) {
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
|
|
||||||
mCore = core;
|
|
||||||
if (isInLinphoneThread()) moveToThread(App::getInstance()->thread());
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageContentGui::~ChatMessageContentGui() {
|
|
||||||
mustBeInMainThread("~" + getClassName());
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageContentCore *ChatMessageContentGui::getCore() const {
|
|
||||||
return mCore.get();
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHAT_MESSAGE_CONTENT_GUI_H_
|
|
||||||
#define CHAT_MESSAGE_CONTENT_GUI_H_
|
|
||||||
|
|
||||||
#include "core/chat/message/content/ChatMessageContentCore.hpp"
|
|
||||||
#include <QObject>
|
|
||||||
#include <QSharedPointer>
|
|
||||||
|
|
||||||
class ChatMessageContentGui : public QObject, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(ChatMessageContentCore *core READ getCore CONSTANT)
|
|
||||||
|
|
||||||
public:
|
|
||||||
ChatMessageContentGui(QSharedPointer<ChatMessageContentCore> core);
|
|
||||||
~ChatMessageContentGui();
|
|
||||||
ChatMessageContentCore *getCore() const;
|
|
||||||
QSharedPointer<ChatMessageContentCore> mCore;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,227 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ChatMessageContentList.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "core/chat/ChatCore.hpp"
|
|
||||||
#include "core/chat/message/content/ChatMessageContentGui.hpp"
|
|
||||||
|
|
||||||
#include <QMimeDatabase>
|
|
||||||
#include <QSharedPointer>
|
|
||||||
|
|
||||||
#include <linphone++/linphone.hh>
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ChatMessageContentList)
|
|
||||||
|
|
||||||
QSharedPointer<ChatMessageContentList> ChatMessageContentList::create() {
|
|
||||||
auto model = QSharedPointer<ChatMessageContentList>(new ChatMessageContentList(), &QObject::deleteLater);
|
|
||||||
model->moveToThread(App::getInstance()->thread());
|
|
||||||
model->setSelf(model);
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageContentList::ChatMessageContentList(QObject *parent) : ListProxy(parent) {
|
|
||||||
mustBeInMainThread(getClassName());
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageContentList::~ChatMessageContentList() {
|
|
||||||
mustBeInMainThread("~" + getClassName());
|
|
||||||
mModelConnection = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageGui *ChatMessageContentList::getChatMessage() const {
|
|
||||||
if (mChatMessageCore) return new ChatMessageGui(mChatMessageCore);
|
|
||||||
else return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedPointer<ChatMessageCore> ChatMessageContentList::getChatMessageCore() const {
|
|
||||||
return mChatMessageCore;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentList::setChatMessageCore(QSharedPointer<ChatMessageCore> core) {
|
|
||||||
if (mChatMessageCore != core) {
|
|
||||||
// if (mChatMessageCore) disconnect(mChatMessageCore.get(), &ChatCore::, this, nullptr);
|
|
||||||
mChatMessageCore = core;
|
|
||||||
// if (mChatMessageCore)
|
|
||||||
// connect(mChatMessageCore.get(), &ChatCore::messageListChanged, this, &ChatMessageContentList::lUpdate);
|
|
||||||
emit chatMessageChanged();
|
|
||||||
lUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentList::setChatMessageGui(ChatMessageGui *chat) {
|
|
||||||
auto chatCore = chat ? chat->mCore : nullptr;
|
|
||||||
setChatMessageCore(chatCore);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ChatMessageContentList::findFirstUnreadIndex() {
|
|
||||||
auto chatList = getSharedList<ChatMessageCore>();
|
|
||||||
auto it = std::find_if(chatList.begin(), chatList.end(),
|
|
||||||
[](const QSharedPointer<ChatMessageCore> item) { return !item->isRead(); });
|
|
||||||
return it == chatList.end() ? -1 : std::distance(chatList.begin(), it);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentList::addFiles(const QStringList &paths) {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
|
|
||||||
QStringList finalList;
|
|
||||||
QList<QFileInfo> fileList;
|
|
||||||
|
|
||||||
int nbNotFound = 0;
|
|
||||||
QString lastNotFound;
|
|
||||||
int nbExcess = 0;
|
|
||||||
int count = rowCount();
|
|
||||||
|
|
||||||
for (auto &path : paths) {
|
|
||||||
QFileInfo file(path.toUtf8());
|
|
||||||
// #ifdef _WIN32
|
|
||||||
// // A bug from FileDialog suppose that the file is local and overwrite the uri by removing "\\".
|
|
||||||
// if (!file.exists()) {
|
|
||||||
// path.prepend("\\\\");
|
|
||||||
// file.setFileName(path);
|
|
||||||
// }
|
|
||||||
// #endif
|
|
||||||
if (!file.exists()) {
|
|
||||||
++nbNotFound;
|
|
||||||
lastNotFound = path;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count + finalList.count() >= 12) {
|
|
||||||
++nbExcess;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
finalList.append(path);
|
|
||||||
fileList.append(file);
|
|
||||||
}
|
|
||||||
if (nbNotFound > 0) {
|
|
||||||
//: Error adding file
|
|
||||||
Utils::showInformationPopup(tr("popup_error_title"),
|
|
||||||
//: File was not found: %1
|
|
||||||
(nbNotFound == 1 ? tr("popup_error_path_does_not_exist_message").arg(lastNotFound)
|
|
||||||
//: %n files were not found
|
|
||||||
: tr("popup_error_nb_files_not_found_message").arg(nbNotFound)),
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
if (nbExcess > 0) {
|
|
||||||
//: Error
|
|
||||||
Utils::showInformationPopup(tr("popup_error_title"),
|
|
||||||
//: You can send 12 files maximum at a time. %n files were ignored
|
|
||||||
tr("popup_error_max_files_count_message", "", nbExcess), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
mModelConnection->invokeToModel([this, finalList, fileList] {
|
|
||||||
int nbTooBig = 0;
|
|
||||||
int nbMimeError = 0;
|
|
||||||
QString lastMimeError;
|
|
||||||
QList<QSharedPointer<ChatMessageContentCore>> contentList;
|
|
||||||
for (auto &file : fileList) {
|
|
||||||
qint64 fileSize = file.size();
|
|
||||||
if (fileSize > Constants::FileSizeLimit) {
|
|
||||||
++nbTooBig;
|
|
||||||
lWarning() << log().arg("Unable to send file. (Size limit=%1)").arg(Constants::FileSizeLimit);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto name = file.fileName().toStdString();
|
|
||||||
auto path = file.filePath();
|
|
||||||
std::shared_ptr<linphone::Content> content = CoreModel::getInstance()->getCore()->createContent();
|
|
||||||
QStringList mimeType = QMimeDatabase().mimeTypeForFile(path).name().split('/');
|
|
||||||
if (mimeType.length() != 2) {
|
|
||||||
++nbMimeError;
|
|
||||||
lastMimeError = path;
|
|
||||||
lWarning() << log().arg("Unable to get supported mime type for: `%1`.").arg(path);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
content->setType(Utils::appStringToCoreString(mimeType[0]));
|
|
||||||
content->setSubtype(Utils::appStringToCoreString(mimeType[1]));
|
|
||||||
content->setSize(size_t(fileSize));
|
|
||||||
content->setName(name);
|
|
||||||
content->setFilePath(Utils::appStringToCoreString(path));
|
|
||||||
contentList.append(ChatMessageContentCore::create(content, nullptr));
|
|
||||||
}
|
|
||||||
if (nbTooBig > 0) {
|
|
||||||
//: Error adding file
|
|
||||||
Utils::showInformationPopup(
|
|
||||||
tr("popup_error_title"),
|
|
||||||
//: %n files were ignored cause they exceed the maximum size. (Size limit=%2)
|
|
||||||
tr("popup_error_file_too_big_message").arg(nbTooBig).arg(Constants::FileSizeLimit), false);
|
|
||||||
}
|
|
||||||
if (nbMimeError > 0) {
|
|
||||||
//: Error adding file
|
|
||||||
Utils::showInformationPopup(tr("popup_error_title"),
|
|
||||||
//: Unable to get supported mime type for: `%1`.
|
|
||||||
(nbMimeError == 1
|
|
||||||
? tr("popup_error_unsupported_file_message").arg(lastMimeError)
|
|
||||||
//: Unable to get supported mime type for %1 files.
|
|
||||||
: tr("popup_error_unsupported_files_message").arg(nbMimeError)),
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
|
|
||||||
mModelConnection->invokeToCore([this, contentList] {
|
|
||||||
for (auto &contentCore : contentList) {
|
|
||||||
connect(contentCore.get(), &ChatMessageContentCore::isFileChanged, this, [this, contentCore] {
|
|
||||||
int i = -1;
|
|
||||||
get(contentCore.get(), &i);
|
|
||||||
emit dataChanged(index(i), index(i));
|
|
||||||
});
|
|
||||||
add(contentCore);
|
|
||||||
contentCore->lCreateThumbnail(
|
|
||||||
true); // Was not created because linphone::Content is not considered as a file (yet)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentList::setSelf(QSharedPointer<ChatMessageContentList> me) {
|
|
||||||
mModelConnection = SafeConnection<ChatMessageContentList, CoreModel>::create(me, CoreModel::getInstance());
|
|
||||||
|
|
||||||
mModelConnection->makeConnectToCore(&ChatMessageContentList::lUpdate, [this]() {
|
|
||||||
for (auto &content : getSharedList<ChatMessageContentCore>()) {
|
|
||||||
if (content) disconnect(content.get(), &ChatMessageContentCore::wasDownloadedChanged, this, nullptr);
|
|
||||||
if (content) disconnect(content.get(), &ChatMessageContentCore::thumbnailChanged, this, nullptr);
|
|
||||||
}
|
|
||||||
if (!mChatMessageCore) return;
|
|
||||||
auto contents = mChatMessageCore->getChatMessageContentList();
|
|
||||||
for (auto &content : contents) {
|
|
||||||
connect(content.get(), &ChatMessageContentCore::wasDownloadedChanged, this,
|
|
||||||
[this, content](bool wasDownloaded) {
|
|
||||||
if (wasDownloaded) {
|
|
||||||
content->lCreateThumbnail();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(content.get(), &ChatMessageContentCore::thumbnailChanged, this, [this] { emit lUpdate(); });
|
|
||||||
}
|
|
||||||
resetData<ChatMessageContentCore>(contents);
|
|
||||||
});
|
|
||||||
mModelConnection->makeConnectToCore(&ChatMessageContentList::lAddFiles,
|
|
||||||
[this](const QStringList &paths) { addFiles(paths); });
|
|
||||||
emit lUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant ChatMessageContentList::data(const QModelIndex &index, int role) const {
|
|
||||||
int row = index.row();
|
|
||||||
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
|
||||||
if (role == Qt::DisplayRole)
|
|
||||||
return QVariant::fromValue(new ChatMessageContentGui(mList[row].objectCast<ChatMessageContentCore>()));
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHAT_MESSAGE_CONTENT_LIST_H_
|
|
||||||
#define CHAT_MESSAGE_CONTENT_LIST_H_
|
|
||||||
|
|
||||||
#include "core/proxy/ListProxy.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
|
||||||
#include <QLocale>
|
|
||||||
|
|
||||||
class ChatMessageGui;
|
|
||||||
class ChatMessageCore;
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class ChatMessageContentList : public ListProxy, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
static QSharedPointer<ChatMessageContentList> create();
|
|
||||||
ChatMessageContentList(QObject *parent = Q_NULLPTR);
|
|
||||||
~ChatMessageContentList();
|
|
||||||
|
|
||||||
QSharedPointer<ChatMessageCore> getChatMessageCore() const;
|
|
||||||
ChatMessageGui *getChatMessage() const;
|
|
||||||
void setChatMessageCore(QSharedPointer<ChatMessageCore> core);
|
|
||||||
void setChatMessageGui(ChatMessageGui *chat);
|
|
||||||
|
|
||||||
int findFirstUnreadIndex();
|
|
||||||
|
|
||||||
void addFiles(const QStringList &paths);
|
|
||||||
|
|
||||||
void setSelf(QSharedPointer<ChatMessageContentList> me);
|
|
||||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void lAddFiles(QStringList paths);
|
|
||||||
void isFileChanged();
|
|
||||||
void lUpdate();
|
|
||||||
void chatMessageChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QSharedPointer<ChatMessageCore> mChatMessageCore;
|
|
||||||
QSharedPointer<SafeConnection<ChatMessageContentList, CoreModel>> mModelConnection;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ChatMessageContentProxy.hpp"
|
|
||||||
#include "ChatMessageContentGui.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "core/chat/message/ChatMessageGui.hpp"
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ChatMessageContentProxy)
|
|
||||||
|
|
||||||
ChatMessageContentProxy::ChatMessageContentProxy(QObject *parent) : LimitProxy(parent) {
|
|
||||||
mList = ChatMessageContentList::create();
|
|
||||||
setSourceModel(mList.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageContentProxy::~ChatMessageContentProxy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentProxy::setSourceModel(QAbstractItemModel *model) {
|
|
||||||
auto oldChatMessageContentList = getListModel<ChatMessageContentList>();
|
|
||||||
if (oldChatMessageContentList) {
|
|
||||||
// disconnect(oldChatMessageContentList);
|
|
||||||
}
|
|
||||||
auto newChatMessageContentList = dynamic_cast<ChatMessageContentList *>(model);
|
|
||||||
if (newChatMessageContentList) {
|
|
||||||
// connect(newChatMessageContentList, &ChatMessageContentList::chatChanged, this,
|
|
||||||
// &ChatMessageContentProxy::chatChanged);
|
|
||||||
}
|
|
||||||
setSourceModels(new SortFilterList(model));
|
|
||||||
sort(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageGui *ChatMessageContentProxy::getChatMessageGui() {
|
|
||||||
auto model = getListModel<ChatMessageContentList>();
|
|
||||||
if (!mChatMessageGui && model) mChatMessageGui = model->getChatMessage();
|
|
||||||
return mChatMessageGui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentProxy::setChatMessageGui(ChatMessageGui *chat) {
|
|
||||||
getListModel<ChatMessageContentList>()->setChatMessageGui(chat);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessageContentGui *ChatMessageContentProxy::getChatMessageContentAtIndex(int i) {
|
|
||||||
auto model = getListModel<ChatMessageContentList>();
|
|
||||||
auto sourceIndex = mapToSource(index(i, 0)).row();
|
|
||||||
if (model) {
|
|
||||||
auto chat = model->getAt<ChatMessageContentCore>(sourceIndex);
|
|
||||||
if (chat) return new ChatMessageContentGui(chat);
|
|
||||||
else return nullptr;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentProxy::addFiles(const QStringList &paths) {
|
|
||||||
auto model = getListModel<ChatMessageContentList>();
|
|
||||||
if (model) emit model->lAddFiles(paths);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentProxy::removeContent(ChatMessageContentGui *contentGui) {
|
|
||||||
auto model = getListModel<ChatMessageContentList>();
|
|
||||||
if (model && contentGui) model->remove(contentGui->mCore);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageContentProxy::clear() {
|
|
||||||
auto model = getListModel<ChatMessageContentList>();
|
|
||||||
if (model) model->clearData();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageContentProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
|
||||||
auto contentCore = getItemAtSource<ChatMessageContentList, ChatMessageContentCore>(sourceRow);
|
|
||||||
if (contentCore) {
|
|
||||||
if (mFilterType == (int)FilterContentType::Unknown) return false;
|
|
||||||
else if (mFilterType == (int)FilterContentType::File) {
|
|
||||||
return !contentCore->isVoiceRecording() && (contentCore->isFile() || contentCore->isFileTransfer());
|
|
||||||
} else if (mFilterType == (int)FilterContentType::Text) return contentCore->isText();
|
|
||||||
else if (mFilterType == (int)FilterContentType::Voice) return contentCore->isVoiceRecording();
|
|
||||||
else if (mFilterType == (int)FilterContentType::Conference) return contentCore->isCalendar();
|
|
||||||
else if (mFilterType == (int)FilterContentType::All) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatMessageContentProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft,
|
|
||||||
const QModelIndex &sourceRight) const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHAT_MESSAGE_CONENT_PROXY_H_
|
|
||||||
#define CHAT_MESSAGE_CONENT_PROXY_H_
|
|
||||||
|
|
||||||
#include "ChatMessageContentList.hpp"
|
|
||||||
#include "core/proxy/LimitProxy.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class ChatMessageGui;
|
|
||||||
class ChatMessageContentGui;
|
|
||||||
|
|
||||||
class ChatMessageContentProxy : public LimitProxy, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(ChatMessageGui *chatMessageGui READ getChatMessageGui WRITE setChatMessageGui NOTIFY chatChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum class FilterContentType { Unknown = 0, File = 1, Text = 2, Voice = 3, Conference = 4, All = 5 };
|
|
||||||
Q_ENUM(FilterContentType)
|
|
||||||
|
|
||||||
DECLARE_SORTFILTER_CLASS(ChatMessageContentProxy *mHideListProxy = nullptr;)
|
|
||||||
ChatMessageContentProxy(QObject *parent = Q_NULLPTR);
|
|
||||||
~ChatMessageContentProxy();
|
|
||||||
|
|
||||||
ChatMessageGui *getChatMessageGui();
|
|
||||||
void setChatMessageGui(ChatMessageGui *chat);
|
|
||||||
|
|
||||||
Q_INVOKABLE ChatMessageContentGui *getChatMessageContentAtIndex(int i);
|
|
||||||
|
|
||||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
|
||||||
|
|
||||||
Q_INVOKABLE void addFiles(const QStringList &paths);
|
|
||||||
Q_INVOKABLE void removeContent(ChatMessageContentGui *contentGui);
|
|
||||||
Q_INVOKABLE void clear();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void chatChanged();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QSharedPointer<ChatMessageContentList> mList;
|
|
||||||
ChatMessageGui *mChatMessageGui = nullptr;
|
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ImdnStatusList.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
|
|
||||||
#include <QSharedPointer>
|
|
||||||
|
|
||||||
#include <linphone++/linphone.hh>
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ImdnStatusList)
|
|
||||||
|
|
||||||
QSharedPointer<ImdnStatusList> ImdnStatusList::create() {
|
|
||||||
auto model = QSharedPointer<ImdnStatusList>(new ImdnStatusList(), &QObject::deleteLater);
|
|
||||||
model->moveToThread(App::getInstance()->thread());
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImdnStatusList::ImdnStatusList(QObject *parent) : AbstractListProxy<ImdnStatus>(parent) {
|
|
||||||
mustBeInMainThread(getClassName());
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImdnStatusList::~ImdnStatusList() {
|
|
||||||
mustBeInMainThread("~" + getClassName());
|
|
||||||
mList.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<ImdnStatus> ImdnStatusList::getImdnStatusList() {
|
|
||||||
return mList;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImdnStatusList::setImdnStatusList(QList<ImdnStatus> imdnStatusList) {
|
|
||||||
resetData(imdnStatusList);
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant ImdnStatusList::data(const QModelIndex &index, int role) const {
|
|
||||||
int row = index.row();
|
|
||||||
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
|
||||||
if (role == Qt::DisplayRole) return QVariant::fromValue(mList.at(row));
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IMDN_STATUS_LIST_H_
|
|
||||||
#define IMDN_STATUS_LIST_H_
|
|
||||||
|
|
||||||
#include "core/chat/message/ChatMessageCore.hpp"
|
|
||||||
#include "core/proxy/AbstractListProxy.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
|
||||||
#include <QLocale>
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class ImdnStatusList : public AbstractListProxy<ImdnStatus>, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
static QSharedPointer<ImdnStatusList> create();
|
|
||||||
ImdnStatusList(QObject *parent = Q_NULLPTR);
|
|
||||||
~ImdnStatusList();
|
|
||||||
|
|
||||||
QList<ImdnStatus> getImdnStatusList();
|
|
||||||
void setImdnStatusList(QList<ImdnStatus> imdnStatusList);
|
|
||||||
|
|
||||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void imdnStatusListChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ImdnStatusProxy.hpp"
|
|
||||||
#include "ImdnStatusList.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
// #include "core/chat/message/ChatMessageGui.hpp"
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ImdnStatusProxy)
|
|
||||||
|
|
||||||
ImdnStatusProxy::ImdnStatusProxy(QObject *parent) : LimitProxy(parent) {
|
|
||||||
mList = ImdnStatusList::create();
|
|
||||||
setSourceModel(mList.get());
|
|
||||||
connect(mList.get(), &ImdnStatusList::modelReset, this, &ImdnStatusProxy::imdnStatusListChanged);
|
|
||||||
connect(this, &ImdnStatusProxy::filterChanged, this, [this] { invalidate(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
ImdnStatusProxy::~ImdnStatusProxy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<ImdnStatus> ImdnStatusProxy::getImdnStatusList() {
|
|
||||||
return mList->getImdnStatusList();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImdnStatusProxy::setImdnStatusList(QList<ImdnStatus> statusList) {
|
|
||||||
mList->setImdnStatusList(statusList);
|
|
||||||
}
|
|
||||||
|
|
||||||
LinphoneEnums::ChatMessageState ImdnStatusProxy::getFilter() const {
|
|
||||||
return mFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImdnStatusProxy::setFilter(LinphoneEnums::ChatMessageState filter) {
|
|
||||||
if (mFilter != filter) {
|
|
||||||
mFilter = filter;
|
|
||||||
emit filterChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImdnStatusProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
|
||||||
auto imdn = mList->getAt(sourceRow);
|
|
||||||
return imdn.mState == mFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImdnStatusProxy::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IMDN_STATUS_PROXY_H_
|
|
||||||
#define IMDN_STATUS_PROXY_H_
|
|
||||||
|
|
||||||
#include "core/chat/message/ChatMessageCore.hpp"
|
|
||||||
#include "core/proxy/LimitProxy.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class ImdnStatusList;
|
|
||||||
|
|
||||||
class ImdnStatusProxy : public LimitProxy, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(
|
|
||||||
QList<ImdnStatus> imdnStatusList READ getImdnStatusList WRITE setImdnStatusList NOTIFY imdnStatusListChanged)
|
|
||||||
Q_PROPERTY(LinphoneEnums::ChatMessageState filter READ getFilter WRITE setFilter NOTIFY filterChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
ImdnStatusProxy(QObject *parent = Q_NULLPTR);
|
|
||||||
~ImdnStatusProxy();
|
|
||||||
|
|
||||||
QList<ImdnStatus> getImdnStatusList();
|
|
||||||
void setImdnStatusList(QList<ImdnStatus> imdnStatusList);
|
|
||||||
|
|
||||||
LinphoneEnums::ChatMessageState getFilter() const;
|
|
||||||
void setFilter(LinphoneEnums::ChatMessageState filter);
|
|
||||||
|
|
||||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
|
||||||
bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void imdnStatusListChanged();
|
|
||||||
void filterChanged();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
LinphoneEnums::ChatMessageState mFilter;
|
|
||||||
QSharedPointer<ImdnStatusList> mList;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -47,12 +47,7 @@ ConferenceCore::ConferenceCore(const std::shared_ptr<linphone::Conference> &conf
|
||||||
mIsLocalScreenSharing = mConferenceModel->isLocalScreenSharing();
|
mIsLocalScreenSharing = mConferenceModel->isLocalScreenSharing();
|
||||||
mIsScreenSharingEnabled = mConferenceModel->isScreenSharingEnabled();
|
mIsScreenSharingEnabled = mConferenceModel->isScreenSharingEnabled();
|
||||||
mIsRecording = conference->isRecording();
|
mIsRecording = conference->isRecording();
|
||||||
if (conference->getCurrentParams()) mIsChatEnabled = conference->getCurrentParams()->chatEnabled();
|
|
||||||
auto me = conference->getMe();
|
auto me = conference->getMe();
|
||||||
auto confAddress = conference->getConferenceAddress();
|
|
||||||
if (confAddress) {
|
|
||||||
mConfUri = Utils::coreStringToAppString(confAddress->asStringUriOnly());
|
|
||||||
}
|
|
||||||
if (me) {
|
if (me) {
|
||||||
mMe = ParticipantCore::create(me);
|
mMe = ParticipantCore::create(me);
|
||||||
}
|
}
|
||||||
|
|
@ -80,14 +75,7 @@ void ConferenceCore::setSelf(QSharedPointer<ConferenceCore> me) {
|
||||||
if (newState == linphone::Conference::State::Created) {
|
if (newState == linphone::Conference::State::Created) {
|
||||||
if (auto participantDevice = conference->getActiveSpeakerParticipantDevice()) {
|
if (auto participantDevice = conference->getActiveSpeakerParticipantDevice()) {
|
||||||
auto device = ParticipantDeviceCore::create(participantDevice);
|
auto device = ParticipantDeviceCore::create(participantDevice);
|
||||||
QString address;
|
mConferenceModelConnection->invokeToCore([this, device]() { setActiveSpeakerDevice(device); });
|
||||||
auto confAddress = conference->getConferenceAddress();
|
|
||||||
if (confAddress) address = Utils::coreStringToAppString(confAddress->asStringUriOnly());
|
|
||||||
mConferenceModelConnection->invokeToCore([this, device, address]() {
|
|
||||||
setActiveSpeakerDevice(device);
|
|
||||||
mConfUri = address;
|
|
||||||
emit conferenceUriChanged();
|
|
||||||
});
|
|
||||||
} else if (conference->getParticipantDeviceList().size() > 1) {
|
} else if (conference->getParticipantDeviceList().size() > 1) {
|
||||||
for (auto &device : conference->getParticipantDeviceList()) {
|
for (auto &device : conference->getParticipantDeviceList()) {
|
||||||
if (!ToolModel::isMe(device->getAddress())) {
|
if (!ToolModel::isMe(device->getAddress())) {
|
||||||
|
|
@ -206,10 +194,6 @@ void ConferenceCore::setIsScreenSharingEnabled(bool state) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConferenceCore::isChatEnabled() const {
|
|
||||||
return mIsChatEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<ConferenceModel> ConferenceCore::getModel() const {
|
std::shared_ptr<ConferenceModel> ConferenceCore::getModel() const {
|
||||||
return mConferenceModel;
|
return mConferenceModel;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,14 +37,12 @@ class ConferenceCore : public QObject, public AbstractObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
Q_PROPERTY(QDateTime startDate READ getStartDate CONSTANT)
|
Q_PROPERTY(QDateTime startDate READ getStartDate CONSTANT)
|
||||||
Q_PROPERTY(bool isChatEnabled READ isChatEnabled CONSTANT)
|
|
||||||
// Q_PROPERTY(ParticipantDeviceList *participantDevices READ getParticipantDeviceList CONSTANT)
|
// Q_PROPERTY(ParticipantDeviceList *participantDevices READ getParticipantDeviceList CONSTANT)
|
||||||
// Q_PROPERTY(ParticipantModel* localParticipant READ getLocalParticipant NOTIFY localParticipantChanged)
|
// Q_PROPERTY(ParticipantModel* localParticipant READ getLocalParticipant NOTIFY localParticipantChanged)
|
||||||
Q_PROPERTY(bool isReady MEMBER mIsReady WRITE setIsReady NOTIFY isReadyChanged)
|
Q_PROPERTY(bool isReady MEMBER mIsReady WRITE setIsReady NOTIFY isReadyChanged)
|
||||||
Q_PROPERTY(bool isRecording READ isRecording WRITE setRecording NOTIFY isRecordingChanged)
|
Q_PROPERTY(bool isRecording READ isRecording WRITE setRecording NOTIFY isRecordingChanged)
|
||||||
|
|
||||||
Q_PROPERTY(QString subject READ getSubject WRITE setSubject NOTIFY subjectChanged)
|
Q_PROPERTY(QString subject READ getSubject WRITE setSubject NOTIFY subjectChanged)
|
||||||
Q_PROPERTY(QString uri MEMBER mConfUri NOTIFY conferenceUriChanged)
|
|
||||||
Q_PROPERTY(bool isLocalScreenSharing MEMBER mIsLocalScreenSharing WRITE setIsLocalScreenSharing NOTIFY
|
Q_PROPERTY(bool isLocalScreenSharing MEMBER mIsLocalScreenSharing WRITE setIsLocalScreenSharing NOTIFY
|
||||||
isLocalScreenSharingChanged)
|
isLocalScreenSharingChanged)
|
||||||
Q_PROPERTY(bool isScreenSharingEnabled MEMBER mIsScreenSharingEnabled WRITE setIsScreenSharingEnabled NOTIFY
|
Q_PROPERTY(bool isScreenSharingEnabled MEMBER mIsScreenSharingEnabled WRITE setIsScreenSharingEnabled NOTIFY
|
||||||
|
|
@ -82,8 +80,6 @@ public:
|
||||||
void setIsLocalScreenSharing(bool state);
|
void setIsLocalScreenSharing(bool state);
|
||||||
void setIsScreenSharingEnabled(bool state);
|
void setIsScreenSharingEnabled(bool state);
|
||||||
|
|
||||||
bool isChatEnabled() const;
|
|
||||||
|
|
||||||
std::shared_ptr<ConferenceModel> getModel() const;
|
std::shared_ptr<ConferenceModel> getModel() const;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
@ -96,7 +92,6 @@ signals:
|
||||||
void activeSpeakerDeviceChanged();
|
void activeSpeakerDeviceChanged();
|
||||||
void subjectChanged();
|
void subjectChanged();
|
||||||
void isRecordingChanged();
|
void isRecordingChanged();
|
||||||
void conferenceUriChanged();
|
|
||||||
|
|
||||||
void lToggleScreenSharing();
|
void lToggleScreenSharing();
|
||||||
|
|
||||||
|
|
@ -111,9 +106,7 @@ private:
|
||||||
bool mIsRecording = false;
|
bool mIsRecording = false;
|
||||||
bool mIsLocalScreenSharing = false;
|
bool mIsLocalScreenSharing = false;
|
||||||
bool mIsScreenSharingEnabled = false;
|
bool mIsScreenSharingEnabled = false;
|
||||||
bool mIsChatEnabled = false;
|
|
||||||
QString mSubject;
|
QString mSubject;
|
||||||
QString mConfUri;
|
|
||||||
QDateTime mStartDate = QDateTime::currentDateTime();
|
QDateTime mStartDate = QDateTime::currentDateTime();
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 Belledonne Communications SARL.
|
* Copyright (c) 2021 Belledonne Communications SARL.
|
||||||
*
|
*
|
||||||
* This file is part of linphone-desktop
|
* This file is part of linphone-desktop
|
||||||
|
|
@ -21,15 +21,12 @@
|
||||||
#include "ConferenceInfoCore.hpp"
|
#include "ConferenceInfoCore.hpp"
|
||||||
|
|
||||||
#include "core/App.hpp"
|
#include "core/App.hpp"
|
||||||
#include "core/path/Paths.hpp"
|
|
||||||
#include "core/proxy/ListProxy.hpp"
|
#include "core/proxy/ListProxy.hpp"
|
||||||
#include "model/object/VariantObject.hpp"
|
#include "model/object/VariantObject.hpp"
|
||||||
#include "model/tool/ToolModel.hpp"
|
#include "model/tool/ToolModel.hpp"
|
||||||
#include "tool/Utils.hpp"
|
#include "tool/Utils.hpp"
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
#include "tool/thread/SafeConnection.hpp"
|
||||||
|
|
||||||
#include <QDesktopServices>
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ConferenceInfoCore)
|
DEFINE_ABSTRACT_OBJECT(ConferenceInfoCore)
|
||||||
|
|
||||||
QSharedPointer<ConferenceInfoCore>
|
QSharedPointer<ConferenceInfoCore>
|
||||||
|
|
@ -72,13 +69,16 @@ ConferenceInfoCore::ConferenceInfoCore(std::shared_ptr<linphone::ConferenceInfo>
|
||||||
mUri = address && address->isValid() && !address->getDomain().empty()
|
mUri = address && address->isValid() && !address->getDomain().empty()
|
||||||
? Utils::coreStringToAppString(address->asStringUriOnly())
|
? Utils::coreStringToAppString(address->asStringUriOnly())
|
||||||
: "";
|
: "";
|
||||||
mIcalendarString = Utils::coreStringToAppString(conferenceInfo->getIcalendarString());
|
|
||||||
mDateTime = QDateTime::fromMSecsSinceEpoch(conferenceInfo->getDateTime() * 1000);
|
mDateTime = QDateTime::fromMSecsSinceEpoch(conferenceInfo->getDateTime() * 1000);
|
||||||
mDuration = conferenceInfo->getDuration();
|
mDuration = conferenceInfo->getDuration();
|
||||||
mEndDateTime = mDateTime.addSecs(mDuration * 60);
|
mEndDateTime = mDateTime.addSecs(mDuration * 60);
|
||||||
mIsScheduled = mDateTime.isValid();
|
mIsScheduled = mDateTime.isValid();
|
||||||
mOrganizerAddress = Utils::coreStringToAppString(conferenceInfo->getOrganizer()->asStringUriOnly());
|
mOrganizerAddress = Utils::coreStringToAppString(conferenceInfo->getOrganizer()->asStringUriOnly());
|
||||||
mOrganizerName = mConferenceInfoModel->getOrganizerName();
|
mOrganizerName = Utils::coreStringToAppString(conferenceInfo->getOrganizer()->getDisplayName());
|
||||||
|
if (mOrganizerName.isEmpty()) {
|
||||||
|
mOrganizerName = Utils::coreStringToAppString(conferenceInfo->getOrganizer()->getUsername());
|
||||||
|
mOrganizerName.replace(".", " ");
|
||||||
|
}
|
||||||
mSubject = Utils::coreStringToAppString(conferenceInfo->getSubject());
|
mSubject = Utils::coreStringToAppString(conferenceInfo->getSubject());
|
||||||
mDescription = Utils::coreStringToAppString(conferenceInfo->getDescription());
|
mDescription = Utils::coreStringToAppString(conferenceInfo->getDescription());
|
||||||
mIsEnded = getDateTimeUtc().addSecs(mDuration * 60) < QDateTime::currentDateTimeUtc();
|
mIsEnded = getDateTimeUtc().addSecs(mDuration * 60) < QDateTime::currentDateTimeUtc();
|
||||||
|
|
@ -127,7 +127,6 @@ ConferenceInfoCore::ConferenceInfoCore(const ConferenceInfoCore &conferenceInfoC
|
||||||
mIsEnded = conferenceInfoCore.mIsEnded;
|
mIsEnded = conferenceInfoCore.mIsEnded;
|
||||||
mInviteEnabled = conferenceInfoCore.mInviteEnabled;
|
mInviteEnabled = conferenceInfoCore.mInviteEnabled;
|
||||||
mConferenceInfoState = conferenceInfoCore.mConferenceInfoState;
|
mConferenceInfoState = conferenceInfoCore.mConferenceInfoState;
|
||||||
mIcalendarString = conferenceInfoCore.mIcalendarString;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConferenceInfoCore::~ConferenceInfoCore() {
|
ConferenceInfoCore::~ConferenceInfoCore() {
|
||||||
|
|
@ -180,13 +179,6 @@ void ConferenceInfoCore::setSelf(QSharedPointer<ConferenceInfoCore> me) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
mConfInfoModelConnection->makeConnectToCore(&ConferenceInfoCore::lCancelCreation, [this]() {
|
|
||||||
mConfInfoModelConnection->invokeToModel([this] {
|
|
||||||
if (mConferenceInfoModel) {
|
|
||||||
mConferenceInfoModel->setConferenceScheduler(nullptr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mConfInfoModelConnection->makeConnectToCore(&ConferenceInfoCore::lDeleteConferenceInfo, [this]() {
|
mConfInfoModelConnection->makeConnectToCore(&ConferenceInfoCore::lDeleteConferenceInfo, [this]() {
|
||||||
mConfInfoModelConnection->invokeToModel([this] { mConferenceInfoModel->deleteConferenceInfo(); });
|
mConfInfoModelConnection->invokeToModel([this] { mConferenceInfoModel->deleteConferenceInfo(); });
|
||||||
});
|
});
|
||||||
|
|
@ -200,15 +192,21 @@ void ConferenceInfoCore::setSelf(QSharedPointer<ConferenceInfoCore> me) {
|
||||||
QString uri;
|
QString uri;
|
||||||
if (state == linphone::ConferenceScheduler::State::Ready) {
|
if (state == linphone::ConferenceScheduler::State::Ready) {
|
||||||
uri = mConferenceInfoModel->getConferenceScheduler()->getUri();
|
uri = mConferenceInfoModel->getConferenceScheduler()->getUri();
|
||||||
emit CoreModel::getInstance() -> conferenceInfoReceived(
|
|
||||||
CoreModel::getInstance()->getCore(),
|
|
||||||
mConferenceInfoModel->getConferenceInfo());
|
|
||||||
}
|
}
|
||||||
mConfInfoModelConnection->invokeToCore([this, state = LinphoneEnums::fromLinphone(state),
|
mConfInfoModelConnection->invokeToCore([this, state = LinphoneEnums::fromLinphone(state),
|
||||||
infoState = LinphoneEnums::fromLinphone(confInfoState),
|
infoState = LinphoneEnums::fromLinphone(confInfoState),
|
||||||
uri] {
|
uri] {
|
||||||
setConferenceSchedulerState(state);
|
setConferenceSchedulerState(state);
|
||||||
setConferenceInfoState(infoState);
|
setConferenceInfoState(infoState);
|
||||||
|
if (state == LinphoneEnums::ConferenceSchedulerState::Ready) {
|
||||||
|
setUri(uri);
|
||||||
|
mConfInfoModelConnection->invokeToModel([this, uri, infoState] {
|
||||||
|
if (infoState == LinphoneEnums::ConferenceInfoState::New)
|
||||||
|
emit CoreModel::getInstance()->conferenceInfoCreated(
|
||||||
|
mConferenceInfoModel->getConferenceInfo());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setConferenceSchedulerState(state);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
mConfInfoModelConnection->makeConnectToModel(
|
mConfInfoModelConnection->makeConnectToModel(
|
||||||
|
|
@ -330,8 +328,7 @@ void ConferenceInfoCore::setTimeZoneModel(TimeZoneModel *model) {
|
||||||
mTimeZoneModel->getStandardTimeOffset() != model->getStandardTimeOffset() ||
|
mTimeZoneModel->getStandardTimeOffset() != model->getStandardTimeOffset() ||
|
||||||
mTimeZoneModel->getTimeZone() != model->getTimeZone()) {
|
mTimeZoneModel->getTimeZone() != model->getTimeZone()) {
|
||||||
|
|
||||||
mTimeZoneModel = QSharedPointer<TimeZoneModel>(new TimeZoneModel(model->getTimeZone()));
|
mTimeZoneModel = QSharedPointer<TimeZoneModel>(model);
|
||||||
|
|
||||||
emit timeZoneModelChanged();
|
emit timeZoneModelChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -558,10 +555,6 @@ void ConferenceInfoCore::writeIntoModel(std::shared_ptr<ConferenceInfoModel> mod
|
||||||
model->setParticipantInfos(participantInfos);
|
model->setParticipantInfos(participantInfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ConferenceInfoModel> ConferenceInfoCore::getModel() const {
|
|
||||||
return mConferenceInfoModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConferenceInfoCore::save() {
|
void ConferenceInfoCore::save() {
|
||||||
mustBeInMainThread(getClassName() + "::save()");
|
mustBeInMainThread(getClassName() + "::save()");
|
||||||
ConferenceInfoCore *thisCopy = new ConferenceInfoCore(*this); // Pointer to avoid multiple copies in lambdas
|
ConferenceInfoCore *thisCopy = new ConferenceInfoCore(*this); // Pointer to avoid multiple copies in lambdas
|
||||||
|
|
@ -582,8 +575,8 @@ void ConferenceInfoCore::save() {
|
||||||
linphone::RegistrationState::Ok) {
|
linphone::RegistrationState::Ok) {
|
||||||
//: "Erreur"
|
//: "Erreur"
|
||||||
Utils::showInformationPopup(tr("information_popup_error_title"),
|
Utils::showInformationPopup(tr("information_popup_error_title"),
|
||||||
//: "Votre compte est déconnecté"
|
//: "Votre compte est déconnecté"
|
||||||
tr("information_popup_disconnected_account_message"), false);
|
tr("information_popup_disconnected_account_message"), false);
|
||||||
emit saveFailed();
|
emit saveFailed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -606,9 +599,6 @@ void ConferenceInfoCore::save() {
|
||||||
} else lCritical() << "No default account";
|
} else lCritical() << "No default account";
|
||||||
// Add text capability for chat in conf
|
// Add text capability for chat in conf
|
||||||
linphoneConf->setCapability(linphone::StreamType::Text, true);
|
linphoneConf->setCapability(linphone::StreamType::Text, true);
|
||||||
if (SettingsModel::getInstance()->getCreateEndToEndEncryptedMeetingsAndGroupCalls())
|
|
||||||
linphoneConf->setSecurityLevel(linphone::Conference::SecurityLevel::EndToEnd);
|
|
||||||
else linphoneConf->setSecurityLevel(linphone::Conference::SecurityLevel::PointToPoint);
|
|
||||||
auto confInfoModel = Utils::makeQObject_ptr<ConferenceInfoModel>(linphoneConf);
|
auto confInfoModel = Utils::makeQObject_ptr<ConferenceInfoModel>(linphoneConf);
|
||||||
auto confSchedulerModel = confInfoModel->getConferenceScheduler();
|
auto confSchedulerModel = confInfoModel->getConferenceScheduler();
|
||||||
if (!confSchedulerModel) {
|
if (!confSchedulerModel) {
|
||||||
|
|
@ -647,6 +637,12 @@ void ConferenceInfoCore::undo() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConferenceInfoCore::cancelCreation() {
|
||||||
|
if (mConferenceInfoModel) {
|
||||||
|
mConferenceInfoModel->setConferenceScheduler(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void ConferenceInfoCore::onInvitationsSent(const std::list<std::shared_ptr<linphone::Address>> &failedInvitations) {
|
void ConferenceInfoCore::onInvitationsSent(const std::list<std::shared_ptr<linphone::Address>> &failedInvitations) {
|
||||||
|
|
@ -658,14 +654,3 @@ bool ConferenceInfoCore::isAllDayConf() const {
|
||||||
return mDateTime.time().hour() == 0 && mDateTime.time().minute() == 0 && mEndDateTime.time().hour() == 23 &&
|
return mDateTime.time().hour() == 0 && mDateTime.time().minute() == 0 && mEndDateTime.time().hour() == 23 &&
|
||||||
mEndDateTime.time().minute() == 59;
|
mEndDateTime.time().minute() == 59;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConferenceInfoCore::exportConferenceToICS() const {
|
|
||||||
QString filePath(Paths::getAppLocalDirPath() + "conference.ics");
|
|
||||||
QFile file(filePath);
|
|
||||||
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
||||||
QTextStream out(&file);
|
|
||||||
out << mIcalendarString;
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 Belledonne Communications SARL.
|
* Copyright (c) 2022 Belledonne Communications SARL.
|
||||||
*
|
*
|
||||||
* This file is part of linphone-desktop
|
* This file is part of linphone-desktop
|
||||||
|
|
@ -126,17 +126,14 @@ public:
|
||||||
void writeFromModel(const std::shared_ptr<ConferenceInfoModel> &model);
|
void writeFromModel(const std::shared_ptr<ConferenceInfoModel> &model);
|
||||||
void writeIntoModel(std::shared_ptr<ConferenceInfoModel> model);
|
void writeIntoModel(std::shared_ptr<ConferenceInfoModel> model);
|
||||||
|
|
||||||
std::shared_ptr<ConferenceInfoModel> getModel() const;
|
|
||||||
|
|
||||||
Q_INVOKABLE void save();
|
Q_INVOKABLE void save();
|
||||||
Q_INVOKABLE void undo();
|
Q_INVOKABLE void undo();
|
||||||
|
Q_INVOKABLE void cancelCreation();
|
||||||
|
|
||||||
virtual void onInvitationsSent(const std::list<std::shared_ptr<linphone::Address>> &failedInvitations);
|
virtual void onInvitationsSent(const std::list<std::shared_ptr<linphone::Address>> &failedInvitations);
|
||||||
|
|
||||||
Q_INVOKABLE bool isAllDayConf() const;
|
Q_INVOKABLE bool isAllDayConf() const;
|
||||||
|
|
||||||
Q_INVOKABLE void exportConferenceToICS() const;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dateTimeChanged();
|
void dateTimeChanged();
|
||||||
void endDateTimeChanged();
|
void endDateTimeChanged();
|
||||||
|
|
@ -161,7 +158,6 @@ signals:
|
||||||
void invitationsSent();
|
void invitationsSent();
|
||||||
void removed(ConferenceInfoCore *confInfo);
|
void removed(ConferenceInfoCore *confInfo);
|
||||||
|
|
||||||
void lCancelCreation();
|
|
||||||
void lCancelConferenceInfo();
|
void lCancelConferenceInfo();
|
||||||
void lDeleteConferenceInfo(); // Remove completly this conference info from DB
|
void lDeleteConferenceInfo(); // Remove completly this conference info from DB
|
||||||
|
|
||||||
|
|
@ -179,7 +175,6 @@ private:
|
||||||
QString mSubject;
|
QString mSubject;
|
||||||
QString mDescription;
|
QString mDescription;
|
||||||
QString mUri;
|
QString mUri;
|
||||||
QString mIcalendarString;
|
|
||||||
QVariantList mParticipants;
|
QVariantList mParticipants;
|
||||||
QSharedPointer<TimeZoneModel> mTimeZoneModel;
|
QSharedPointer<TimeZoneModel> mTimeZoneModel;
|
||||||
LinphoneEnums::ConferenceSchedulerState mConferenceSchedulerState;
|
LinphoneEnums::ConferenceSchedulerState mConferenceSchedulerState;
|
||||||
|
|
|
||||||
|
|
@ -58,119 +58,58 @@ ConferenceInfoList::~ConferenceInfoList() {
|
||||||
void ConferenceInfoList::setSelf(QSharedPointer<ConferenceInfoList> me) {
|
void ConferenceInfoList::setSelf(QSharedPointer<ConferenceInfoList> me) {
|
||||||
mCoreModelConnection = SafeConnection<ConferenceInfoList, CoreModel>::create(me, CoreModel::getInstance());
|
mCoreModelConnection = SafeConnection<ConferenceInfoList, CoreModel>::create(me, CoreModel::getInstance());
|
||||||
|
|
||||||
mCoreModelConnection->makeConnectToCore(&ConferenceInfoList::lUpdate, [this]() {
|
mCoreModelConnection->makeConnectToCore(&ConferenceInfoList::lUpdate, [this](bool isInitialization) {
|
||||||
if (mIsUpdating) {
|
mCoreModelConnection->invokeToModel([this, isInitialization]() {
|
||||||
connect(this, &ConferenceInfoList::isUpdatingChanged, this, [this] {
|
|
||||||
if (!mIsUpdating) {
|
|
||||||
disconnect(this, &ConferenceInfoList::isUpdatingChanged, this, nullptr);
|
|
||||||
lUpdate();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setIsUpdating(true);
|
|
||||||
mCoreModelConnection->invokeToModel([this]() {
|
|
||||||
mustBeInLinphoneThread(getClassName());
|
|
||||||
beginResetModel();
|
|
||||||
mList.clear();
|
|
||||||
QList<QSharedPointer<ConferenceInfoCore>> *items = new QList<QSharedPointer<ConferenceInfoCore>>();
|
QList<QSharedPointer<ConferenceInfoCore>> *items = new QList<QSharedPointer<ConferenceInfoCore>>();
|
||||||
|
mustBeInLinphoneThread(getClassName());
|
||||||
auto defaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
|
auto defaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
|
||||||
setAccountConnected(defaultAccount && defaultAccount->getState() == linphone::RegistrationState::Ok);
|
if (!defaultAccount) return;
|
||||||
if (!defaultAccount || !mAccountConnected) {
|
|
||||||
endResetModel();
|
|
||||||
setIsUpdating(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::list<std::shared_ptr<linphone::ConferenceInfo>> conferenceInfos =
|
std::list<std::shared_ptr<linphone::ConferenceInfo>> conferenceInfos =
|
||||||
defaultAccount->getConferenceInformationList();
|
defaultAccount->getConferenceInformationList();
|
||||||
if (conferenceInfos.empty()) {
|
|
||||||
endResetModel();
|
|
||||||
setIsUpdating(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
items->push_back(nullptr); // Add Dummy conference for today
|
items->push_back(nullptr); // Add Dummy conference for today
|
||||||
for (auto conferenceInfo : conferenceInfos) {
|
for (auto conferenceInfo : conferenceInfos) {
|
||||||
// if (conferenceInfo->getState() == linphone::ConferenceInfo::State::Cancelled) {
|
if (conferenceInfo->getState() == linphone::ConferenceInfo::State::Cancelled) {
|
||||||
// auto myAddress = defaultAccount->getParams()->getIdentityAddress();
|
auto myAddress = defaultAccount->getParams()->getIdentityAddress();
|
||||||
// if (!myAddress || myAddress->weakEqual(conferenceInfo->getOrganizer())) continue;
|
if (!myAddress || myAddress->weakEqual(conferenceInfo->getOrganizer())) continue;
|
||||||
// }
|
}
|
||||||
auto confInfoCore = build(conferenceInfo);
|
auto confInfoCore = build(conferenceInfo);
|
||||||
// Cancelled conference organized ourself me must be hidden
|
// Cancelled conference organized ourself me must be hidden
|
||||||
if (confInfoCore) {
|
if (confInfoCore) {
|
||||||
|
// qDebug() << log().arg("Add conf") << confInfoCore->getSubject() << "with state"
|
||||||
|
// << confInfoCore->getConferenceInfoState();
|
||||||
items->push_back(confInfoCore);
|
items->push_back(confInfoCore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mCoreModelConnection->invokeToCore([this, items]() {
|
mCoreModelConnection->invokeToCore([this, items, isInitialization]() {
|
||||||
mustBeInMainThread(getClassName());
|
mustBeInMainThread(getClassName());
|
||||||
for (auto &item : *items) {
|
for (auto &item : *items) {
|
||||||
connectItem(item);
|
connectItem(item);
|
||||||
mList << item.template objectCast<QObject>();
|
|
||||||
}
|
}
|
||||||
updateHaveCurrentDate();
|
resetData(*items);
|
||||||
endResetModel();
|
|
||||||
setIsUpdating(false);
|
|
||||||
delete items;
|
delete items;
|
||||||
|
if (isInitialization) {
|
||||||
|
emit initialized();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
mCoreModelConnection->makeConnectToModel(
|
|
||||||
&CoreModel::conferenceInfoReceived,
|
|
||||||
[this](const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<const linphone::ConferenceInfo> &conferenceInfo) {
|
|
||||||
lInfo() << log().arg("conference info received") << conferenceInfo->getSubject();
|
|
||||||
// We must refresh all the conference infos cause we are not able to determine
|
|
||||||
// which account is concerned by the signal if multiple accounts are connected
|
|
||||||
emit lUpdate();
|
|
||||||
});
|
|
||||||
|
|
||||||
// This is needed because account does not have a contact address until
|
// This is needed because account does not have a contact address until
|
||||||
// it is connected, so we can't verify if it is the organizer of a deleted
|
// it is connected, so we can't verify if it is the organizer of a deleted
|
||||||
// conference (which must hidden)
|
// conference (which must hidden)
|
||||||
|
mCoreModelConnection->makeConnectToModel(&CoreModel::defaultAccountChanged, [this]() { emit lUpdate(true); });
|
||||||
|
|
||||||
mCoreModelConnection->makeConnectToModel(
|
mCoreModelConnection->makeConnectToModel(
|
||||||
&CoreModel::defaultAccountChanged,
|
&CoreModel::conferenceInfoCreated,
|
||||||
[this](const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::Account> &account) {
|
[this](const std::shared_ptr<linphone::ConferenceInfo> &confInfo) { addConference(confInfo); });
|
||||||
auto accountCore = account ? AccountCore::create(account) : nullptr;
|
mCoreModelConnection->makeConnectToModel(
|
||||||
mCoreModelConnection->invokeToCore([this, accountCore] {
|
&CoreModel::conferenceInfoReceived,
|
||||||
if (mCurrentAccountCore) {
|
[this](const std::shared_ptr<linphone::Core> &core,
|
||||||
disconnect(mCurrentAccountCore.get(), &AccountCore::registrationStateChanged, this, nullptr);
|
const std::shared_ptr<const linphone::ConferenceInfo> &conferenceInfo) {
|
||||||
disconnect(mCurrentAccountCore.get(), &AccountCore::conferenceInformationUpdated, this, nullptr);
|
lDebug() << log().arg("conference info received") << conferenceInfo->getSubject();
|
||||||
}
|
addConference(conferenceInfo->clone());
|
||||||
mCurrentAccountCore = accountCore;
|
|
||||||
if (mCurrentAccountCore) {
|
|
||||||
connect(mCurrentAccountCore.get(), &AccountCore::registrationStateChanged, this,
|
|
||||||
[this] { emit lUpdate(); });
|
|
||||||
connect(mCurrentAccountCore.get(), &AccountCore::conferenceInformationUpdated, this,
|
|
||||||
[this] { emit lUpdate(); });
|
|
||||||
}
|
|
||||||
emit lUpdate();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
mCoreModelConnection->invokeToModel([this] {
|
emit lUpdate(true);
|
||||||
auto defaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
|
|
||||||
auto accountCore = defaultAccount ? AccountCore::create(defaultAccount) : nullptr;
|
|
||||||
mCoreModelConnection->invokeToCore([this, accountCore] {
|
|
||||||
mCurrentAccountCore = accountCore;
|
|
||||||
if (mCurrentAccountCore) {
|
|
||||||
connect(mCurrentAccountCore.get(), &AccountCore::registrationStateChanged, this,
|
|
||||||
[this] { emit lUpdate(); });
|
|
||||||
connect(mCurrentAccountCore.get(), &AccountCore::conferenceInformationUpdated, this,
|
|
||||||
[this] { emit lUpdate(); });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
emit lUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConferenceInfoList::setAccountConnected(bool connected) {
|
|
||||||
if (mAccountConnected != connected) {
|
|
||||||
mAccountConnected = connected;
|
|
||||||
emit accountConnectedChanged(mAccountConnected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ConferenceInfoList::getAccountConnected() const {
|
|
||||||
return mAccountConnected;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConferenceInfoList::resetData(QList<QSharedPointer<ConferenceInfoCore>> data) {
|
void ConferenceInfoList::resetData(QList<QSharedPointer<ConferenceInfoCore>> data) {
|
||||||
|
|
@ -190,7 +129,6 @@ void ConferenceInfoList::addConference(const std::shared_ptr<linphone::Conferenc
|
||||||
return confInfo->getUri()->weakEqual(confAddr);
|
return confInfo->getUri()->weakEqual(confAddr);
|
||||||
});
|
});
|
||||||
if (haveConf == list.end()) {
|
if (haveConf == list.end()) {
|
||||||
if (confInfo->getState() == linphone::ConferenceInfo::State::Cancelled) return;
|
|
||||||
auto confInfoCore = build(confInfo);
|
auto confInfoCore = build(confInfo);
|
||||||
mCoreModelConnection->invokeToCore([this, confInfoCore] {
|
mCoreModelConnection->invokeToCore([this, confInfoCore] {
|
||||||
connectItem(confInfoCore);
|
connectItem(confInfoCore);
|
||||||
|
|
@ -235,17 +173,13 @@ int ConferenceInfoList::getCurrentDateIndex() {
|
||||||
return it == confInfoList.end() ? -1 : std::distance(confInfoList.begin(), it);
|
return it == confInfoList.end() ? -1 : std::distance(confInfoList.begin(), it);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<ConferenceInfoCore> ConferenceInfoList::getCurrentDateConfInfo(bool enableCancelledConference) {
|
QSharedPointer<ConferenceInfoCore> ConferenceInfoList::getCurrentDateConfInfo() {
|
||||||
auto today = QDate::currentDate();
|
auto today = QDate::currentDate();
|
||||||
auto confInfoList = getSharedList<ConferenceInfoCore>();
|
auto confInfoList = getSharedList<ConferenceInfoCore>();
|
||||||
QList<QSharedPointer<ConferenceInfoCore>>::iterator it;
|
QList<QSharedPointer<ConferenceInfoCore>>::iterator it;
|
||||||
if (mHaveCurrentDate) {
|
if (mHaveCurrentDate) {
|
||||||
it = std::find_if(confInfoList.begin(), confInfoList.end(),
|
it = std::find_if(confInfoList.begin(), confInfoList.end(),
|
||||||
[today, enableCancelledConference](const QSharedPointer<ConferenceInfoCore> &item) {
|
[today](const QSharedPointer<ConferenceInfoCore> &item) {
|
||||||
if (!item) return false;
|
|
||||||
if (!enableCancelledConference &&
|
|
||||||
item->getConferenceInfoState() == LinphoneEnums::ConferenceInfoState::Cancelled)
|
|
||||||
return false;
|
|
||||||
return item && item->getDateTimeUtc().date() == today;
|
return item && item->getDateTimeUtc().date() == today;
|
||||||
});
|
});
|
||||||
} else it = std::find(confInfoList.begin(), confInfoList.end(), nullptr);
|
} else it = std::find(confInfoList.begin(), confInfoList.end(), nullptr);
|
||||||
|
|
@ -302,9 +236,7 @@ QVariant ConferenceInfoList::data(const QModelIndex &index, int role) const {
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
return QVariant::fromValue(new ConferenceInfoGui(mList[row].objectCast<ConferenceInfoCore>()));
|
return QVariant::fromValue(new ConferenceInfoGui(mList[row].objectCast<ConferenceInfoCore>()));
|
||||||
} else if (role == Qt::DisplayRole + 1) {
|
} else if (role == Qt::DisplayRole + 1) {
|
||||||
auto date = mList[row].objectCast<ConferenceInfoCore>()->getDateTimeUtc();
|
return Utils::toDateMonthString(mList[row].objectCast<ConferenceInfoCore>()->getDateTimeUtc());
|
||||||
if (date.date().year() != QDate::currentDate().year()) return Utils::toDateMonthAndYearString(date);
|
|
||||||
else return Utils::toDateMonthString(date);
|
|
||||||
}
|
}
|
||||||
} else { // Dummy date
|
} else { // Dummy date
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
||||||
*
|
*
|
||||||
* This file is part of linphone-desktop
|
* This file is part of linphone-desktop
|
||||||
* (see https://www.linphone.org).
|
* (see https://www.linphone.org).
|
||||||
|
|
@ -48,32 +48,28 @@ public:
|
||||||
void updateHaveCurrentDate();
|
void updateHaveCurrentDate();
|
||||||
|
|
||||||
int getCurrentDateIndex();
|
int getCurrentDateIndex();
|
||||||
QSharedPointer<ConferenceInfoCore> getCurrentDateConfInfo(bool enableCancelledConference = false);
|
QSharedPointer<ConferenceInfoCore> getCurrentDateConfInfo();
|
||||||
|
|
||||||
QSharedPointer<ConferenceInfoCore> build(const std::shared_ptr<linphone::ConferenceInfo> &conferenceInfo);
|
QSharedPointer<ConferenceInfoCore> build(const std::shared_ptr<linphone::ConferenceInfo> &conferenceInfo);
|
||||||
void connectItem(QSharedPointer<ConferenceInfoCore> confInfoCore);
|
void connectItem(QSharedPointer<ConferenceInfoCore> confInfoCore);
|
||||||
|
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
void setAccountConnected(bool connected);
|
|
||||||
bool getAccountConnected() const;
|
|
||||||
|
|
||||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void lUpdate();
|
void lUpdate(bool isInitialization = false);
|
||||||
|
void initialized();
|
||||||
void addCurrentDateChanged();
|
void addCurrentDateChanged();
|
||||||
void haveCurrentDateChanged();
|
void haveCurrentDateChanged();
|
||||||
void currentDateIndexChanged(int index);
|
void currentDateIndexChanged(int index);
|
||||||
void confInfoInserted(QSharedPointer<ConferenceInfoCore> data);
|
void confInfoInserted(QSharedPointer<ConferenceInfoCore> data);
|
||||||
void confInfoUpdated(QSharedPointer<ConferenceInfoCore> data);
|
void confInfoUpdated(QSharedPointer<ConferenceInfoCore> data);
|
||||||
void accountConnectedChanged(bool connected);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSharedPointer<SafeConnection<ConferenceInfoList, CoreModel>> mCoreModelConnection;
|
QSharedPointer<SafeConnection<ConferenceInfoList, CoreModel>> mCoreModelConnection;
|
||||||
QSharedPointer<AccountCore> mCurrentAccountCore;
|
QSharedPointer<AccountCore> mCurrentAccountCore;
|
||||||
bool mHaveCurrentDate = false;
|
bool mHaveCurrentDate = false;
|
||||||
bool mAccountConnected = false;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
#endif // CONFERENCE_INFO_LIST_H_
|
#endif // CONFERENCE_INFO_LIST_H_
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
||||||
*
|
*
|
||||||
* This file is part of linphone-desktop
|
* This file is part of linphone-desktop
|
||||||
* (see https://www.linphone.org).
|
* (see https://www.linphone.org).
|
||||||
|
|
@ -57,26 +57,20 @@ ConferenceInfoProxy::ConferenceInfoProxy(QObject *parent) : LimitProxy(parent) {
|
||||||
if (isSignalConnected(conferenceInfoUpdatedSignal)) emit conferenceInfoUpdated(new ConferenceInfoGui(data));
|
if (isSignalConnected(conferenceInfoUpdatedSignal)) emit conferenceInfoUpdated(new ConferenceInfoGui(data));
|
||||||
},
|
},
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
connect(mList.get(), &ConferenceInfoList::accountConnectedChanged, this,
|
connect(mList.get(), &ConferenceInfoList::initialized, this, &ConferenceInfoProxy::initialized);
|
||||||
&ConferenceInfoProxy::accountConnectedChanged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConferenceInfoProxy::~ConferenceInfoProxy() {
|
ConferenceInfoProxy::~ConferenceInfoProxy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConferenceInfoProxy::haveCurrentDate() const {
|
bool ConferenceInfoProxy::haveCurrentDate() const {
|
||||||
return mList && mList->haveCurrentDate();
|
return mList->haveCurrentDate();
|
||||||
}
|
|
||||||
|
|
||||||
bool ConferenceInfoProxy::getAccountConnected() const {
|
|
||||||
return mList && mList->getAccountConnected();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConferenceInfoProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
bool ConferenceInfoProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
||||||
auto list = qobject_cast<ConferenceInfoList *>(sourceModel());
|
auto list = qobject_cast<ConferenceInfoList *>(sourceModel());
|
||||||
auto ciCore = list->getAt<ConferenceInfoCore>(sourceRow);
|
auto ciCore = list->getAt<ConferenceInfoCore>(sourceRow);
|
||||||
if (ciCore) {
|
if (ciCore) {
|
||||||
if (ciCore->getDuration() == 0) return false;
|
|
||||||
bool searchTextInSubject = false;
|
bool searchTextInSubject = false;
|
||||||
bool searchTextInParticipant = false;
|
bool searchTextInParticipant = false;
|
||||||
if (ciCore->getSubject().contains(mFilterText, Qt::CaseInsensitive)) searchTextInSubject = true;
|
if (ciCore->getSubject().contains(mFilterText, Qt::CaseInsensitive)) searchTextInSubject = true;
|
||||||
|
|
@ -105,14 +99,6 @@ void ConferenceInfoProxy::clear() {
|
||||||
mList->clearData();
|
mList->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConferenceInfoGui *ConferenceInfoProxy::getCurrentDateConfInfo(bool enableCancelledConference) {
|
|
||||||
if (mList) {
|
|
||||||
auto confInfo = mList->getCurrentDateConfInfo();
|
|
||||||
return confInfo ? new ConferenceInfoGui(confInfo) : nullptr;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ConferenceInfoProxy::loadUntil(ConferenceInfoGui *confInfo) {
|
int ConferenceInfoProxy::loadUntil(ConferenceInfoGui *confInfo) {
|
||||||
return loadUntil(confInfo ? confInfo->mCore : nullptr);
|
return loadUntil(confInfo ? confInfo->mCore : nullptr);
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +136,7 @@ bool ConferenceInfoProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft
|
||||||
auto nowDate = QDate::currentDate();
|
auto nowDate = QDate::currentDate();
|
||||||
if (!l || !r) { // sort on date
|
if (!l || !r) { // sort on date
|
||||||
auto rdate = r ? r->getDateTimeUtc().date() : QDate::currentDate();
|
auto rdate = r ? r->getDateTimeUtc().date() : QDate::currentDate();
|
||||||
return !l ? nowDate < r->getDateTimeUtc().date() : l->getDateTimeUtc().date() < nowDate;
|
return !l ? nowDate <= r->getDateTimeUtc().date() : l->getDateTimeUtc().date() < nowDate;
|
||||||
} else {
|
} else {
|
||||||
return l->getDateTimeUtc() < r->getDateTimeUtc();
|
return l->getDateTimeUtc() < r->getDateTimeUtc();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ class ConferenceInfoProxy : public LimitProxy, public AbstractObject {
|
||||||
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool haveCurrentDate READ haveCurrentDate NOTIFY haveCurrentDateChanged)
|
Q_PROPERTY(bool haveCurrentDate READ haveCurrentDate NOTIFY haveCurrentDateChanged)
|
||||||
Q_PROPERTY(bool accountConnected READ getAccountConnected NOTIFY accountConnectedChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum ConferenceInfoFiltering { None = 0, Future = 1 };
|
enum ConferenceInfoFiltering { None = 0, Future = 1 };
|
||||||
|
|
@ -44,17 +43,15 @@ public:
|
||||||
~ConferenceInfoProxy();
|
~ConferenceInfoProxy();
|
||||||
|
|
||||||
bool haveCurrentDate() const;
|
bool haveCurrentDate() const;
|
||||||
bool getAccountConnected() const;
|
|
||||||
|
|
||||||
Q_INVOKABLE void clear();
|
Q_INVOKABLE void clear();
|
||||||
Q_INVOKABLE ConferenceInfoGui *getCurrentDateConfInfo(bool enableCancelledConference = false);
|
|
||||||
Q_INVOKABLE int loadUntil(ConferenceInfoGui *confInfo);
|
Q_INVOKABLE int loadUntil(ConferenceInfoGui *confInfo);
|
||||||
int loadUntil(QSharedPointer<ConferenceInfoCore> data);
|
int loadUntil(QSharedPointer<ConferenceInfoCore> data);
|
||||||
signals:
|
signals:
|
||||||
|
void initialized();
|
||||||
void haveCurrentDateChanged();
|
void haveCurrentDateChanged();
|
||||||
void conferenceInfoCreated(ConferenceInfoGui *confInfo);
|
void conferenceInfoCreated(ConferenceInfoGui *confInfo);
|
||||||
void conferenceInfoUpdated(ConferenceInfoGui *confInfo);
|
void conferenceInfoUpdated(ConferenceInfoGui *confInfo);
|
||||||
void accountConnectedChanged(bool connected);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSharedPointer<ConferenceInfoList> mList;
|
QSharedPointer<ConferenceInfoList> mList;
|
||||||
|
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "EmojiList.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "core/chat/ChatCore.hpp"
|
|
||||||
#include "core/chat/message/content/ChatMessageContentGui.hpp"
|
|
||||||
|
|
||||||
#include <QMimeDatabase>
|
|
||||||
#include <QSharedPointer>
|
|
||||||
|
|
||||||
#include <linphone++/linphone.hh>
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(EmojiList)
|
|
||||||
|
|
||||||
QSharedPointer<EmojiList> EmojiList::create() {
|
|
||||||
auto model = QSharedPointer<EmojiList>(new EmojiList(), &QObject::deleteLater);
|
|
||||||
model->moveToThread(App::getInstance()->thread());
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmojiList::EmojiList(QObject *parent) : AbstractListProxy<Reaction>(parent) {
|
|
||||||
mustBeInMainThread(getClassName());
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
|
||||||
}
|
|
||||||
|
|
||||||
EmojiList::~EmojiList() {
|
|
||||||
mustBeInMainThread("~" + getClassName());
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<Reaction> EmojiList::getReactions() {
|
|
||||||
return mList;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmojiList::setReactions(QList<Reaction> reactions) {
|
|
||||||
resetData(reactions);
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant EmojiList::data(const QModelIndex &index, int role) const {
|
|
||||||
int row = index.row();
|
|
||||||
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
|
||||||
if (role == Qt::DisplayRole) return QVariant::fromValue(mList.at(row));
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EMOJI_LIST_H_
|
|
||||||
#define EMOJI_LIST_H_
|
|
||||||
|
|
||||||
#include "core/chat/message/ChatMessageCore.hpp"
|
|
||||||
#include "core/proxy/AbstractListProxy.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
|
||||||
#include <QLocale>
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class EmojiList : public AbstractListProxy<Reaction>, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
static QSharedPointer<EmojiList> create();
|
|
||||||
EmojiList(QObject *parent = Q_NULLPTR);
|
|
||||||
~EmojiList();
|
|
||||||
|
|
||||||
QList<Reaction> getReactions();
|
|
||||||
void setReactions(QList<Reaction> reactions);
|
|
||||||
|
|
||||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QList<Reaction> mReactions;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
/*
|
|
||||||
* MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2023 AmirHosseinCH
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "EmojiModel.hpp"
|
|
||||||
#include "core/path/Paths.hpp"
|
|
||||||
#include "tool/Constants.hpp"
|
|
||||||
|
|
||||||
EmojiModel::EmojiModel() {
|
|
||||||
QFile file(QString(":/data/emoji/emoji.json"));
|
|
||||||
auto open = file.open(QIODevice::ReadOnly);
|
|
||||||
QByteArray data = file.readAll();
|
|
||||||
file.close();
|
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data);
|
|
||||||
QJsonObject rootObj = doc.object();
|
|
||||||
for (auto category{rootObj.begin()}; category != rootObj.end(); ++category) {
|
|
||||||
emojies[category.key()] = category.value().toArray();
|
|
||||||
QJsonArray &emojiesData = emojies[category.key()];
|
|
||||||
for (auto it{emojiesData.begin()}; it != emojiesData.end(); ++it) {
|
|
||||||
QJsonObject emoji = it->toObject();
|
|
||||||
QJsonArray allKeywords = emoji.value("keywords").toArray();
|
|
||||||
for (auto k{allKeywords.begin()}; k != allKeywords.end(); ++k) {
|
|
||||||
keywords[k->toString()].append(emoji);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int EmojiModel::count(QString category) {
|
|
||||||
return emojies[category].size();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString EmojiModel::path(QString category, int index, int skinColor) {
|
|
||||||
QJsonObject emoji = emojies[category][index].toObject();
|
|
||||||
if (emoji.contains("types") && skinColor != -1) {
|
|
||||||
QJsonArray types = emoji.value("types").toArray();
|
|
||||||
return mIconsPath + types[skinColor].toString() + mIconsType;
|
|
||||||
} else return mIconsPath + emoji.value("code").toString() + mIconsType;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<QString> EmojiModel::search(QString searchKey, int skinColor) {
|
|
||||||
bool foundFirstItem{false};
|
|
||||||
QVector<QString> searchResult;
|
|
||||||
for (auto it{keywords.begin()}; it != keywords.end(); ++it) {
|
|
||||||
if (it.key().startsWith(searchKey)) {
|
|
||||||
QVector<QJsonObject> &emojiesData{it.value()};
|
|
||||||
for (auto emoji{emojiesData.begin()}; emoji != emojiesData.end(); ++emoji) {
|
|
||||||
if (emoji->contains("types") && skinColor != -1) {
|
|
||||||
QJsonArray types = emoji->value("types").toArray();
|
|
||||||
QString path = mIconsPath + types[skinColor].toString() + mIconsType;
|
|
||||||
if (!searchResult.contains(path)) searchResult.append(path);
|
|
||||||
} else {
|
|
||||||
QString path = mIconsPath + emoji->value("code").toString() + mIconsType;
|
|
||||||
if (!searchResult.contains(path)) searchResult.append(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foundFirstItem = true;
|
|
||||||
} else if (foundFirstItem) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return searchResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmojiModel::setIconsPath(QString path) {
|
|
||||||
mIconsPath = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmojiModel::setIconsType(QString type) {
|
|
||||||
mIconsType = type;
|
|
||||||
}
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
/*
|
|
||||||
* MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2023 AmirHosseinCH
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EMOJIMODEL_H
|
|
||||||
#define EMOJIMODEL_H
|
|
||||||
|
|
||||||
#include <QFile>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
class EmojiModel : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(QString iconsPath WRITE setIconsPath MEMBER mIconsPath)
|
|
||||||
Q_PROPERTY(QString iconsType WRITE setIconsType MEMBER mIconsType)
|
|
||||||
public:
|
|
||||||
EmojiModel();
|
|
||||||
void setIconsPath(QString);
|
|
||||||
void setIconsType(QString);
|
|
||||||
public slots:
|
|
||||||
int count(QString);
|
|
||||||
QString path(QString, int, int = -1);
|
|
||||||
QVector<QString> search(QString, int = -1);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString mIconsPath;
|
|
||||||
QString mIconsType;
|
|
||||||
QMap<QString, QJsonArray> emojies;
|
|
||||||
QMap<QString, QVector<QJsonObject>> keywords;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "EmojiProxy.hpp"
|
|
||||||
#include "EmojiList.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
// #include "core/chat/message/ChatMessageGui.hpp"
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(EmojiProxy)
|
|
||||||
|
|
||||||
EmojiProxy::EmojiProxy(QObject *parent) : LimitProxy(parent) {
|
|
||||||
mList = EmojiList::create();
|
|
||||||
setSourceModel(mList.get());
|
|
||||||
connect(mList.get(), &EmojiList::modelReset, this, &EmojiProxy::reactionsChanged);
|
|
||||||
connect(this, &EmojiProxy::filterChanged, this, [this] { invalidate(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
EmojiProxy::~EmojiProxy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<Reaction> EmojiProxy::getReactions() {
|
|
||||||
return mList->getReactions();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmojiProxy::setReactions(QList<Reaction> reactions) {
|
|
||||||
mList->setReactions(reactions);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString EmojiProxy::getFilter() const {
|
|
||||||
return mFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmojiProxy::setFilter(QString filter) {
|
|
||||||
if (mFilter != filter) {
|
|
||||||
mFilter = filter;
|
|
||||||
emit filterChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmojiProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
|
||||||
auto emoji = mList->getAt(sourceRow);
|
|
||||||
return emoji.mBody.contains(mFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmojiProxy::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EMOJI_PROXY_H_
|
|
||||||
#define EMOJI_PROXY_H_
|
|
||||||
|
|
||||||
#include "core/chat/message/ChatMessageCore.hpp"
|
|
||||||
#include "core/emoji/EmojiModel.hpp"
|
|
||||||
#include "core/proxy/LimitProxy.hpp"
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class EmojiList;
|
|
||||||
|
|
||||||
class EmojiProxy : public LimitProxy, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(QList<Reaction> reactions READ getReactions WRITE setReactions NOTIFY reactionsChanged)
|
|
||||||
Q_PROPERTY(QString filter READ getFilter WRITE setFilter NOTIFY filterChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
EmojiProxy(QObject *parent = Q_NULLPTR);
|
|
||||||
~EmojiProxy();
|
|
||||||
|
|
||||||
QList<Reaction> getReactions();
|
|
||||||
void setReactions(QList<Reaction> reactions);
|
|
||||||
|
|
||||||
QString getFilter() const;
|
|
||||||
void setFilter(QString filter);
|
|
||||||
|
|
||||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
|
||||||
bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void reactionsChanged();
|
|
||||||
void filterChanged();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QString mFilter;
|
|
||||||
QSharedPointer<EmojiList> mList;
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <QtDebug>
|
|
||||||
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "model/core/CoreModel.hpp"
|
|
||||||
#include "model/setting/SettingsModel.hpp"
|
|
||||||
|
|
||||||
#include "AbstractEventCountNotifier.hpp"
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(AbstractEventCountNotifier)
|
|
||||||
|
|
||||||
AbstractEventCountNotifier::AbstractEventCountNotifier(QObject *parent) : QObject(parent) {
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractEventCountNotifier::getEventCount() const {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
auto coreModel = CoreModel::getInstance();
|
|
||||||
int count = coreModel->getCore()->getMissedCallsCount();
|
|
||||||
if (SettingsModel::getInstance()->getStandardChatEnabled() || SettingsModel::getInstance()->getSecureChatEnabled())
|
|
||||||
count += coreModel->getCore()->getUnreadChatMessageCountFromActiveLocals();
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractEventCountNotifier::getCurrentEventCount() const {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
auto coreModel = CoreModel::getInstance();
|
|
||||||
int count = coreModel->getCore()->getMissedCallsCount();
|
|
||||||
bool filtered = SettingsModel::getInstance()->isSystrayNotificationFiltered();
|
|
||||||
bool global = SettingsModel::getInstance()->isSystrayNotificationGlobal();
|
|
||||||
// if (global && !filtered)
|
|
||||||
if (true) return getEventCount();
|
|
||||||
else {
|
|
||||||
auto currentAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
|
|
||||||
if (currentAccount) {
|
|
||||||
count += currentAccount->getUnreadChatMessageCount();
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ABSTRACT_EVENT_COUNT_NOTIFIER_H_
|
|
||||||
#define ABSTRACT_EVENT_COUNT_NOTIFIER_H_
|
|
||||||
|
|
||||||
#include <QHash>
|
|
||||||
#include <QObject>
|
|
||||||
#include <QPair>
|
|
||||||
#include <QSystemTrayIcon>
|
|
||||||
|
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
namespace linphone {
|
|
||||||
class ChatMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
class CallModel;
|
|
||||||
class ChatRoomModel;
|
|
||||||
class HistoryModel;
|
|
||||||
|
|
||||||
class AbstractEventCountNotifier : public QObject, public AbstractObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
AbstractEventCountNotifier(QObject *parent = Q_NULLPTR);
|
|
||||||
|
|
||||||
int getEventCount() const; // global
|
|
||||||
int getCurrentEventCount() const; // Current account
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void notifyEventCount(int n) = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ABSTRACT_EVENT_COUNT_NOTIFIER_H_
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EVENT_COUNT_NOTIFIER_MAC_OS_H_
|
|
||||||
#define EVENT_COUNT_NOTIFIER_MAC_OS_H_
|
|
||||||
|
|
||||||
#include "AbstractEventCountNotifier.hpp"
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
extern "C" void notifyEventCountMacOs(int n);
|
|
||||||
|
|
||||||
class EventCountNotifier : public AbstractEventCountNotifier {
|
|
||||||
public:
|
|
||||||
EventCountNotifier(QObject *parent = Q_NULLPTR) : AbstractEventCountNotifier(parent) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void notifyEventCount(int n) override {
|
|
||||||
notifyEventCountMacOs(n);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EVENT_COUNT_NOTIFIER_MAC_OS_H_
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* EventCountNotifierMacOs.m
|
|
||||||
* Copyright (C) 2017-2018 Belledonne Communications, Grenoble, France
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* Created on: June 30, 2017
|
|
||||||
* Author: Ghislain MARY
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
void notifyEventCountMacOs (int n) {
|
|
||||||
NSString *badgeStr = (n > 0) ? [NSString stringWithFormat:@"%d", n] : @"";
|
|
||||||
[[NSApp dockTile] setBadgeLabel:badgeStr];
|
|
||||||
}
|
|
||||||
|
|
@ -1,134 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QSvgRenderer>
|
|
||||||
#include <QSystemTrayIcon>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QWindow>
|
|
||||||
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "model/core/CoreModel.hpp"
|
|
||||||
#include "model/setting/SettingsModel.hpp"
|
|
||||||
#include "tool/Constants.hpp"
|
|
||||||
#include "tool/Utils.hpp"
|
|
||||||
|
|
||||||
#include "EventCountNotifierSystemTrayIcon.hpp"
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
constexpr int IconWidth = 256;
|
|
||||||
constexpr int IconHeight = 256;
|
|
||||||
|
|
||||||
constexpr int IconCounterBackgroundRadius = 100;
|
|
||||||
constexpr int IconCounterBlinkInterval = 1000;
|
|
||||||
constexpr int IconCounterTextPixelSize = 144;
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(EventCountNotifier)
|
|
||||||
|
|
||||||
QSharedPointer<EventCountNotifier> EventCountNotifier::create(QObject *parent) {
|
|
||||||
auto sharedPointer = QSharedPointer<EventCountNotifier>(new EventCountNotifier(parent), &QObject::deleteLater);
|
|
||||||
sharedPointer->setSelf(sharedPointer);
|
|
||||||
sharedPointer->moveToThread(App::getInstance()->thread());
|
|
||||||
return sharedPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventCountNotifier::EventCountNotifier(QObject *parent) : AbstractEventCountNotifier(parent) {
|
|
||||||
QSvgRenderer renderer((QString(Constants::WindowIconPath)));
|
|
||||||
if (!renderer.isValid()) qFatal("Invalid SVG Image.");
|
|
||||||
|
|
||||||
QPixmap buf(IconWidth, IconHeight);
|
|
||||||
buf.fill(QColor(Qt::transparent));
|
|
||||||
|
|
||||||
QPainter painter(&buf);
|
|
||||||
renderer.render(&painter);
|
|
||||||
|
|
||||||
mBuf = new QPixmap(buf);
|
|
||||||
mBufWithCounter = new QPixmap();
|
|
||||||
|
|
||||||
mBlinkTimer = new QTimer(this);
|
|
||||||
mBlinkTimer->setInterval(IconCounterBlinkInterval);
|
|
||||||
connect(mBlinkTimer, &QTimer::timeout, this, &EventCountNotifier::update);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventCountNotifier::setSelf(QSharedPointer<EventCountNotifier> me) {
|
|
||||||
}
|
|
||||||
|
|
||||||
EventCountNotifier::~EventCountNotifier() {
|
|
||||||
delete mBuf;
|
|
||||||
delete mBufWithCounter;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void EventCountNotifier::notifyEventCount(int n) {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
n = n > 99 ? 99 : n;
|
|
||||||
QSystemTrayIcon *sysTrayIcon = App::getInstance()->getSystemTrayIcon();
|
|
||||||
if (!sysTrayIcon) return;
|
|
||||||
|
|
||||||
if (!n) {
|
|
||||||
mBlinkTimer->stop();
|
|
||||||
sysTrayIcon->setIcon(QIcon(*mBuf));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
*mBufWithCounter = *mBuf;
|
|
||||||
QPainter p(mBufWithCounter);
|
|
||||||
|
|
||||||
const int width = mBufWithCounter->width();
|
|
||||||
const int height = mBufWithCounter->height();
|
|
||||||
|
|
||||||
// Draw background.
|
|
||||||
{
|
|
||||||
p.setBrush(QColor(Utils::getDefaultStyleColor("main1_100")));
|
|
||||||
p.drawEllipse(QPointF(width / 2, height / 2), IconCounterBackgroundRadius, IconCounterBackgroundRadius);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw text.
|
|
||||||
{
|
|
||||||
QFont font = p.font();
|
|
||||||
font.setPixelSize(IconCounterTextPixelSize);
|
|
||||||
|
|
||||||
p.setFont(font);
|
|
||||||
p.setPen(QPen(QColor(Utils::getDefaultStyleColor("main1_500_main"))));
|
|
||||||
p.drawText(QRect(0, 0, width, height), Qt::AlignCenter, QString::number(n));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change counter.
|
|
||||||
mBlinkTimer->stop();
|
|
||||||
auto coreModel = CoreModel::getInstance();
|
|
||||||
if (!coreModel->isInitialized() || SettingsModel::getInstance()->isSystrayNotificationBlinkEnabled())
|
|
||||||
mBlinkTimer->start();
|
|
||||||
mDisplayCounter = true;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventCountNotifier::update() {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
QSystemTrayIcon *sysTrayIcon = App::getInstance()->getSystemTrayIcon();
|
|
||||||
if (sysTrayIcon) {
|
|
||||||
sysTrayIcon->setIcon(QIcon(mDisplayCounter ? *mBufWithCounter : *mBuf));
|
|
||||||
}
|
|
||||||
mDisplayCounter = !mDisplayCounter;
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EVENT_COUNT_NOTIFIER_SYSTEM_TRAY_ICON_H_
|
|
||||||
#define EVENT_COUNT_NOTIFIER_SYSTEM_TRAY_ICON_H_
|
|
||||||
|
|
||||||
#include "AbstractEventCountNotifier.hpp"
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class QTimer;
|
|
||||||
|
|
||||||
class EventCountNotifier : public AbstractEventCountNotifier {
|
|
||||||
public:
|
|
||||||
static QSharedPointer<EventCountNotifier> create(QObject *parent = Q_NULLPTR);
|
|
||||||
EventCountNotifier(QObject *parent = Q_NULLPTR);
|
|
||||||
void setSelf(QSharedPointer<EventCountNotifier> me);
|
|
||||||
~EventCountNotifier();
|
|
||||||
|
|
||||||
void notifyEventCount(int n) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const QPixmap *mBuf = nullptr;
|
|
||||||
QPixmap *mBufWithCounter = nullptr;
|
|
||||||
QTimer *mBlinkTimer = nullptr;
|
|
||||||
bool mDisplayCounter = false;
|
|
||||||
QSharedPointer<SafeConnection<EventCountNotifier, CoreModel>> mCoreModelConnection;
|
|
||||||
void update();
|
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EVENT_COUNT_NOTIFIER_SYSTEM_TRAY_ICON_H_
|
|
||||||
|
|
@ -48,9 +48,8 @@ FriendCore::FriendCore(const std::shared_ptr<linphone::Friend> &contact, bool is
|
||||||
mustBeInLinphoneThread(getClassName());
|
mustBeInLinphoneThread(getClassName());
|
||||||
mFriendModel = Utils::makeQObject_ptr<FriendModel>(contact);
|
mFriendModel = Utils::makeQObject_ptr<FriendModel>(contact);
|
||||||
mFriendModel->setSelf(mFriendModel);
|
mFriendModel->setSelf(mFriendModel);
|
||||||
auto presence = mFriendModel->getPresence(contact);
|
mConsolidatedPresence = LinphoneEnums::fromLinphone(contact->getConsolidatedPresence());
|
||||||
auto note = mFriendModel->getPresenceNote(contact);
|
mPresenceTimestamp = mFriendModel->getPresenceTimestamp();
|
||||||
App::postCoreAsync([this, presence, note]() { setPresence(presence, note); });
|
|
||||||
mPictureUri = Utils::coreStringToAppString(contact->getPhoto());
|
mPictureUri = Utils::coreStringToAppString(contact->getPhoto());
|
||||||
mFullName = mFriendModel->getFullName();
|
mFullName = mFriendModel->getFullName();
|
||||||
auto defaultAddress = contact->getAddress();
|
auto defaultAddress = contact->getAddress();
|
||||||
|
|
@ -66,7 +65,7 @@ FriendCore::FriendCore(const std::shared_ptr<linphone::Friend> &contact, bool is
|
||||||
auto addresses = contact->getAddresses();
|
auto addresses = contact->getAddresses();
|
||||||
for (auto &address : addresses) {
|
for (auto &address : addresses) {
|
||||||
mAddressList.append(Utils::createFriendAddressVariant(
|
mAddressList.append(Utils::createFriendAddressVariant(
|
||||||
tr("sip_address"), Utils::coreStringToAppString(address->asStringUriOnly())));
|
tr("sip_address"), Utils::coreStringToAppString(address->asStringUriOnly())));
|
||||||
}
|
}
|
||||||
mDefaultAddress = defaultAddress ? Utils::coreStringToAppString(defaultAddress->asStringUriOnly()) : QString();
|
mDefaultAddress = defaultAddress ? Utils::coreStringToAppString(defaultAddress->asStringUriOnly()) : QString();
|
||||||
mDefaultFullAddress = defaultAddress ? Utils::coreStringToAppString(defaultAddress->asString()) : QString();
|
mDefaultFullAddress = defaultAddress ? Utils::coreStringToAppString(defaultAddress->asString()) : QString();
|
||||||
|
|
@ -91,8 +90,7 @@ FriendCore::FriendCore(const std::shared_ptr<linphone::Friend> &contact, bool is
|
||||||
mStarred = contact->getStarred();
|
mStarred = contact->getStarred();
|
||||||
mIsSaved = true;
|
mIsSaved = true;
|
||||||
mIsStored = isStored;
|
mIsStored = isStored;
|
||||||
mIsLdap = ToolModel::friendIsInFriendList(ToolModel::getLdapFriendList(), contact) ||
|
mIsLdap = ToolModel::friendIsInFriendList(ToolModel::getLdapFriendList(), contact);
|
||||||
(sourceFlags & (int)linphone::MagicSearch::Source::LdapServers) != 0;
|
|
||||||
mIsCardDAV = (sourceFlags & (int)linphone::MagicSearch::Source::RemoteCardDAV) != 0;
|
mIsCardDAV = (sourceFlags & (int)linphone::MagicSearch::Source::RemoteCardDAV) != 0;
|
||||||
mIsAppFriend = ToolModel::friendIsInFriendList(ToolModel::getAppFriendList(), contact);
|
mIsAppFriend = ToolModel::friendIsInFriendList(ToolModel::getAppFriendList(), contact);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -144,7 +142,8 @@ void FriendCore::setSelf(QSharedPointer<FriendCore> me) {
|
||||||
mFriendModelConnection->makeConnectToModel(
|
mFriendModelConnection->makeConnectToModel(
|
||||||
&FriendModel::removed, [this]() { mFriendModelConnection->invokeToCore([this]() { removed(this); }); });
|
&FriendModel::removed, [this]() { mFriendModelConnection->invokeToCore([this]() { removed(this); }); });
|
||||||
mFriendModelConnection->makeConnectToModel(
|
mFriendModelConnection->makeConnectToModel(
|
||||||
&FriendModel::presenceReceived, [this](LinphoneEnums::Presence presence, QString presenceNote) {
|
&FriendModel::presenceReceived,
|
||||||
|
[this](LinphoneEnums::ConsolidatedPresence consolidatedPresence, QDateTime presenceTimestamp) {
|
||||||
auto devices = mFriendModel->getDevices();
|
auto devices = mFriendModel->getDevices();
|
||||||
QVariantList devicesList;
|
QVariantList devicesList;
|
||||||
for (auto &device : devices) {
|
for (auto &device : devices) {
|
||||||
|
|
@ -154,11 +153,14 @@ void FriendCore::setSelf(QSharedPointer<FriendCore> me) {
|
||||||
Utils::coreStringToAppString(device->getAddress()->asString()),
|
Utils::coreStringToAppString(device->getAddress()->asString()),
|
||||||
LinphoneEnums::fromLinphone(device->getSecurityLevel())));
|
LinphoneEnums::fromLinphone(device->getSecurityLevel())));
|
||||||
}
|
}
|
||||||
mFriendModelConnection->invokeToCore([this, presence, devicesList, presenceNote]() {
|
mFriendModelConnection->invokeToCore(
|
||||||
setPresence(presence, presenceNote);
|
[this, consolidatedPresence, presenceTimestamp, devicesList]() {
|
||||||
setDevices(devicesList);
|
setConsolidatedPresence(consolidatedPresence);
|
||||||
updateVerifiedDevicesCount();
|
setPresenceTimestamp(presenceTimestamp);
|
||||||
});
|
|
||||||
|
setDevices(devicesList);
|
||||||
|
updateVerifiedDevicesCount();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
mFriendModelConnection->makeConnectToModel(&FriendModel::pictureUriChanged, [this](const QString &uri) {
|
mFriendModelConnection->makeConnectToModel(&FriendModel::pictureUriChanged, [this](const QString &uri) {
|
||||||
mFriendModelConnection->invokeToCore([this, uri]() { this->onPictureUriChanged(uri); });
|
mFriendModelConnection->invokeToCore([this, uri]() { this->onPictureUriChanged(uri); });
|
||||||
|
|
@ -186,7 +188,7 @@ void FriendCore::setSelf(QSharedPointer<FriendCore> me) {
|
||||||
QList<QVariant> addr;
|
QList<QVariant> addr;
|
||||||
for (auto &num : numbers) {
|
for (auto &num : numbers) {
|
||||||
addr.append(Utils::createFriendAddressVariant(
|
addr.append(Utils::createFriendAddressVariant(
|
||||||
tr("sip_address"), Utils::coreStringToAppString(num->asStringUriOnly())));
|
tr("sip_address"), Utils::coreStringToAppString(num->asStringUriOnly())));
|
||||||
}
|
}
|
||||||
mFriendModelConnection->invokeToCore([this, addr]() { resetPhoneNumbers(addr); });
|
mFriendModelConnection->invokeToCore([this, addr]() { resetPhoneNumbers(addr); });
|
||||||
});
|
});
|
||||||
|
|
@ -417,10 +419,9 @@ void FriendCore::appendAddress(const QString &addr) {
|
||||||
QString interpretedFullAddress = linphoneAddr ? Utils::coreStringToAppString(linphoneAddr->asString()) : "";
|
QString interpretedFullAddress = linphoneAddr ? Utils::coreStringToAppString(linphoneAddr->asString()) : "";
|
||||||
QString interpretedAddress = linphoneAddr ? Utils::coreStringToAppString(linphoneAddr->asStringUriOnly()) : "";
|
QString interpretedAddress = linphoneAddr ? Utils::coreStringToAppString(linphoneAddr->asStringUriOnly()) : "";
|
||||||
mCoreModelConnection->invokeToCore([this, interpretedAddress, interpretedFullAddress]() {
|
mCoreModelConnection->invokeToCore([this, interpretedAddress, interpretedFullAddress]() {
|
||||||
if (interpretedAddress.isEmpty())
|
if (interpretedAddress.isEmpty()) Utils::showInformationPopup(tr("information_popup_error_title"),
|
||||||
Utils::showInformationPopup(tr("information_popup_error_title"),
|
//: "Adresse invalide"
|
||||||
//: "Adresse invalide"
|
tr("information_popup_invalid_address_message"), false);
|
||||||
tr("information_popup_invalid_address_message"), false);
|
|
||||||
else {
|
else {
|
||||||
mAddressList.append(Utils::createFriendAddressVariant(tr("sip_address"), interpretedAddress));
|
mAddressList.append(Utils::createFriendAddressVariant(tr("sip_address"), interpretedAddress));
|
||||||
if (mDefaultFullAddress.isEmpty()) mDefaultFullAddress = interpretedFullAddress;
|
if (mDefaultFullAddress.isEmpty()) mDefaultFullAddress = interpretedFullAddress;
|
||||||
|
|
@ -506,6 +507,30 @@ void FriendCore::setDefaultAddress(const QString &address) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LinphoneEnums::ConsolidatedPresence FriendCore::getConsolidatedPresence() const {
|
||||||
|
return mConsolidatedPresence;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FriendCore::setConsolidatedPresence(LinphoneEnums::ConsolidatedPresence presence) {
|
||||||
|
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
||||||
|
if (mConsolidatedPresence != presence) {
|
||||||
|
mConsolidatedPresence = presence;
|
||||||
|
emit consolidatedPresenceChanged(mConsolidatedPresence);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDateTime FriendCore::getPresenceTimestamp() const {
|
||||||
|
return mPresenceTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FriendCore::setPresenceTimestamp(QDateTime presenceTimestamp) {
|
||||||
|
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
||||||
|
if (mPresenceTimestamp != presenceTimestamp) {
|
||||||
|
mPresenceTimestamp = presenceTimestamp;
|
||||||
|
emit presenceTimestampChanged(mPresenceTimestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString FriendCore::getPictureUri() const {
|
QString FriendCore::getPictureUri() const {
|
||||||
return mPictureUri;
|
return mPictureUri;
|
||||||
}
|
}
|
||||||
|
|
@ -587,8 +612,8 @@ void FriendCore::writeFromModel(const std::shared_ptr<FriendModel> &model) {
|
||||||
|
|
||||||
QList<QVariant> addresses;
|
QList<QVariant> addresses;
|
||||||
for (auto &addr : model->getAddresses()) {
|
for (auto &addr : model->getAddresses()) {
|
||||||
addresses.append(Utils::createFriendAddressVariant(tr("sip_address"),
|
addresses.append(
|
||||||
Utils::coreStringToAppString(addr->asStringUriOnly())));
|
Utils::createFriendAddressVariant(tr("sip_address"), Utils::coreStringToAppString(addr->asStringUriOnly())));
|
||||||
}
|
}
|
||||||
mAddressList = addresses;
|
mAddressList = addresses;
|
||||||
mDefaultAddress = model->getDefaultAddress();
|
mDefaultAddress = model->getDefaultAddress();
|
||||||
|
|
@ -734,29 +759,3 @@ bool FriendCore::getReadOnly() const {
|
||||||
std::shared_ptr<FriendModel> FriendCore::getFriendModel() {
|
std::shared_ptr<FriendModel> FriendCore::getFriendModel() {
|
||||||
return mFriendModel;
|
return mFriendModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FriendCore::setPresence(LinphoneEnums::Presence presence, QString presenceNote) {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
bool notify = false;
|
|
||||||
if (presence != mPresence) {
|
|
||||||
mPresence = presence;
|
|
||||||
notify = true;
|
|
||||||
}
|
|
||||||
if (presenceNote != mPresenceNote) {
|
|
||||||
mPresenceNote = presenceNote;
|
|
||||||
notify = true;
|
|
||||||
}
|
|
||||||
if (notify) emit presenceChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
QUrl FriendCore::getPresenceIcon() {
|
|
||||||
return Utils::getPresenceIcon(mPresence);
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor FriendCore::getPresenceColor() {
|
|
||||||
return Utils::getPresenceColor(mPresence);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString FriendCore::getPresenceStatus() {
|
|
||||||
return Utils::getPresenceStatus(mPresence);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@
|
||||||
#include "tool/thread/SafeSharedPointer.hpp"
|
#include "tool/thread/SafeSharedPointer.hpp"
|
||||||
#include <linphone++/linphone.hh>
|
#include <linphone++/linphone.hh>
|
||||||
|
|
||||||
#include <QColor>
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QMap>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
|
@ -63,11 +63,9 @@ class FriendCore : public QObject, public AbstractObject {
|
||||||
Q_PROPERTY(QString defaultAddress READ getDefaultAddress WRITE setDefaultAddress NOTIFY defaultAddressChanged)
|
Q_PROPERTY(QString defaultAddress READ getDefaultAddress WRITE setDefaultAddress NOTIFY defaultAddressChanged)
|
||||||
Q_PROPERTY(QString defaultFullAddress READ getDefaultFullAddress WRITE setDefaultFullAddress NOTIFY
|
Q_PROPERTY(QString defaultFullAddress READ getDefaultFullAddress WRITE setDefaultFullAddress NOTIFY
|
||||||
defaultFullAddressChanged)
|
defaultFullAddressChanged)
|
||||||
Q_PROPERTY(LinphoneEnums::Presence presence MEMBER mPresence NOTIFY presenceChanged)
|
Q_PROPERTY(QDateTime presenceTimestamp READ getPresenceTimestamp NOTIFY presenceTimestampChanged)
|
||||||
Q_PROPERTY(QUrl presenceIcon READ getPresenceIcon NOTIFY presenceChanged)
|
Q_PROPERTY(LinphoneEnums::ConsolidatedPresence consolidatedPresence READ getConsolidatedPresence NOTIFY
|
||||||
Q_PROPERTY(QColor presenceColor READ getPresenceColor NOTIFY presenceChanged)
|
consolidatedPresenceChanged)
|
||||||
Q_PROPERTY(QString presenceStatus READ getPresenceStatus NOTIFY presenceChanged)
|
|
||||||
Q_PROPERTY(QString presenceNote MEMBER mPresenceNote NOTIFY presenceChanged)
|
|
||||||
Q_PROPERTY(bool isSaved READ getIsSaved NOTIFY isSavedChanged)
|
Q_PROPERTY(bool isSaved READ getIsSaved NOTIFY isSavedChanged)
|
||||||
Q_PROPERTY(bool isStored READ getIsStored NOTIFY isStoredChanged)
|
Q_PROPERTY(bool isStored READ getIsStored NOTIFY isStoredChanged)
|
||||||
Q_PROPERTY(QString pictureUri READ getPictureUri WRITE setPictureUri NOTIFY pictureUriChanged)
|
Q_PROPERTY(QString pictureUri READ getPictureUri WRITE setPictureUri NOTIFY pictureUriChanged)
|
||||||
|
|
@ -132,6 +130,12 @@ public:
|
||||||
void setDevices(QVariantList devices);
|
void setDevices(QVariantList devices);
|
||||||
Q_INVOKABLE LinphoneEnums::SecurityLevel getSecurityLevelForAddress(const QString &address) const;
|
Q_INVOKABLE LinphoneEnums::SecurityLevel getSecurityLevelForAddress(const QString &address) const;
|
||||||
|
|
||||||
|
LinphoneEnums::ConsolidatedPresence getConsolidatedPresence() const;
|
||||||
|
void setConsolidatedPresence(LinphoneEnums::ConsolidatedPresence presence);
|
||||||
|
|
||||||
|
QDateTime getPresenceTimestamp() const;
|
||||||
|
void setPresenceTimestamp(QDateTime presenceTimestamp);
|
||||||
|
|
||||||
bool getIsSaved() const;
|
bool getIsSaved() const;
|
||||||
void setIsSaved(bool isSaved);
|
void setIsSaved(bool isSaved);
|
||||||
|
|
||||||
|
|
@ -142,6 +146,8 @@ public:
|
||||||
void setPictureUri(const QString &uri);
|
void setPictureUri(const QString &uri);
|
||||||
void onPictureUriChanged(QString uri);
|
void onPictureUriChanged(QString uri);
|
||||||
|
|
||||||
|
void onPresenceReceived(LinphoneEnums::ConsolidatedPresence consolidatedPresence, QDateTime presenceTimestamp);
|
||||||
|
|
||||||
bool isLdap() const;
|
bool isLdap() const;
|
||||||
bool isAppFriend() const;
|
bool isAppFriend() const;
|
||||||
bool isCardDAV() const;
|
bool isCardDAV() const;
|
||||||
|
|
@ -153,10 +159,6 @@ public:
|
||||||
Q_INVOKABLE void save();
|
Q_INVOKABLE void save();
|
||||||
Q_INVOKABLE void undo();
|
Q_INVOKABLE void undo();
|
||||||
|
|
||||||
QColor getPresenceColor();
|
|
||||||
QString getPresenceStatus();
|
|
||||||
QUrl getPresenceIcon();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void resetPhoneNumbers(QList<QVariant> newList);
|
void resetPhoneNumbers(QList<QVariant> newList);
|
||||||
void resetAddresses(QList<QVariant> newList);
|
void resetAddresses(QList<QVariant> newList);
|
||||||
|
|
@ -171,6 +173,8 @@ signals:
|
||||||
void addressChanged();
|
void addressChanged();
|
||||||
void organizationChanged();
|
void organizationChanged();
|
||||||
void jobChanged();
|
void jobChanged();
|
||||||
|
void consolidatedPresenceChanged(LinphoneEnums::ConsolidatedPresence level);
|
||||||
|
void presenceTimestampChanged(QDateTime presenceTimestamp);
|
||||||
void pictureUriChanged();
|
void pictureUriChanged();
|
||||||
void saved();
|
void saved();
|
||||||
void isSavedChanged(bool isSaved);
|
void isSavedChanged(bool isSaved);
|
||||||
|
|
@ -182,16 +186,13 @@ signals:
|
||||||
void devicesChanged();
|
void devicesChanged();
|
||||||
void verifiedDevicesChanged();
|
void verifiedDevicesChanged();
|
||||||
void lSetStarred(bool starred);
|
void lSetStarred(bool starred);
|
||||||
void presenceChanged();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void writeIntoModel(std::shared_ptr<FriendModel> model) const;
|
void writeIntoModel(std::shared_ptr<FriendModel> model) const;
|
||||||
void writeFromModel(const std::shared_ptr<FriendModel> &model);
|
void writeFromModel(const std::shared_ptr<FriendModel> &model);
|
||||||
|
|
||||||
LinphoneEnums::Presence mPresence = LinphoneEnums::Presence::Undefined;
|
LinphoneEnums::ConsolidatedPresence mConsolidatedPresence = LinphoneEnums::ConsolidatedPresence::Offline;
|
||||||
QColor mPresenceColor;
|
QDateTime mPresenceTimestamp;
|
||||||
QString mPresenceStatus;
|
|
||||||
QString mPresenceNote = "";
|
|
||||||
QString mGivenName;
|
QString mGivenName;
|
||||||
QString mFamilyName;
|
QString mFamilyName;
|
||||||
QString mFullName;
|
QString mFullName;
|
||||||
|
|
@ -213,9 +214,6 @@ protected:
|
||||||
QSharedPointer<SafeConnection<FriendCore, FriendModel>> mFriendModelConnection;
|
QSharedPointer<SafeConnection<FriendCore, FriendModel>> mFriendModelConnection;
|
||||||
QSharedPointer<SafeConnection<FriendCore, CoreModel>> mCoreModelConnection;
|
QSharedPointer<SafeConnection<FriendCore, CoreModel>> mCoreModelConnection;
|
||||||
|
|
||||||
private:
|
|
||||||
void setPresence(LinphoneEnums::Presence presence, QString presenceNote);
|
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,27 +64,22 @@ void LoginPage::login(const QString &username,
|
||||||
const QString &password,
|
const QString &password,
|
||||||
QString displayName,
|
QString displayName,
|
||||||
QString domain,
|
QString domain,
|
||||||
LinphoneEnums::TransportType transportType,
|
LinphoneEnums::TransportType transportType) {
|
||||||
QString registrarUri,
|
|
||||||
QString outboundProxyAddress,
|
|
||||||
QString connectionId) {
|
|
||||||
setErrorMessage("");
|
setErrorMessage("");
|
||||||
App::postModelAsync([=]() {
|
App::postModelAsync([=]() {
|
||||||
// Create on Model thread.
|
// Create on Model thread.
|
||||||
AccountManager *accountManager = new AccountManager();
|
AccountManager *accountManager = new AccountManager();
|
||||||
connect(accountManager, &AccountManager::registrationStateChanged, this,
|
connect(accountManager, &AccountManager::registrationStateChanged, this,
|
||||||
[accountManager, this](linphone::RegistrationState state, linphone::Reason reason,
|
[accountManager, this](linphone::RegistrationState state, QString message) mutable {
|
||||||
QString message) mutable {
|
|
||||||
// View thread
|
// View thread
|
||||||
setRegistrationState(state);
|
setRegistrationState(state);
|
||||||
mBadIds = reason == linphone::Reason::Forbidden;
|
|
||||||
emit reasonChanged();
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case linphone::RegistrationState::Failed: {
|
case linphone::RegistrationState::Failed: {
|
||||||
if (message.isEmpty())
|
if (message.isEmpty())
|
||||||
//: Erreur durant la connexion, veuillez vérifier vos paramètres
|
//: Erreur durant la connexion
|
||||||
setErrorMessage(tr("default_account_connection_state_error_toast"));
|
setErrorMessage(tr("default_account_connection_state_error_toast"));
|
||||||
else setErrorMessage(message);
|
else
|
||||||
|
setErrorMessage(message);
|
||||||
if (accountManager) {
|
if (accountManager) {
|
||||||
accountManager->deleteLater();
|
accountManager->deleteLater();
|
||||||
accountManager = nullptr;
|
accountManager = nullptr;
|
||||||
|
|
@ -115,9 +110,9 @@ void LoginPage::login(const QString &username,
|
||||||
|
|
||||||
QString error;
|
QString error;
|
||||||
if (!accountManager->login(username, password, displayName, domain, LinphoneEnums::toLinphone(transportType),
|
if (!accountManager->login(username, password, displayName, domain, LinphoneEnums::toLinphone(transportType),
|
||||||
&error, registrarUri, outboundProxyAddress, connectionId)) {
|
&error)) {
|
||||||
setErrorMessage(error);
|
setErrorMessage(error);
|
||||||
emit accountManager->registrationStateChanged(linphone::RegistrationState::None, linphone::Reason::None);
|
emit accountManager->registrationStateChanged(linphone::RegistrationState::None);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,16 +35,12 @@ public:
|
||||||
|
|
||||||
Q_PROPERTY(linphone::RegistrationState registrationState READ getRegistrationState NOTIFY registrationStateChanged)
|
Q_PROPERTY(linphone::RegistrationState registrationState READ getRegistrationState NOTIFY registrationStateChanged)
|
||||||
Q_PROPERTY(QString errorMessage READ getErrorMessage NOTIFY errorMessageChanged)
|
Q_PROPERTY(QString errorMessage READ getErrorMessage NOTIFY errorMessageChanged)
|
||||||
Q_PROPERTY(bool badIds MEMBER mBadIds NOTIFY reasonChanged)
|
|
||||||
|
|
||||||
Q_INVOKABLE void login(const QString &username,
|
Q_INVOKABLE void login(const QString &username,
|
||||||
const QString &password,
|
const QString &password,
|
||||||
QString displayName = QString(),
|
QString displayName = QString(),
|
||||||
QString domain = QString(),
|
QString domain = QString(),
|
||||||
LinphoneEnums::TransportType transportType = LinphoneEnums::TransportType::Tls,
|
LinphoneEnums::TransportType transportType = LinphoneEnums::TransportType::Tls);
|
||||||
QString registrarUri = QString(),
|
|
||||||
QString outboundProxyAddress = QString(),
|
|
||||||
QString connectionId = QString());
|
|
||||||
|
|
||||||
linphone::RegistrationState getRegistrationState() const;
|
linphone::RegistrationState getRegistrationState() const;
|
||||||
void setRegistrationState(linphone::RegistrationState status);
|
void setRegistrationState(linphone::RegistrationState status);
|
||||||
|
|
@ -55,12 +51,10 @@ public:
|
||||||
signals:
|
signals:
|
||||||
void registrationStateChanged();
|
void registrationStateChanged();
|
||||||
void errorMessageChanged(QString error);
|
void errorMessageChanged(QString error);
|
||||||
void reasonChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
linphone::RegistrationState mRegistrationState = linphone::RegistrationState::None;
|
linphone::RegistrationState mRegistrationState = linphone::RegistrationState::None;
|
||||||
QString mErrorMessage;
|
QString mErrorMessage;
|
||||||
bool mBadIds = false;
|
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,8 @@
|
||||||
|
|
||||||
#include "core/App.hpp"
|
#include "core/App.hpp"
|
||||||
#include "core/call/CallGui.hpp"
|
#include "core/call/CallGui.hpp"
|
||||||
#include "core/chat/ChatGui.hpp"
|
|
||||||
#include "model/tool/ToolModel.hpp"
|
#include "model/tool/ToolModel.hpp"
|
||||||
#include "tool/LinphoneEnums.hpp"
|
#include "tool/LinphoneEnums.hpp"
|
||||||
#include "tool/accessibility/AccessibilityHelper.hpp"
|
|
||||||
#include "tool/providers/AvatarProvider.hpp"
|
#include "tool/providers/AvatarProvider.hpp"
|
||||||
#include "tool/providers/ImageProvider.hpp"
|
#include "tool/providers/ImageProvider.hpp"
|
||||||
|
|
||||||
|
|
@ -87,9 +85,9 @@ void setProperty(QObject &object, const char *property, const T &value) {
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
const QHash<int, Notifier::Notification> Notifier::Notifications = {
|
const QHash<int, Notifier::Notification> Notifier::Notifications = {
|
||||||
{Notifier::ReceivedMessage, {Notifier::ReceivedMessage, "NotificationReceivedMessage.qml", 10}},
|
//{Notifier::ReceivedMessage, {Notifier::ReceivedMessage, "NotificationReceivedMessage.qml", 10}},
|
||||||
//{Notifier::ReceivedFileMessage, {Notifier::ReceivedFileMessage, "NotificationReceivedFileMessage.qml", 10}},
|
//{Notifier::ReceivedFileMessage, {Notifier::ReceivedFileMessage, "NotificationReceivedFileMessage.qml", 10}},
|
||||||
{Notifier::ReceivedCall, {Notifier::ReceivedCall, "NotificationReceivedCall.qml", 30}}
|
{Notifier::ReceivedCall, {Notifier::ReceivedCall, "NotificationReceivedCall.qml", 30}},
|
||||||
//{Notifier::NewVersionAvailable, {Notifier::NewVersionAvailable, "NotificationNewVersionAvailable.qml", 30}},
|
//{Notifier::NewVersionAvailable, {Notifier::NewVersionAvailable, "NotificationNewVersionAvailable.qml", 30}},
|
||||||
//{Notifier::SnapshotWasTaken, {Notifier::SnapshotWasTaken, "NotificationSnapshotWasTaken.qml", 10}},
|
//{Notifier::SnapshotWasTaken, {Notifier::SnapshotWasTaken, "NotificationSnapshotWasTaken.qml", 10}},
|
||||||
//{Notifier::RecordingCompleted, {Notifier::RecordingCompleted, "NotificationRecordingCompleted.qml", 10}}
|
//{Notifier::RecordingCompleted, {Notifier::RecordingCompleted, "NotificationRecordingCompleted.qml", 10}}
|
||||||
|
|
@ -129,8 +127,8 @@ Notifier::~Notifier() {
|
||||||
|
|
||||||
bool Notifier::createNotification(Notifier::NotificationType type, QVariantMap data) {
|
bool Notifier::createNotification(Notifier::NotificationType type, QVariantMap data) {
|
||||||
mMutex->lock();
|
mMutex->lock();
|
||||||
// Q_ASSERT(mInstancesNumber <= MaxNotificationsNumber);
|
Q_ASSERT(mInstancesNumber <= MaxNotificationsNumber);
|
||||||
if (mInstancesNumber >= MaxNotificationsNumber) { // Check existing instances.
|
if (mInstancesNumber == MaxNotificationsNumber) { // Check existing instances.
|
||||||
qWarning() << QStringLiteral("Unable to create another notification.");
|
qWarning() << QStringLiteral("Unable to create another notification.");
|
||||||
mMutex->unlock();
|
mMutex->unlock();
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -165,6 +163,7 @@ bool Notifier::createNotification(Notifier::NotificationType type, QVariantMap d
|
||||||
engine->deleteLater();
|
engine->deleteLater();
|
||||||
exit(-1);
|
exit(-1);
|
||||||
} else {
|
} else {
|
||||||
|
lDebug() << engine->rootObjects()[0];
|
||||||
auto window = qobject_cast<QQuickWindow *>(obj);
|
auto window = qobject_cast<QQuickWindow *>(obj);
|
||||||
if (window) {
|
if (window) {
|
||||||
window->setProperty(NotificationPropertyData, data);
|
window->setProperty(NotificationPropertyData, data);
|
||||||
|
|
@ -172,24 +171,28 @@ bool Notifier::createNotification(Notifier::NotificationType type, QVariantMap d
|
||||||
// window->setProperty(it.key().toLatin1(), it.value());
|
// window->setProperty(it.key().toLatin1(), it.value());
|
||||||
const int timeout = Notifications[type].getTimeout() * 1000;
|
const int timeout = Notifications[type].getTimeout() * 1000;
|
||||||
auto updateNotificationCoordinates = [this, window, screen](int width, int height) {
|
auto updateNotificationCoordinates = [this, window, screen](int width, int height) {
|
||||||
auto screenHeightOffset =
|
int *screenHeightOffset = &mScreenHeightOffset[screen->name()]; // Access optimization
|
||||||
screen ? mScreenHeightOffset.value(screen->name()) : 0; // Access optimization
|
|
||||||
QRect availableGeometry = screen->availableGeometry();
|
QRect availableGeometry = screen->availableGeometry();
|
||||||
|
int heightOffset = availableGeometry.y() +
|
||||||
|
(availableGeometry.height() -
|
||||||
|
height); //*screen->devicePixelRatio(); when using manual scaler
|
||||||
|
|
||||||
window->setX(availableGeometry.x() +
|
window->setX(availableGeometry.x() +
|
||||||
(availableGeometry.width() -
|
(availableGeometry.width() -
|
||||||
width)); //*screen->devicePixelRatio()); when using manual scaler
|
width)); //*screen->devicePixelRatio()); when using manual scaler
|
||||||
window->setY(availableGeometry.y() + availableGeometry.height() - screenHeightOffset -
|
window->setY(heightOffset - (*screenHeightOffset % heightOffset));
|
||||||
height);
|
|
||||||
};
|
};
|
||||||
|
QObject::connect(window, &QQuickWindow::widthChanged,
|
||||||
|
[window, updateNotificationCoordinates](int w) {
|
||||||
|
updateNotificationCoordinates(w, window->height());
|
||||||
|
});
|
||||||
|
QObject::connect(window, &QQuickWindow::heightChanged,
|
||||||
|
[window, updateNotificationCoordinates](int h) {
|
||||||
|
updateNotificationCoordinates(window->width(), h);
|
||||||
|
});
|
||||||
updateNotificationCoordinates(window->width(), window->height());
|
updateNotificationCoordinates(window->width(), window->height());
|
||||||
auto screenHeightOffset =
|
QObject::connect(window, &QQuickWindow::closing, window,
|
||||||
screen ? mScreenHeightOffset.take(screen->name()) : 0; // Access optimization
|
[this, window] { deleteNotification(QVariant::fromValue(window)); });
|
||||||
mScreenHeightOffset.insert(screen->name(), screenHeightOffset + window->height());
|
|
||||||
QObject::connect(window, &QQuickWindow::closing, window, [this, window] {
|
|
||||||
qDebug() << "closing notification";
|
|
||||||
deleteNotification(QVariant::fromValue(window));
|
|
||||||
});
|
|
||||||
showNotification(window, timeout);
|
showNotification(window, timeout);
|
||||||
lInfo() << QStringLiteral("Create notification:") << QVariant::fromValue(window);
|
lInfo() << QStringLiteral("Create notification:") << QVariant::fromValue(window);
|
||||||
}
|
}
|
||||||
|
|
@ -209,6 +212,8 @@ bool Notifier::createNotification(Notifier::NotificationType type, QVariantMap d
|
||||||
|
|
||||||
void Notifier::showNotification(QObject *notification, int timeout) {
|
void Notifier::showNotification(QObject *notification, int timeout) {
|
||||||
// Display notification.
|
// Display notification.
|
||||||
|
QMetaObject::invokeMethod(notification, NotificationShowMethodName, Qt::DirectConnection);
|
||||||
|
|
||||||
QTimer *timer = new QTimer(notification);
|
QTimer *timer = new QTimer(notification);
|
||||||
timer->setInterval(timeout);
|
timer->setInterval(timeout);
|
||||||
timer->setSingleShot(true);
|
timer->setSingleShot(true);
|
||||||
|
|
@ -280,153 +285,63 @@ void Notifier::notifyReceivedCall(const shared_ptr<linphone::Call> &call) {
|
||||||
auto account = ToolModel::findAccount(call->getToAddress());
|
auto account = ToolModel::findAccount(call->getToAddress());
|
||||||
if (account) {
|
if (account) {
|
||||||
auto accountModel = Utils::makeQObject_ptr<AccountModel>(account);
|
auto accountModel = Utils::makeQObject_ptr<AccountModel>(account);
|
||||||
|
accountModel->setSelf(accountModel);
|
||||||
if (!accountModel->getNotificationsAllowed()) {
|
if (!accountModel->getNotificationsAllowed()) {
|
||||||
lInfo() << log().arg(
|
qInfo()
|
||||||
"Notifications have been disabled for this account - not creating a notification for incoming call");
|
<< "Notifications have been disabled for this account - not creating a notification for incoming call";
|
||||||
if (accountModel->forwardToVoiceMailInDndPresence()) {
|
|
||||||
lInfo() << log().arg("Transferring call to voicemail");
|
|
||||||
auto voicemailAddress = linphone::Factory::get()->createAddress(
|
|
||||||
Utils::appStringToCoreString(accountModel->getVoicemailAddress()));
|
|
||||||
if (voicemailAddress) call->transferTo(voicemailAddress);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
accountModel->deleteLater();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto model = CallCore::create(call);
|
auto model = CallCore::create(call);
|
||||||
auto gui = new CallGui(model);
|
auto gui = new CallGui(model);
|
||||||
gui->moveToThread(App::getInstance()->thread());
|
gui->moveToThread(App::getInstance()->thread());
|
||||||
auto callLog = call->getCallLog();
|
App::postCoreAsync([this, gui]() {
|
||||||
auto displayName = callLog && callLog->getConferenceInfo()
|
|
||||||
? Utils::coreStringToAppString(callLog->getConferenceInfo()->getSubject())
|
|
||||||
: ToolModel::getDisplayName(call->getRemoteAddress());
|
|
||||||
|
|
||||||
// Accessibility alert
|
|
||||||
//: New call from %1
|
|
||||||
AccessibilityHelper::announceMessage(tr("new_call_alert_accessible_name").arg(displayName));
|
|
||||||
|
|
||||||
App::postCoreAsync([this, gui, displayName]() {
|
|
||||||
mustBeInMainThread(getClassName());
|
mustBeInMainThread(getClassName());
|
||||||
QVariantMap map;
|
QVariantMap map;
|
||||||
|
|
||||||
map["displayName"].setValue(displayName);
|
|
||||||
map["call"].setValue(gui);
|
map["call"].setValue(gui);
|
||||||
CREATE_NOTIFICATION(Notifier::ReceivedCall, map)
|
CREATE_NOTIFICATION(Notifier::ReceivedCall, map)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notifier::notifyReceivedMessages(const std::shared_ptr<linphone::ChatRoom> &room,
|
|
||||||
const list<shared_ptr<linphone::ChatMessage>> &messages) {
|
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
||||||
|
|
||||||
if (room->getMuted()) return;
|
|
||||||
|
|
||||||
QString txt;
|
|
||||||
QString remoteAddress;
|
|
||||||
|
|
||||||
if (messages.size() > 0) {
|
|
||||||
|
|
||||||
shared_ptr<linphone::ChatMessage> message = messages.front();
|
|
||||||
auto receiverAccount = ToolModel::findAccount(message->getToAddress());
|
|
||||||
if (receiverAccount) {
|
|
||||||
auto senderAccount = ToolModel::findAccount(message->getFromAddress());
|
|
||||||
auto currentAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
|
|
||||||
if (senderAccount && senderAccount->getContactAddress() && currentAccount->getContactAddress() &&
|
|
||||||
senderAccount->getContactAddress()->weakEqual(currentAccount->getContactAddress())) {
|
|
||||||
qDebug() << "sender is current account, return";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto accountModel = Utils::makeQObject_ptr<AccountModel>(receiverAccount);
|
|
||||||
if (!accountModel->getNotificationsAllowed()) {
|
|
||||||
lInfo() << log().arg(
|
|
||||||
"Notifications have been disabled for this account - not creating a notification for "
|
|
||||||
"incoming message");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
accountModel->deleteLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto getMessage = [this, &remoteAddress, &txt](const shared_ptr<linphone::ChatMessage> &message) {
|
|
||||||
if (message->isRead()) return;
|
|
||||||
auto remoteAddr = message->getFromAddress();
|
|
||||||
// remoteAddr->clean();
|
|
||||||
remoteAddress = Utils::coreStringToAppString(remoteAddr->asStringUriOnly());
|
|
||||||
auto fileContent = message->getFileTransferInformation();
|
|
||||||
if (!fileContent) {
|
|
||||||
for (auto content : message->getContents()) {
|
|
||||||
if (content->isText()) txt += content->getUtf8Text().c_str();
|
|
||||||
}
|
|
||||||
} else if (fileContent->isVoiceRecording())
|
|
||||||
//: 'Voice message received!' : message to warn the user in a notofication for voice messages.
|
|
||||||
txt = tr("new_voice_message");
|
|
||||||
else txt = tr("new_file_message");
|
|
||||||
if (txt.isEmpty() && message->hasConferenceInvitationContent())
|
|
||||||
//: 'Conference invitation received!' : Notification about receiving an invitation to a conference.
|
|
||||||
txt = tr("new_conference_invitation");
|
|
||||||
};
|
|
||||||
|
|
||||||
if (messages.size() == 1) { // Display only sender on mono message.
|
|
||||||
if (message->isRead()) return;
|
|
||||||
getMessage(message);
|
|
||||||
if (txt.isEmpty()) { // Do not notify message without content
|
|
||||||
qDebug() << "empty notif, return";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int unreadCount = 0;
|
|
||||||
for (auto &message : messages) {
|
|
||||||
if (!message->isRead()) {
|
|
||||||
++unreadCount;
|
|
||||||
if (unreadCount == 1) getMessage(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (unreadCount == 0) return;
|
|
||||||
if (unreadCount > 1)
|
|
||||||
//: 'New messages received!' Notification that warn the user of new messages.
|
|
||||||
txt = tr("new_chat_room_messages");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Play noitification sound
|
|
||||||
auto settings = SettingsModel::getInstance();
|
|
||||||
if (settings && !settings->dndEnabled()) {
|
|
||||||
CoreModel::getInstance()->getCore()->playLocal(
|
|
||||||
Utils::appStringToCoreString(settings->getChatNotificationSoundPath()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If chat currently displayed, do not display notification
|
|
||||||
auto currentlyDisplayedChat = App::getInstance()->getCurrentChat();
|
|
||||||
auto mainWin = App::getInstance()->getMainWindow();
|
|
||||||
if (currentlyDisplayedChat && mainWin->isActive()) {
|
|
||||||
auto linphoneCurrent = currentlyDisplayedChat->mCore->getModel()->getMonitor();
|
|
||||||
if (linphoneCurrent->getIdentifier() == room->getIdentifier()) {
|
|
||||||
lInfo() << log().arg("Chat is currently displayed in the view, do not show notification");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto chatCore = ChatCore::create(room);
|
|
||||||
|
|
||||||
App::postCoreAsync([this, txt, chatCore, remoteAddress]() {
|
|
||||||
mustBeInMainThread(getClassName());
|
|
||||||
|
|
||||||
// Accessibility alert
|
|
||||||
//: New message on chatroom %1
|
|
||||||
AccessibilityHelper::announceMessage(tr("new_message_alert_accessible_name").arg(chatCore->getTitle()));
|
|
||||||
|
|
||||||
QVariantMap map;
|
|
||||||
map["message"] = txt;
|
|
||||||
map["remoteAddress"] = remoteAddress;
|
|
||||||
map["chatRoomName"] = chatCore->getTitle();
|
|
||||||
map["chatRoomAddress"] = chatCore->getChatRoomAddress();
|
|
||||||
map["avatarUri"] = chatCore->getAvatarUri();
|
|
||||||
map["isGroupChat"] = chatCore->isGroupChat();
|
|
||||||
map["chat"] = QVariant::fromValue(chatCore ? new ChatGui(chatCore) : nullptr);
|
|
||||||
CREATE_NOTIFICATION(Notifier::ReceivedMessage, map)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
|
void Notifier::notifyReceivedMessages(const list<shared_ptr<linphone::ChatMessage>> &messages) {
|
||||||
|
QVariantMap map;
|
||||||
|
QString txt;
|
||||||
|
if (messages.size() > 0) {
|
||||||
|
shared_ptr<linphone::ChatMessage> message = messages.front();
|
||||||
|
|
||||||
|
if (messages.size() == 1) {
|
||||||
|
auto fileContent = message->getFileTransferInformation();
|
||||||
|
if (!fileContent) {
|
||||||
|
foreach (auto content, message->getContents()) {
|
||||||
|
if (content->isText()) txt += content->getUtf8Text().c_str();
|
||||||
|
}
|
||||||
|
} else if (fileContent->isVoiceRecording())
|
||||||
|
//: 'Voice message received!' : message to warn the user in a notofication for voice messages.
|
||||||
|
txt = tr("new_voice_message");
|
||||||
|
else txt = tr("new_file_message");
|
||||||
|
if (txt.isEmpty() && message->hasConferenceInvitationContent())
|
||||||
|
//: 'Conference invitation received!' : Notification about receiving an invitation to a conference.
|
||||||
|
txt = tr("new_conference_invitation");
|
||||||
|
} else
|
||||||
|
//: 'New messages received!' Notification that warn the user of new messages.
|
||||||
|
txt = tr("new_chat_room_messages");
|
||||||
|
map["message"] = txt;
|
||||||
|
shared_ptr<linphone::ChatRoom> chatRoom(message->getChatRoom());
|
||||||
|
map["timelineModel"].setValue(
|
||||||
|
CoreManager::getInstance()->getTimelineListModel()->getTimeline(chatRoom, true).get());
|
||||||
|
if (messages.size() == 1) { // Display only sender on mono message.
|
||||||
|
map["remoteAddress"] = Utils::coreStringToAppString(message->getFromAddress()->asStringUriOnly());
|
||||||
|
map["fullremoteAddress"] = Utils::coreStringToAppString(message->getFromAddress()->asString());
|
||||||
|
}
|
||||||
|
map["localAddress"] = Utils::coreStringToAppString(message->getToAddress()->asStringUriOnly());
|
||||||
|
map["fullLocalAddress"] = Utils::coreStringToAppString(message->getToAddress()->asString());
|
||||||
|
map["window"].setValue(App::getInstance()->getMainWindow());
|
||||||
|
CREATE_NOTIFICATION(Notifier::ReceivedMessage, map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Notifier::notifyReceivedReactions(
|
void Notifier::notifyReceivedReactions(
|
||||||
const QList<QPair<std::shared_ptr<linphone::ChatMessage>, std::shared_ptr<const linphone::ChatMessageReaction>>>
|
const QList<QPair<std::shared_ptr<linphone::ChatMessage>, std::shared_ptr<const linphone::ChatMessageReaction>>>
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,9 @@ public:
|
||||||
~Notifier();
|
~Notifier();
|
||||||
|
|
||||||
enum NotificationType {
|
enum NotificationType {
|
||||||
ReceivedMessage,
|
// ReceivedMessage,
|
||||||
// ReceivedFileMessage,
|
// ReceivedFileMessage,
|
||||||
ReceivedCall
|
ReceivedCall,
|
||||||
// NewVersionAvailable,
|
// NewVersionAvailable,
|
||||||
// SnapshotWasTaken,
|
// SnapshotWasTaken,
|
||||||
// RecordingCompleted
|
// RecordingCompleted
|
||||||
|
|
@ -52,9 +52,8 @@ public:
|
||||||
// void notifyReceivedCall(Call *call);
|
// void notifyReceivedCall(Call *call);
|
||||||
void notifyReceivedCall(const std::shared_ptr<linphone::Call> &call); // Call from Linphone
|
void notifyReceivedCall(const std::shared_ptr<linphone::Call> &call); // Call from Linphone
|
||||||
|
|
||||||
void notifyReceivedMessages(const std::shared_ptr<linphone::ChatRoom> &room,
|
|
||||||
const std::list<std::shared_ptr<linphone::ChatMessage>> &messages);
|
|
||||||
/*
|
/*
|
||||||
|
void notifyReceivedMessages(const std::list<std::shared_ptr<linphone::ChatMessage>> &messages);
|
||||||
void notifyReceivedReactions(
|
void notifyReceivedReactions(
|
||||||
const QList<QPair<std::shared_ptr<linphone::ChatMessage>, std::shared_ptr<const
|
const QList<QPair<std::shared_ptr<linphone::ChatMessage>, std::shared_ptr<const
|
||||||
linphone::ChatMessageReaction>>> &reactions); void notifyReceivedFileMessage(const
|
linphone::ChatMessageReaction>>> &reactions); void notifyReceivedFileMessage(const
|
||||||
|
|
|
||||||
|
|
@ -46,16 +46,12 @@ ParticipantCore::ParticipantCore(const std::shared_ptr<linphone::Participant> &p
|
||||||
mParticipantModel->moveToThread(CoreModel::getInstance()->thread());
|
mParticipantModel->moveToThread(CoreModel::getInstance()->thread());
|
||||||
if (participant) {
|
if (participant) {
|
||||||
mAdminStatus = participant->isAdmin();
|
mAdminStatus = participant->isAdmin();
|
||||||
auto participantAddress = participant->getAddress();
|
mSipAddress = Utils::coreStringToAppString(participant->getAddress()->asStringUriOnly());
|
||||||
mUsername = Utils::coreStringToAppString(participantAddress->getUsername());
|
|
||||||
mSipAddress = Utils::coreStringToAppString(participantAddress->asStringUriOnly());
|
|
||||||
mIsMe = ToolModel::isMe(mSipAddress);
|
mIsMe = ToolModel::isMe(mSipAddress);
|
||||||
mCreationTime = QDateTime::fromSecsSinceEpoch(participant->getCreationTime());
|
mCreationTime = QDateTime::fromSecsSinceEpoch(participant->getCreationTime());
|
||||||
mDisplayName = Utils::coreStringToAppString(participantAddress->getDisplayName());
|
mDisplayName = Utils::coreStringToAppString(participant->getAddress()->getDisplayName());
|
||||||
if (mDisplayName.isEmpty()) mDisplayName = ToolModel::getDisplayName(participantAddress);
|
if (mDisplayName.isEmpty())
|
||||||
auto isFriend = ToolModel::findFriendByAddress(participantAddress);
|
mDisplayName = Utils::coreStringToAppString(participant->getAddress()->getUsername());
|
||||||
if (isFriend && isFriend->getCore()) mSecurityLevel = LinphoneEnums::fromLinphone(isFriend->getSecurityLevel());
|
|
||||||
else mSecurityLevel = LinphoneEnums::SecurityLevel::None;
|
|
||||||
for (auto &device : participant->getDevices()) {
|
for (auto &device : participant->getDevices()) {
|
||||||
auto name = Utils::coreStringToAppString(device->getName());
|
auto name = Utils::coreStringToAppString(device->getName());
|
||||||
auto address = Utils::coreStringToAppString(device->getAddress()->asStringUriOnly());
|
auto address = Utils::coreStringToAppString(device->getAddress()->asStringUriOnly());
|
||||||
|
|
@ -79,7 +75,7 @@ void ParticipantCore::setSelf(QSharedPointer<ParticipantCore> me) {
|
||||||
connect(this, &ParticipantCore::sipAddressChanged, this, &ParticipantCore::updateIsMe);
|
connect(this, &ParticipantCore::sipAddressChanged, this, &ParticipantCore::updateIsMe);
|
||||||
}
|
}
|
||||||
|
|
||||||
LinphoneEnums::SecurityLevel ParticipantCore::getSecurityLevel() const {
|
int ParticipantCore::getSecurityLevel() const {
|
||||||
return mSecurityLevel;
|
return mSecurityLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -125,17 +121,6 @@ QString ParticipantCore::getDisplayName() const {
|
||||||
return mDisplayName;
|
return mDisplayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticipantCore::setUsername(const QString &name) {
|
|
||||||
if (mUsername != name) {
|
|
||||||
mUsername = name;
|
|
||||||
emit usernameChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ParticipantCore::getUsername() const {
|
|
||||||
return mUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDateTime ParticipantCore::getCreationTime() const {
|
QDateTime ParticipantCore::getCreationTime() const {
|
||||||
return mCreationTime;
|
return mCreationTime;
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +153,7 @@ void ParticipantCore::setIsFocus(const bool &focus) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticipantCore::setSecurityLevel(LinphoneEnums::SecurityLevel level) {
|
void ParticipantCore::setSecurityLevel(int level) {
|
||||||
if (level != mSecurityLevel) {
|
if (level != mSecurityLevel) {
|
||||||
mSecurityLevel = level;
|
mSecurityLevel = level;
|
||||||
emit securityLevelChanged();
|
emit securityLevelChanged();
|
||||||
|
|
|
||||||
|
|
@ -40,12 +40,11 @@ class ParticipantCore : public QObject, public AbstractObject {
|
||||||
|
|
||||||
Q_PROPERTY(QString sipAddress READ getSipAddress WRITE setSipAddress NOTIFY sipAddressChanged)
|
Q_PROPERTY(QString sipAddress READ getSipAddress WRITE setSipAddress NOTIFY sipAddressChanged)
|
||||||
Q_PROPERTY(QString displayName READ getDisplayName WRITE setDisplayName NOTIFY displayNameChanged)
|
Q_PROPERTY(QString displayName READ getDisplayName WRITE setDisplayName NOTIFY displayNameChanged)
|
||||||
Q_PROPERTY(QString username READ getUsername WRITE setUsername NOTIFY usernameChanged)
|
|
||||||
Q_PROPERTY(bool isAdmin READ isAdmin WRITE setIsAdmin NOTIFY isAdminChanged)
|
Q_PROPERTY(bool isAdmin READ isAdmin WRITE setIsAdmin NOTIFY isAdminChanged)
|
||||||
Q_PROPERTY(bool isMe READ isMe NOTIFY isMeChanged)
|
Q_PROPERTY(bool isMe READ isMe NOTIFY isMeChanged)
|
||||||
Q_PROPERTY(QDateTime creationTime READ getCreationTime CONSTANT)
|
Q_PROPERTY(QDateTime creationTime READ getCreationTime CONSTANT)
|
||||||
Q_PROPERTY(bool focus READ isFocus CONSTANT)
|
Q_PROPERTY(bool focus READ isFocus CONSTANT)
|
||||||
Q_PROPERTY(LinphoneEnums::SecurityLevel securityLevel READ getSecurityLevel NOTIFY securityLevelChanged)
|
Q_PROPERTY(int securityLevel READ getSecurityLevel NOTIFY securityLevelChanged)
|
||||||
Q_PROPERTY(int deviceCount READ getDeviceCount NOTIFY deviceCountChanged)
|
Q_PROPERTY(int deviceCount READ getDeviceCount NOTIFY deviceCountChanged)
|
||||||
Q_PROPERTY(QList<QVariant> devices READ getParticipantDevices NOTIFY deviceChanged)
|
Q_PROPERTY(QList<QVariant> devices READ getParticipantDevices NOTIFY deviceChanged)
|
||||||
|
|
||||||
|
|
@ -57,12 +56,11 @@ public:
|
||||||
void setSelf(QSharedPointer<ParticipantCore> me);
|
void setSelf(QSharedPointer<ParticipantCore> me);
|
||||||
|
|
||||||
QString getDisplayName() const;
|
QString getDisplayName() const;
|
||||||
QString getUsername() const;
|
|
||||||
QString getSipAddress() const;
|
QString getSipAddress() const;
|
||||||
QDateTime getCreationTime() const;
|
QDateTime getCreationTime() const;
|
||||||
bool isAdmin() const;
|
bool isAdmin() const;
|
||||||
bool isFocus() const;
|
bool isFocus() const;
|
||||||
LinphoneEnums::SecurityLevel getSecurityLevel() const;
|
int getSecurityLevel() const;
|
||||||
int getDeviceCount() const;
|
int getDeviceCount() const;
|
||||||
|
|
||||||
bool isMe() const;
|
bool isMe() const;
|
||||||
|
|
@ -71,11 +69,10 @@ public:
|
||||||
|
|
||||||
void setSipAddress(const QString &address);
|
void setSipAddress(const QString &address);
|
||||||
void setDisplayName(const QString &name);
|
void setDisplayName(const QString &name);
|
||||||
void setUsername(const QString &name);
|
|
||||||
void setCreationTime(const QDateTime &date);
|
void setCreationTime(const QDateTime &date);
|
||||||
void setIsAdmin(const bool &status);
|
void setIsAdmin(const bool &status);
|
||||||
void setIsFocus(const bool &focus);
|
void setIsFocus(const bool &focus);
|
||||||
void setSecurityLevel(LinphoneEnums::SecurityLevel level);
|
void setSecurityLevel(int level);
|
||||||
|
|
||||||
QList<QVariant> getParticipantDevices();
|
QList<QVariant> getParticipantDevices();
|
||||||
|
|
||||||
|
|
@ -95,7 +92,6 @@ signals:
|
||||||
void invitingChanged();
|
void invitingChanged();
|
||||||
void creationTimeChanged();
|
void creationTimeChanged();
|
||||||
void displayNameChanged();
|
void displayNameChanged();
|
||||||
void usernameChanged();
|
|
||||||
|
|
||||||
void lStartInvitation(const int &secs = 30);
|
void lStartInvitation(const int &secs = 30);
|
||||||
void lSetIsAdmin(bool status);
|
void lSetIsAdmin(bool status);
|
||||||
|
|
@ -111,12 +107,11 @@ private:
|
||||||
QList<QVariant> mParticipantDevices;
|
QList<QVariant> mParticipantDevices;
|
||||||
|
|
||||||
QString mDisplayName;
|
QString mDisplayName;
|
||||||
QString mUsername;
|
|
||||||
QString mSipAddress;
|
QString mSipAddress;
|
||||||
QDateTime mCreationTime;
|
QDateTime mCreationTime;
|
||||||
bool mAdminStatus;
|
bool mAdminStatus;
|
||||||
bool mIsFocus;
|
bool mIsFocus;
|
||||||
LinphoneEnums::SecurityLevel mSecurityLevel;
|
int mSecurityLevel;
|
||||||
bool mIsMe;
|
bool mIsMe;
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -44,13 +44,12 @@ ParticipantDeviceCore::ParticipantDeviceCore(const std::shared_ptr<linphone::Par
|
||||||
mustBeInLinphoneThread(getClassName());
|
mustBeInLinphoneThread(getClassName());
|
||||||
if (device) {
|
if (device) {
|
||||||
mName = Utils::coreStringToAppString(device->getName());
|
mName = Utils::coreStringToAppString(device->getName());
|
||||||
auto deviceAddress = device->getAddress();
|
auto deviceAddress = device->getAddress()->clone();
|
||||||
mUniqueAddress = Utils::coreStringToAppString(deviceAddress->asString());
|
mUniqueAddress = Utils::coreStringToAppString(deviceAddress->asString());
|
||||||
mAddress = Utils::coreStringToAppString(deviceAddress->asStringUriOnly());
|
mAddress = Utils::coreStringToAppString(deviceAddress->asStringUriOnly());
|
||||||
// the display name of the device himself may be the uncleaned sip uri
|
// the display name of the device himself may be the uncleaned sip uri
|
||||||
// Use the participant name instead
|
// Use the participant name instead
|
||||||
auto participant = device->getParticipant();
|
mDisplayName = Utils::coreStringToAppString(device->getParticipant()->getAddress()->getDisplayName());
|
||||||
mDisplayName = Utils::coreStringToAppString(participant ? participant->getAddress()->getDisplayName() : "");
|
|
||||||
if (mDisplayName.isEmpty()) {
|
if (mDisplayName.isEmpty()) {
|
||||||
mDisplayName = ToolModel::getDisplayName(deviceAddress);
|
mDisplayName = ToolModel::getDisplayName(deviceAddress);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ParticipantInfoList.hpp"
|
|
||||||
#include "core/App.hpp"
|
|
||||||
#include "core/chat/ChatCore.hpp"
|
|
||||||
#include "core/participant/ParticipantGui.hpp"
|
|
||||||
#include "tool/Utils.hpp"
|
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ParticipantInfoList)
|
|
||||||
|
|
||||||
QSharedPointer<ParticipantInfoList> ParticipantInfoList::create() {
|
|
||||||
auto model = QSharedPointer<ParticipantInfoList>(new ParticipantInfoList(), &QObject::deleteLater);
|
|
||||||
model->moveToThread(App::getInstance()->thread());
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedPointer<ParticipantInfoList> ParticipantInfoList::create(const QSharedPointer<ChatCore> &chatCore) {
|
|
||||||
auto model = create();
|
|
||||||
model->setChatCore(chatCore);
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
ParticipantInfoList::ParticipantInfoList(QObject *parent) : ListProxy(parent) {
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
|
||||||
}
|
|
||||||
|
|
||||||
ParticipantInfoList::~ParticipantInfoList() {
|
|
||||||
mList.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParticipantInfoList::setChatCore(const QSharedPointer<ChatCore> &chatCore) {
|
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
|
||||||
if (mChatCore) disconnect(mChatCore.get(), &ChatCore::participantsChanged, this, nullptr);
|
|
||||||
mChatCore = chatCore;
|
|
||||||
lDebug() << "[ParticipantInfoList] : set Chat " << mChatCore.get();
|
|
||||||
clearData();
|
|
||||||
if (mChatCore) {
|
|
||||||
auto buildList = [this] {
|
|
||||||
QStringList participantAddresses;
|
|
||||||
QList<QSharedPointer<ParticipantGui>> participantList;
|
|
||||||
auto participants = mChatCore->getParticipants();
|
|
||||||
resetData();
|
|
||||||
for (auto p : participants)
|
|
||||||
add(p);
|
|
||||||
};
|
|
||||||
connect(mChatCore.get(), &ChatCore::participantsChanged, this, buildList);
|
|
||||||
buildList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant ParticipantInfoList::data(const QModelIndex &index, int role) const {
|
|
||||||
int row = index.row();
|
|
||||||
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
|
||||||
if (role == Qt::DisplayRole) {
|
|
||||||
return QVariant::fromValue(new ParticipantGui(mList[row].objectCast<ParticipantCore>()));
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue