mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-22 14:18:09 +00:00
Compare commits
40 commits
master
...
6.0.1-Call
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff83c1794e | ||
|
|
fd0cbdcd41 | ||
|
|
971e7a7201 | ||
|
|
480704664e | ||
|
|
e78c7d04f0 | ||
|
|
f25b4a83db | ||
|
|
b3734702cb | ||
|
|
9c3922db95 | ||
|
|
18e8d29959 | ||
|
|
e018173b5f | ||
|
|
f84280e09d | ||
|
|
cdb477853b | ||
|
|
40df729a88 | ||
|
|
9cb5758233 | ||
|
|
33b7cf62f0 | ||
|
|
ea2135d875 | ||
|
|
a649266c26 | ||
|
|
29caaf619a | ||
|
|
ea7621cf35 | ||
|
|
f6e20a9aff | ||
|
|
18ee1566f0 | ||
|
|
14a959ef57 | ||
|
|
c0ad0de987 | ||
|
|
23f5abe0f1 | ||
|
|
a3130c6067 | ||
|
|
aa871c2735 | ||
|
|
8391d438eb | ||
|
|
5ca6876e92 | ||
|
|
7490cf0ca5 | ||
|
|
76277fbe9d | ||
|
|
ca5f4411e7 | ||
|
|
e18a1f78e8 | ||
|
|
e08d5e0377 | ||
|
|
6b02ebed39 | ||
|
|
490f5cdca1 | ||
|
|
fb786c2a9d | ||
|
|
23e32d1953 | ||
|
|
d025aaaeec | ||
|
|
faeed359fb | ||
|
|
1e82f48839 |
80 changed files with 41855 additions and 2695 deletions
171
.gitlab-ci-files/linux-desktop-ubuntu-2204.yml
Normal file
171
.gitlab-ci-files/linux-desktop-ubuntu-2204.yml
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
.factorize_ubuntu2204: &docker_image_platform_and_runner_tag
|
||||||
|
tags: [ "docker" ]
|
||||||
|
image: gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-ubuntu-22-04-lts:$UBUNTU_2204_IMAGE_VERSION
|
||||||
|
|
||||||
|
ubuntu2204-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
|
||||||
|
#################################################
|
||||||
|
|
||||||
|
ubuntu2204-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
|
||||||
|
|
||||||
|
ubuntu2204-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
|
||||||
|
|
||||||
|
ubuntu2204-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: ubuntu2204-ninja-clang
|
||||||
|
|
||||||
|
ubuntu2204-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
|
||||||
|
#################################################
|
||||||
|
|
||||||
|
ubuntu2204-makefile-gcc-package:
|
||||||
|
stage: package
|
||||||
|
tags: [ "docker" ]
|
||||||
|
image: gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-ubuntu-22-04-lts:$UBUNTU_2204_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
|
||||||
|
#################################################
|
||||||
|
|
||||||
|
ubuntu2204-makefile-gcc-deploy:
|
||||||
|
stage: deploy
|
||||||
|
tags: [ "deploy" ]
|
||||||
|
needs:
|
||||||
|
- ubuntu2204-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
|
||||||
|
|
||||||
|
|
||||||
|
ubuntu2204-makefile-gcc-plugins-deploy:
|
||||||
|
stage: deploy
|
||||||
|
tags: [ "deploy" ]
|
||||||
|
needs:
|
||||||
|
- ubuntu2204-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/
|
||||||
|
|
||||||
|
|
@ -204,6 +204,7 @@ win64-ninja-vs2022-package-windows:
|
||||||
|
|
||||||
win64-codesigning:
|
win64-codesigning:
|
||||||
stage: signing
|
stage: signing
|
||||||
|
allow_failure: true
|
||||||
extends:
|
extends:
|
||||||
- .windows-codesigning
|
- .windows-codesigning
|
||||||
needs:
|
needs:
|
||||||
|
|
@ -218,6 +219,7 @@ win64-codesigning:
|
||||||
script:
|
script:
|
||||||
- cd build-desktop/OUTPUT/Packages/
|
- cd build-desktop/OUTPUT/Packages/
|
||||||
- Invoke-Expression "& ${WINDOWS_SIGN_TOOL} sign /fd SHA256 /t ${WINDOWS_SIGN_TIMESTAMP_URL} /sha1 ${WINDOWS_SIGN_HASH} *.exe"
|
- Invoke-Expression "& ${WINDOWS_SIGN_TOOL} sign /fd SHA256 /t ${WINDOWS_SIGN_TIMESTAMP_URL} /sha1 ${WINDOWS_SIGN_HASH} *.exe"
|
||||||
|
- 'if (-not ($LastExitCode -eq 0)) {throw "Error: Signature failed"}'
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- build-desktop\OUTPUT\Packages\*
|
- build-desktop\OUTPUT\Packages\*
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ variables:
|
||||||
DEBIAN_10_IMAGE_VERSION: 20210217_python3
|
DEBIAN_10_IMAGE_VERSION: 20210217_python3
|
||||||
UBUNTU_ROLLING_IMAGE_VERSION: 20211012_add_qtwebview
|
UBUNTU_ROLLING_IMAGE_VERSION: 20211012_add_qtwebview
|
||||||
UBUNTU_2004_IMAGE_VERSION: 20250226_qt6-8-0
|
UBUNTU_2004_IMAGE_VERSION: 20250226_qt6-8-0
|
||||||
|
UBUNTU_2204_IMAGE_VERSION: 20250630_add-qtshadertools
|
||||||
|
|
||||||
|
|
||||||
workflow:
|
workflow:
|
||||||
|
|
@ -50,7 +51,8 @@ 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-2004.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'
|
||||||
|
|
||||||
|
|
|
||||||
45
CHANGELOG.md
Normal file
45
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Change Log
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
Group changes to describe their impact on the project, as follows:
|
||||||
|
|
||||||
|
Added for new features.
|
||||||
|
Changed for changes in existing functionality.
|
||||||
|
Deprecated for once-stable features removed in upcoming releases.
|
||||||
|
Removed for deprecated features removed in this release.
|
||||||
|
Fixed for any bug fixes.
|
||||||
|
Security to invite users to upgrade in case of vulnerabilities.
|
||||||
|
|
||||||
|
## [6.0.1] - 2025-09-08
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- SDK updated to 5.4.42 release
|
||||||
|
- Updated translations from Weblate
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Various issues related to OpenID connect
|
||||||
|
- Wrong thread issue for remote provisioning
|
||||||
|
- Other UI related fixes
|
||||||
|
|
||||||
|
## [6.0.0] - 2025-05-16
|
||||||
|
|
||||||
|
6.0.0 release is a complete rework of Linphone Desktop, with only the call and contact list features availables.
|
||||||
|
Disclaimer: this release is focused on calls, meetings/conferences are available but aren't stable yet and chat features are missing.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Contacts trust: contacts for which all devices have been validated through a ZRTP call with SAS exchange are now highlighted with a blue circle (and with a red one in case of mistrust). That trust is now handled at contact level (instead of conversation level in previous versions).
|
||||||
|
- Security focus: security & trust is more visible than ever, and unsecure conversations & calls are even more visible than before.
|
||||||
|
- CardDAV: you can configure as many CardDAV servers you want to synchronize you contacts in Linphone (in addition or in replacement of native addressbook import).
|
||||||
|
- OpenID: when used with a SSO compliant SIP server (such as Flexisip), we support single-sign-on login.
|
||||||
|
- MWI support: display and allow to call your voicemail when you have new messages (if supported by your VoIP provider and properly configured in your account params).
|
||||||
|
- CCMP support: if you configure a CCMP server URL in your accounts params, it will be used when scheduling meetings & to fetch list of meetings you've organized/been invited to.
|
||||||
|
- Devices list: check on which device your sip.linphone.org account is connected and the last connection date & time (like on subscribe.linphone.org).
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Separated threads: Contrary to previous versions, our SDK is now running in it's own thread, meaning it won't freeze the UI anymore in case of heavy work, thus reducing the number of ANR and greatly increasing the fluidity of the app.
|
||||||
|
- Asymmetrical video : you no longer need to send your own camera feed to receive the one from the remote end of the call, and vice versa.
|
||||||
|
- Call transfer: Blind & Attended call transfer have been merged into one: during a call, if you initiate a transfer action, either pick another call to do the attended transfer or select a contact from the list (you can input a SIP URI not already in the suggestions list) to start a blind transfer.
|
||||||
|
- Settings: a lot of them are gone, the one that are still there have been reworked to increase user friendliness.
|
||||||
|
- 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
|
||||||
|
- Some settings have changed name and/or section in linphonerc file.
|
||||||
|
|
@ -93,6 +93,12 @@
|
||||||
#include "tool/request/RequestDialog.hpp"
|
#include "tool/request/RequestDialog.hpp"
|
||||||
#include "tool/thread/Thread.hpp"
|
#include "tool/thread/Thread.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)
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
|
|
@ -259,10 +265,11 @@ 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.
|
||||||
QThread::currentThread()->setPriority(QThread::HighPriority);
|
QThread::currentThread()->setPriority(QThread::HighPriority);
|
||||||
|
qDebug() << "app thread is" << QThread::currentThread();
|
||||||
QCoreApplication::setApplicationName(EXECUTABLE_NAME);
|
QCoreApplication::setApplicationName(EXECUTABLE_NAME);
|
||||||
QApplication::setOrganizationDomain(EXECUTABLE_NAME);
|
QApplication::setOrganizationDomain(EXECUTABLE_NAME);
|
||||||
QCoreApplication::setApplicationVersion(APPLICATION_SEMVER);
|
QCoreApplication::setApplicationVersion(APPLICATION_SEMVER);
|
||||||
|
|
@ -291,6 +298,7 @@ App::App(int &argc, char *argv[])
|
||||||
emit currentDateChanged();
|
emit currentDateChanged();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
mEventCountNotifier = new EventCountNotifier(this);
|
||||||
mDateUpdateTimer.start();
|
mDateUpdateTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -355,6 +363,50 @@ void App::setSelf(QSharedPointer<App>(me)) {
|
||||||
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::accountAdded,
|
||||||
|
[this](const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::Account> &account) {
|
||||||
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
qDebug() << "account added";
|
||||||
|
if (CoreModel::getInstance()->mConfigStatus == linphone::ConfiguringState::Successful) {
|
||||||
|
qDebug() << "remote prov finished";
|
||||||
|
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
|
||||||
|
QMetaObject::invokeMethod(mMainWindow, "openMainPage", Qt::DirectConnection,
|
||||||
|
Q_ARG(QVariant, accountConnected));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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); });
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------
|
||||||
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) {
|
||||||
|
|
@ -383,6 +435,15 @@ QThread *App::getLinphoneThread() {
|
||||||
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
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
|
|
@ -426,6 +487,7 @@ void App::initCore() {
|
||||||
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);
|
||||||
|
|
||||||
QMetaObject::invokeMethod(
|
QMetaObject::invokeMethod(
|
||||||
mLinphoneThread->getThreadId(),
|
mLinphoneThread->getThreadId(),
|
||||||
[this, settings = mSettings]() mutable {
|
[this, settings = mSettings]() mutable {
|
||||||
|
|
@ -522,7 +584,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,
|
||||||
|
|
@ -546,6 +608,20 @@ void App::initCore() {
|
||||||
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 (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);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
|
|
@ -565,7 +641,6 @@ 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;
|
||||||
|
|
||||||
|
|
@ -573,28 +648,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
|
// Use this workaround if there is still an issue about detecting wrong language from system on Mac. Qt doesn't
|
||||||
// the current system language on QLocale::system(). So we need to get it from user settings and overwrite its
|
// use the current system language on QLocale::system(). So we need to get it from user settings and overwrite
|
||||||
// Locale.
|
// its 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 the
|
QLocale sysLocale(QLocale::system().name()); // Use Locale from name because Qt has a bug where it didn't use
|
||||||
// QLocale::language (aka : translator.language != locale.language) on
|
// the QLocale::language (aka : translator.language !=
|
||||||
// Mac. #endif
|
// locale.language) on 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());
|
||||||
|
|
@ -775,34 +850,37 @@ 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), "[command]");
|
mParser->addPositionalArgument("command", tr("command_line_arg_order").replace("%1", APPLICATION_NAME),
|
||||||
|
"[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), tr("command_line_option_config_arg")},
|
//{"config", tr("command_line_option_config").replace("%1", EXECUTABLE_NAME),
|
||||||
|
// 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 configuration."
|
//: "Specify the linphone configuration file to be fetched. It will be merged with the current
|
||||||
tr("command_line_option_config_to_fetch")
|
//: configuration."
|
||||||
.replace("%1", EXECUTABLE_NAME),
|
tr("command_line_option_config_to_fetch").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), tr("command_line_option_call_arg")},
|
//{{"c", "call"}, tr("command_line_option_call").replace("%1", EXECUTABLE_NAME),
|
||||||
|
// 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
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,9 @@ public:
|
||||||
static QThread *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>
|
||||||
|
|
@ -119,6 +122,10 @@ 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();
|
||||||
|
|
@ -184,6 +191,7 @@ private:
|
||||||
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;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ 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/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
|
||||||
|
|
@ -99,5 +100,9 @@ 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)
|
||||||
|
|
|
||||||
|
|
@ -83,8 +83,19 @@ void AccountDeviceList::refreshDevices() {
|
||||||
auto requestDeviceList = [this] {
|
auto requestDeviceList = [this] {
|
||||||
if (!mAccountManagerServicesModelConnection) return;
|
if (!mAccountManagerServicesModelConnection) return;
|
||||||
mAccountManagerServicesModelConnection->invokeToModel([this]() {
|
mAccountManagerServicesModelConnection->invokeToModel([this]() {
|
||||||
|
auto connectedAccounts = CoreModel::getInstance()->getCore()->getAccountList();
|
||||||
auto identityAddress = mAccountCore->getModel()->getMonitor()->getParams()->getIdentityAddress();
|
auto identityAddress = mAccountCore->getModel()->getMonitor()->getParams()->getIdentityAddress();
|
||||||
auto authinfo = mAccountCore->getModel()->getMonitor()->findAuthInfo();
|
auto found = std::find_if(connectedAccounts.begin(), connectedAccounts.end(),
|
||||||
|
[identityAddress](std::shared_ptr<linphone::Account> account) {
|
||||||
|
return account && account->getParams()->getIdentityAddress()->weakEqual(
|
||||||
|
identityAddress);
|
||||||
|
});
|
||||||
|
if (found == connectedAccounts.end()) {
|
||||||
|
qDebug() << "[AccountDeviceList] account" << identityAddress->asStringUriOnly()
|
||||||
|
<< "not connected anymore, return";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// auto authinfo = mAccountCore->getModel()->getMonitor()->findAuthInfo();
|
||||||
qDebug() << "[AccountDeviceList] request devices for address" << identityAddress->asStringUriOnly();
|
qDebug() << "[AccountDeviceList] request devices for address" << identityAddress->asStringUriOnly();
|
||||||
mAccountManagerServicesModel->getDeviceList(identityAddress);
|
mAccountManagerServicesModel->getDeviceList(identityAddress);
|
||||||
});
|
});
|
||||||
|
|
@ -150,14 +161,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,
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,6 @@ 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;
|
||||||
mMicrophoneMuted = call->getMicrophoneMuted();
|
|
||||||
mSpeakerMuted = call->getSpeakerMuted();
|
|
||||||
auto videoDirection = call->getParams()->getVideoDirection();
|
auto videoDirection = call->getParams()->getVideoDirection();
|
||||||
mLocalVideoEnabled =
|
mLocalVideoEnabled =
|
||||||
videoDirection == linphone::MediaDirection::SendOnly || videoDirection == linphone::MediaDirection::SendRecv;
|
videoDirection == linphone::MediaDirection::SendOnly || videoDirection == linphone::MediaDirection::SendRecv;
|
||||||
|
|
@ -158,6 +156,8 @@ 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;
|
||||||
|
|
||||||
|
|
@ -208,10 +208,11 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
mCallModelConnection->invokeToCore([this, recording]() {
|
mCallModelConnection->invokeToCore([this, recording]() {
|
||||||
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(QString::fromStdString(mCallModel->getRecordFile())),
|
tr("call_record_saved_in_file_message")
|
||||||
|
.arg(QString::fromStdString(mCallModel->getRecordFile())),
|
||||||
true, App::getInstance()->getCallsWindow());
|
true, App::getInstance()->getCallsWindow());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -308,8 +309,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();
|
||||||
|
|
@ -321,7 +322,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); });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -388,23 +389,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) {
|
||||||
|
|
@ -414,15 +415,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());
|
||||||
}
|
}
|
||||||
|
|
@ -430,14 +431,14 @@ 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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -198,15 +198,6 @@ void ConferenceInfoCore::setSelf(QSharedPointer<ConferenceInfoCore> me) {
|
||||||
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(
|
||||||
|
|
|
||||||
|
|
@ -99,9 +99,6 @@ void ConferenceInfoList::setSelf(QSharedPointer<ConferenceInfoList> me) {
|
||||||
// conference (which must hidden)
|
// conference (which must hidden)
|
||||||
mCoreModelConnection->makeConnectToModel(&CoreModel::defaultAccountChanged, [this]() { emit lUpdate(true); });
|
mCoreModelConnection->makeConnectToModel(&CoreModel::defaultAccountChanged, [this]() { emit lUpdate(true); });
|
||||||
|
|
||||||
mCoreModelConnection->makeConnectToModel(
|
|
||||||
&CoreModel::conferenceInfoCreated,
|
|
||||||
[this](const std::shared_ptr<linphone::ConferenceInfo> &confInfo) { addConference(confInfo); });
|
|
||||||
mCoreModelConnection->makeConnectToModel(
|
mCoreModelConnection->makeConnectToModel(
|
||||||
&CoreModel::conferenceInfoReceived,
|
&CoreModel::conferenceInfoReceived,
|
||||||
[this](const std::shared_ptr<linphone::Core> &core,
|
[this](const std::shared_ptr<linphone::Core> &core,
|
||||||
|
|
@ -236,7 +233,9 @@ 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) {
|
||||||
return Utils::toDateMonthString(mList[row].objectCast<ConferenceInfoCore>()->getDateTimeUtc());
|
auto date = 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) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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();
|
||||||
|
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)
|
||||||
|
return getEventCount();
|
||||||
|
// else {
|
||||||
|
// auto currentAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
|
||||||
|
// if (currentAccount) {
|
||||||
|
// auto linphoneChatRooms = currentAccount->filterChatRooms("");
|
||||||
|
// for (const auto &chatRoom : linphoneChatRooms) {
|
||||||
|
// count += chatRoom->getUnreadMessagesCount();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return count;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* 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_
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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_
|
||||||
30
Linphone/core/event-count-notifier/EventCountNotifierMacOs.m
Normal file
30
Linphone/core/event-count-notifier/EventCountNotifierMacOs.m
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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_
|
||||||
|
|
@ -445,8 +445,9 @@ QList<QVariant> FriendCore::getAllAddresses() const {
|
||||||
auto phoneNumbers = mPhoneNumberList;
|
auto phoneNumbers = mPhoneNumberList;
|
||||||
while (addressIt != mAddressList.end()) {
|
while (addressIt != mAddressList.end()) {
|
||||||
auto username = Utils::getUsername(addressIt->toMap()["address"].toString());
|
auto username = Utils::getUsername(addressIt->toMap()["address"].toString());
|
||||||
std::remove_if(phoneNumbers.begin(), phoneNumbers.end(),
|
phoneNumbers.erase(std::remove_if(phoneNumbers.begin(), phoneNumbers.end(),
|
||||||
[username](const QVariant &data) { return data.toMap()["address"].toString() == username; });
|
[username](const QVariant &data) { return data.toMap()["address"].toString() == username; })
|
||||||
|
, phoneNumbers.end());
|
||||||
++addressIt;
|
++addressIt;
|
||||||
}
|
}
|
||||||
addresses << phoneNumbers;
|
addresses << phoneNumbers;
|
||||||
|
|
|
||||||
|
|
@ -171,28 +171,24 @@ 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) {
|
||||||
int *screenHeightOffset = &mScreenHeightOffset[screen->name()]; // Access optimization
|
auto screenHeightOffset =
|
||||||
|
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(heightOffset - (*screenHeightOffset % heightOffset));
|
window->setY(availableGeometry.y() + availableGeometry.height() - screenHeightOffset -
|
||||||
|
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());
|
||||||
QObject::connect(window, &QQuickWindow::closing, window,
|
auto screenHeightOffset =
|
||||||
[this, window] { deleteNotification(QVariant::fromValue(window)); });
|
screen ? mScreenHeightOffset.take(screen->name()) : 0; // Access optimization
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,10 +115,13 @@ void MagicSearchList::setSelf(QSharedPointer<MagicSearchList> me) {
|
||||||
splitted.removeFirst();
|
splitted.removeFirst();
|
||||||
contact->setFamilyName(splitted.join(" "));
|
contact->setFamilyName(splitted.join(" "));
|
||||||
} else {
|
} else {
|
||||||
contact->setGivenName(Utils::coreStringToAppString(address->getUsername()));
|
contact->setGivenName(displayName.isEmpty()
|
||||||
|
? Utils::coreStringToAppString(address->getUsername())
|
||||||
|
: displayName);
|
||||||
}
|
}
|
||||||
contact->setDefaultFullAddress(Utils::coreStringToAppString(
|
contact->setDefaultFullAddress(Utils::coreStringToAppString(
|
||||||
address->asString())); // linphone Friend object remove specific address.
|
address->asString())); // linphone Friend object remove specific address.
|
||||||
|
contact->setDefaultAddress(Utils::coreStringToAppString(address->asString()));
|
||||||
contacts->append(contact);
|
contacts->append(contact);
|
||||||
} else if (!it->getPhoneNumber().empty()) {
|
} else if (!it->getPhoneNumber().empty()) {
|
||||||
auto phoneNumber = it->getPhoneNumber();
|
auto phoneNumber = it->getPhoneNumber();
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ SettingsCore::SettingsCore(QObject *parent) : QObject(parent) {
|
||||||
INIT_CORE_MEMBER(AssistantDisableQrCode, settingsModel)
|
INIT_CORE_MEMBER(AssistantDisableQrCode, settingsModel)
|
||||||
|
|
||||||
INIT_CORE_MEMBER(AssistantHideThirdPartyAccount, settingsModel)
|
INIT_CORE_MEMBER(AssistantHideThirdPartyAccount, settingsModel)
|
||||||
INIT_CORE_MEMBER(OnlyDisplaySipUriUsername, settingsModel)
|
INIT_CORE_MEMBER(HideSipAddresses, settingsModel)
|
||||||
INIT_CORE_MEMBER(DarkModeAllowed, settingsModel)
|
INIT_CORE_MEMBER(DarkModeAllowed, settingsModel)
|
||||||
INIT_CORE_MEMBER(MaxAccount, settingsModel)
|
INIT_CORE_MEMBER(MaxAccount, settingsModel)
|
||||||
INIT_CORE_MEMBER(AssistantGoDirectlyToThirdPartySipAccountLogin, settingsModel)
|
INIT_CORE_MEMBER(AssistantGoDirectlyToThirdPartySipAccountLogin, settingsModel)
|
||||||
|
|
@ -179,7 +179,7 @@ SettingsCore::SettingsCore(const SettingsCore &settingsCore) {
|
||||||
mAssistantDisableQrCode = settingsCore.mAssistantDisableQrCode;
|
mAssistantDisableQrCode = settingsCore.mAssistantDisableQrCode;
|
||||||
|
|
||||||
mAssistantHideThirdPartyAccount = settingsCore.mAssistantHideThirdPartyAccount;
|
mAssistantHideThirdPartyAccount = settingsCore.mAssistantHideThirdPartyAccount;
|
||||||
mOnlyDisplaySipUriUsername = settingsCore.mOnlyDisplaySipUriUsername;
|
mHideSipAddresses = settingsCore.mHideSipAddresses;
|
||||||
mDarkModeAllowed = settingsCore.mDarkModeAllowed;
|
mDarkModeAllowed = settingsCore.mDarkModeAllowed;
|
||||||
mMaxAccount = settingsCore.mMaxAccount;
|
mMaxAccount = settingsCore.mMaxAccount;
|
||||||
mAssistantGoDirectlyToThirdPartySipAccountLogin = settingsCore.mAssistantGoDirectlyToThirdPartySipAccountLogin;
|
mAssistantGoDirectlyToThirdPartySipAccountLogin = settingsCore.mAssistantGoDirectlyToThirdPartySipAccountLogin;
|
||||||
|
|
@ -206,6 +206,13 @@ void SettingsCore::setSelf(QSharedPointer<SettingsCore> me) {
|
||||||
mustBeInLinphoneThread(getClassName());
|
mustBeInLinphoneThread(getClassName());
|
||||||
mSettingsModelConnection = SafeConnection<SettingsCore, SettingsModel>::create(me, SettingsModel::getInstance());
|
mSettingsModelConnection = SafeConnection<SettingsCore, SettingsModel>::create(me, SettingsModel::getInstance());
|
||||||
|
|
||||||
|
mSettingsModelConnection->makeConnectToModel(&SettingsModel::captureGraphRunningChanged, [this](bool running) {
|
||||||
|
mSettingsModelConnection->invokeToCore([this, running] {
|
||||||
|
mCaptureGraphRunning = running;
|
||||||
|
emit captureGraphRunningChanged(running);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// VFS
|
// VFS
|
||||||
mSettingsModelConnection->makeConnectToModel(&SettingsModel::vfsEnabledChanged, [this](const bool enabled) {
|
mSettingsModelConnection->makeConnectToModel(&SettingsModel::vfsEnabledChanged, [this](const bool enabled) {
|
||||||
mSettingsModelConnection->invokeToCore([this, enabled]() { setVfsEnabled(enabled); });
|
mSettingsModelConnection->invokeToCore([this, enabled]() { setVfsEnabled(enabled); });
|
||||||
|
|
@ -379,7 +386,7 @@ void SettingsCore::setSelf(QSharedPointer<SettingsCore> me) {
|
||||||
DEFINE_CORE_GETSET_CONNECT(mSettingsModelConnection, SettingsCore, SettingsModel, settingsModel, bool,
|
DEFINE_CORE_GETSET_CONNECT(mSettingsModelConnection, SettingsCore, SettingsModel, settingsModel, bool,
|
||||||
assistantHideThirdPartyAccount, AssistantHideThirdPartyAccount)
|
assistantHideThirdPartyAccount, AssistantHideThirdPartyAccount)
|
||||||
DEFINE_CORE_GETSET_CONNECT(mSettingsModelConnection, SettingsCore, SettingsModel, settingsModel, bool,
|
DEFINE_CORE_GETSET_CONNECT(mSettingsModelConnection, SettingsCore, SettingsModel, settingsModel, bool,
|
||||||
onlyDisplaySipUriUsername, OnlyDisplaySipUriUsername)
|
hideSipAddresses, HideSipAddresses)
|
||||||
DEFINE_CORE_GETSET_CONNECT(mSettingsModelConnection, SettingsCore, SettingsModel, settingsModel, bool,
|
DEFINE_CORE_GETSET_CONNECT(mSettingsModelConnection, SettingsCore, SettingsModel, settingsModel, bool,
|
||||||
darkModeAllowed, DarkModeAllowed)
|
darkModeAllowed, DarkModeAllowed)
|
||||||
DEFINE_CORE_GETSET_CONNECT(mSettingsModelConnection, SettingsCore, SettingsModel, settingsModel, int, maxAccount,
|
DEFINE_CORE_GETSET_CONNECT(mSettingsModelConnection, SettingsCore, SettingsModel, settingsModel, int, maxAccount,
|
||||||
|
|
@ -487,7 +494,7 @@ void SettingsCore::reset(const SettingsCore &settingsCore) {
|
||||||
setAssistantDisableQrCode(settingsCore.mAssistantDisableQrCode);
|
setAssistantDisableQrCode(settingsCore.mAssistantDisableQrCode);
|
||||||
|
|
||||||
setAssistantHideThirdPartyAccount(settingsCore.mAssistantHideThirdPartyAccount);
|
setAssistantHideThirdPartyAccount(settingsCore.mAssistantHideThirdPartyAccount);
|
||||||
setOnlyDisplaySipUriUsername(settingsCore.mOnlyDisplaySipUriUsername);
|
setHideSipAddresses(settingsCore.mHideSipAddresses);
|
||||||
setDarkModeAllowed(settingsCore.mDarkModeAllowed);
|
setDarkModeAllowed(settingsCore.mDarkModeAllowed);
|
||||||
setMaxAccount(settingsCore.mMaxAccount);
|
setMaxAccount(settingsCore.mMaxAccount);
|
||||||
setAssistantGoDirectlyToThirdPartySipAccountLogin(settingsCore.mAssistantGoDirectlyToThirdPartySipAccountLogin);
|
setAssistantGoDirectlyToThirdPartySipAccountLogin(settingsCore.mAssistantGoDirectlyToThirdPartySipAccountLogin);
|
||||||
|
|
@ -560,7 +567,7 @@ QVariantList SettingsCore::getPlaybackDevices() const {
|
||||||
|
|
||||||
void SettingsCore::setPlaybackDevices(QVariantList devices) {
|
void SettingsCore::setPlaybackDevices(QVariantList devices) {
|
||||||
mPlaybackDevices = devices;
|
mPlaybackDevices = devices;
|
||||||
emit captureDevicesChanged(devices);
|
emit playbackDevicesChanged(devices);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantList SettingsCore::getRingerDevices() const {
|
QVariantList SettingsCore::getRingerDevices() const {
|
||||||
|
|
@ -958,7 +965,7 @@ void SettingsCore::writeIntoModel(std::shared_ptr<SettingsModel> model) const {
|
||||||
model->setAssistantDisableQrCode(mAssistantDisableQrCode);
|
model->setAssistantDisableQrCode(mAssistantDisableQrCode);
|
||||||
|
|
||||||
model->setAssistantHideThirdPartyAccount(mAssistantHideThirdPartyAccount);
|
model->setAssistantHideThirdPartyAccount(mAssistantHideThirdPartyAccount);
|
||||||
model->setOnlyDisplaySipUriUsername(mOnlyDisplaySipUriUsername);
|
model->setHideSipAddresses(mHideSipAddresses);
|
||||||
model->setDarkModeAllowed(mDarkModeAllowed);
|
model->setDarkModeAllowed(mDarkModeAllowed);
|
||||||
model->setMaxAccount(mMaxAccount);
|
model->setMaxAccount(mMaxAccount);
|
||||||
model->setAssistantGoDirectlyToThirdPartySipAccountLogin(mAssistantGoDirectlyToThirdPartySipAccountLogin);
|
model->setAssistantGoDirectlyToThirdPartySipAccountLogin(mAssistantGoDirectlyToThirdPartySipAccountLogin);
|
||||||
|
|
@ -1024,7 +1031,7 @@ void SettingsCore::writeFromModel(const std::shared_ptr<SettingsModel> &model) {
|
||||||
mAssistantDisableQrCode = model->getAssistantDisableQrCode();
|
mAssistantDisableQrCode = model->getAssistantDisableQrCode();
|
||||||
|
|
||||||
mAssistantHideThirdPartyAccount = model->getAssistantHideThirdPartyAccount();
|
mAssistantHideThirdPartyAccount = model->getAssistantHideThirdPartyAccount();
|
||||||
mOnlyDisplaySipUriUsername = model->getOnlyDisplaySipUriUsername();
|
mHideSipAddresses = model->getHideSipAddresses();
|
||||||
mDarkModeAllowed = model->getDarkModeAllowed();
|
mDarkModeAllowed = model->getDarkModeAllowed();
|
||||||
mMaxAccount = model->getMaxAccount();
|
mMaxAccount = model->getMaxAccount();
|
||||||
mAssistantGoDirectlyToThirdPartySipAccountLogin = model->getAssistantGoDirectlyToThirdPartySipAccountLogin();
|
mAssistantGoDirectlyToThirdPartySipAccountLogin = model->getAssistantGoDirectlyToThirdPartySipAccountLogin();
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,7 @@ public:
|
||||||
DECLARE_CORE_GETSET_MEMBER(bool, assistantHideCreateAccount, AssistantHideCreateAccount)
|
DECLARE_CORE_GETSET_MEMBER(bool, assistantHideCreateAccount, AssistantHideCreateAccount)
|
||||||
DECLARE_CORE_GETSET_MEMBER(bool, assistantDisableQrCode, AssistantDisableQrCode)
|
DECLARE_CORE_GETSET_MEMBER(bool, assistantDisableQrCode, AssistantDisableQrCode)
|
||||||
DECLARE_CORE_GETSET_MEMBER(bool, assistantHideThirdPartyAccount, AssistantHideThirdPartyAccount)
|
DECLARE_CORE_GETSET_MEMBER(bool, assistantHideThirdPartyAccount, AssistantHideThirdPartyAccount)
|
||||||
DECLARE_CORE_GETSET_MEMBER(bool, onlyDisplaySipUriUsername, OnlyDisplaySipUriUsername)
|
DECLARE_CORE_GETSET_MEMBER(bool, hideSipAddresses, HideSipAddresses)
|
||||||
DECLARE_CORE_GETSET_MEMBER(bool, darkModeAllowed, DarkModeAllowed)
|
DECLARE_CORE_GETSET_MEMBER(bool, darkModeAllowed, DarkModeAllowed)
|
||||||
DECLARE_CORE_GETSET_MEMBER(int, maxAccount, MaxAccount)
|
DECLARE_CORE_GETSET_MEMBER(int, maxAccount, MaxAccount)
|
||||||
DECLARE_CORE_GETSET_MEMBER(bool,
|
DECLARE_CORE_GETSET_MEMBER(bool,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M13.75 20C13.75 20.1989 13.671 20.3897 13.5303 20.5303C13.3897 20.671 13.1989 20.75 13 20.75H7.00002C6.80111 20.75 6.61034 20.671 6.46969 20.5303C6.32904 20.3897 6.25002 20.1989 6.25002 20C6.25002 19.8011 6.32904 19.6103 6.46969 19.4697C6.61034 19.329 6.80111 19.25 7.00002 19.25H13C13.1989 19.25 13.3897 19.329 13.5303 19.4697C13.671 19.6103 13.75 19.8011 13.75 20ZM19.3178 4.65499C18.4749 3.00748 17.2092 1.61364 15.6503 0.616239C15.567 0.563035 15.4741 0.526817 15.3767 0.509668C15.2794 0.492519 15.1796 0.494776 15.0832 0.516311C14.9867 0.537846 14.8955 0.578233 14.8147 0.635151C14.7339 0.692069 14.6651 0.764396 14.6124 0.847973C14.5596 0.931549 14.5239 1.02473 14.5073 1.12215C14.4906 1.21958 14.4934 1.31933 14.5155 1.41567C14.5376 1.51201 14.5784 1.60304 14.6358 1.68353C14.6931 1.76402 14.7658 1.83238 14.8497 1.88468C16.1871 2.73546 17.2707 3.93076 17.9866 5.34499C18.0812 5.51593 18.2388 5.64321 18.4258 5.69974C18.6128 5.75628 18.8145 5.73761 18.9879 5.6477C19.1614 5.5578 19.2929 5.40376 19.3545 5.21836C19.4161 5.03296 19.403 4.83083 19.3178 4.65499ZM1.34783 5.74999C1.48523 5.74993 1.61998 5.71213 1.73736 5.64071C1.85474 5.56929 1.95025 5.46699 2.01346 5.34499C2.72933 3.93076 3.81291 2.73546 5.15033 1.88468C5.23419 1.83238 5.30689 1.76402 5.36424 1.68353C5.4216 1.60304 5.46248 1.51201 5.48454 1.41567C5.50659 1.31933 5.50939 1.21958 5.49277 1.12215C5.47615 1.02473 5.44043 0.931549 5.38768 0.847973C5.33493 0.764396 5.26617 0.692069 5.18538 0.635151C5.10458 0.578233 5.01333 0.537846 4.91687 0.516311C4.82041 0.494776 4.72065 0.492519 4.62331 0.509668C4.52598 0.526817 4.433 0.563035 4.34971 0.616239C2.79085 1.61364 1.52514 3.00748 0.682206 4.65499C0.622991 4.76929 0.594192 4.8969 0.598581 5.02556C0.602969 5.15421 0.640397 5.27957 0.707263 5.38957C0.774128 5.49956 0.868181 5.5905 0.980369 5.65363C1.09256 5.71675 1.2191 5.74994 1.34783 5.74999ZM18.7947 15.4944C18.9276 15.7222 18.998 15.9811 18.9989 16.2448C18.9998 16.5086 18.9312 16.7679 18.7999 16.9967C18.6686 17.2255 18.4793 17.4156 18.251 17.5478C18.0228 17.6801 17.7638 17.7498 17.5 17.75H2.50002C2.23641 17.7495 1.9776 17.6795 1.74965 17.5471C1.5217 17.4147 1.33266 17.2246 1.20158 16.9959C1.0705 16.7672 1.002 16.508 1.00299 16.2444C1.00398 15.9808 1.07441 15.7221 1.20721 15.4944C2.05189 14.0366 2.50002 11.9637 2.50002 9.49999C2.50002 7.51087 3.29019 5.60321 4.69672 4.19669C6.10324 2.79017 8.01089 1.99999 10 1.99999C11.9891 1.99999 13.8968 2.79017 15.3033 4.19669C16.7098 5.60321 17.5 7.51087 17.5 9.49999C17.5 11.9628 17.9481 14.0356 18.7947 15.4944ZM17.5 16.25C16.5025 14.5372 16 12.2666 16 9.49999C16 7.90869 15.3679 6.38257 14.2427 5.25735C13.1174 4.13213 11.5913 3.49999 10 3.49999C8.40872 3.49999 6.8826 4.13213 5.75738 5.25735C4.63216 6.38257 4.00002 7.90869 4.00002 9.49999C4.00002 12.2675 3.49564 14.5381 2.50002 16.25H17.5Z" fill="#000000"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.9 KiB |
1
Linphone/data/image/bell-ringing.svg
Normal file
1
Linphone/data/image/bell-ringing.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M224,71.1a8,8,0,0,1-10.78-3.42,94.13,94.13,0,0,0-33.46-36.91,8,8,0,1,1,8.54-13.54,111.46,111.46,0,0,1,39.12,43.09A8,8,0,0,1,224,71.1ZM35.71,72a8,8,0,0,0,7.1-4.32A94.13,94.13,0,0,1,76.27,30.77a8,8,0,1,0-8.54-13.54A111.46,111.46,0,0,0,28.61,60.32,8,8,0,0,0,35.71,72Zm186.1,103.94A16,16,0,0,1,208,200H167.2a40,40,0,0,1-78.4,0H48a16,16,0,0,1-13.79-24.06C43.22,160.39,48,138.28,48,112a80,80,0,0,1,160,0C208,138.27,212.78,160.38,221.81,175.94ZM150.62,200H105.38a24,24,0,0,0,45.24,0ZM208,184c-10.64-18.27-16-42.49-16-72a64,64,0,0,0-128,0c0,29.52-5.38,53.74-16,72Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 680 B |
|
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M168,224a8,8,0,0,1-8,8H96a8,8,0,1,1,0-16h64A8,8,0,0,1,168,224Zm53.85-32A15.8,15.8,0,0,1,208,200H48a16,16,0,0,1-13.8-24.06C39.75,166.38,48,139.34,48,104a80,80,0,1,1,160,0c0,35.33,8.26,62.38,13.81,71.94A15.89,15.89,0,0,1,221.84,192ZM208,184c-7.73-13.27-16-43.95-16-80a64,64,0,1,0-128,0c0,36.06-8.28,66.74-16,80Z"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 433 B |
1
Linphone/data/image/bell.svg
Normal file
1
Linphone/data/image/bell.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M221.8,175.94C216.25,166.38,208,139.33,208,104a80,80,0,1,0-160,0c0,35.34-8.26,62.38-13.81,71.94A16,16,0,0,0,48,200H88.81a40,40,0,0,0,78.38,0H208a16,16,0,0,0,13.8-24.06ZM128,216a24,24,0,0,1-22.62-16h45.24A24,24,0,0,1,128,216ZM48,184c7.7-13.24,16-43.92,16-80a64,64,0,1,1,128,0c0,36.05,8.28,66.73,16,80Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 424 B |
5454
Linphone/data/languages/cs.ts
Normal file
5454
Linphone/data/languages/cs.ts
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
5436
Linphone/data/languages/eu.ts
Normal file
5436
Linphone/data/languages/eu.ts
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
5436
Linphone/data/languages/pt.ts
Normal file
5436
Linphone/data/languages/pt.ts
Normal file
File diff suppressed because it is too large
Load diff
5436
Linphone/data/languages/pt_BR.ts
Normal file
5436
Linphone/data/languages/pt_BR.ts
Normal file
File diff suppressed because it is too large
Load diff
5454
Linphone/data/languages/ru.ts
Normal file
5454
Linphone/data/languages/ru.ts
Normal file
File diff suppressed because it is too large
Load diff
5454
Linphone/data/languages/uk.ts
Normal file
5454
Linphone/data/languages/uk.ts
Normal file
File diff suppressed because it is too large
Load diff
5426
Linphone/data/languages/zh_Hans.ts
Normal file
5426
Linphone/data/languages/zh_Hans.ts
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -75,21 +75,41 @@ OIDCModel::OIDCModel(const std::shared_ptr<linphone::AuthInfo> &authInfo, QObjec
|
||||||
qDebug() << "OIDC Client ID set to [" << clientid << "]";
|
qDebug() << "OIDC Client ID set to [" << clientid << "]";
|
||||||
|
|
||||||
// find an auth info from LinphoneCore where username = clientid
|
// find an auth info from LinphoneCore where username = clientid
|
||||||
auto clientSecret = CoreModel::getInstance()->getCore()->findAuthInfo("", clientid.toStdString(), "");
|
std::shared_ptr<linphone::AuthInfo> clientSecret = nullptr;
|
||||||
if (clientSecret != nullptr) {
|
// search for auth info for this client id
|
||||||
qDebug() << "client secret found for client id [" << clientid << "]";
|
for (const auto &authInfo : CoreModel::getInstance()->getCore()->getAuthInfoList()) {
|
||||||
mOidc.setClientIdentifierSharedKey(clientSecret->getPassword().c_str());
|
if (authInfo->getClientId() == clientid.toStdString()) {
|
||||||
|
qDebug() << "AuthInfo found for client id [" << clientid << "]";
|
||||||
|
clientSecret = authInfo;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString scope = OIDCScope;
|
if (clientSecret != nullptr) {
|
||||||
;
|
qDebug() << "client secret found for client id [" << clientid << "]";
|
||||||
|
mOidc.setClientIdentifierSharedKey(clientSecret->getClientSecret().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<QByteArray> scopeTokens;
|
||||||
if (autorizationUrl.hasQuery()) {
|
if (autorizationUrl.hasQuery()) {
|
||||||
QUrlQuery query(autorizationUrl);
|
QUrlQuery query(autorizationUrl);
|
||||||
if (query.hasQueryItem("scope")) {
|
if (query.hasQueryItem("scope")) {
|
||||||
scope = query.queryItemValue("scope");
|
auto scopeList = query.queryItemValue("scope").split(' ');
|
||||||
|
for (const auto &scopeItem : scopeList) {
|
||||||
|
scopeTokens.insert(scopeItem.toUtf8());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mOidc.setScope(scope);
|
if (scopeTokens.isEmpty()) {
|
||||||
|
scopeTokens.insert(OIDCScope);
|
||||||
|
qDebug() << "No scope found in authorization URL, using default scope [" << OIDCScope << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||||
|
mOidc.setRequestedScopeTokens(scopeTokens);
|
||||||
|
#else
|
||||||
|
mOidc.setScope(QStringList(scopeTokens.begin(), scopeTokens.end()).join(' '));
|
||||||
|
#endif
|
||||||
mTimeout.setInterval(1000 * 60 * 2); // 2minutes
|
mTimeout.setInterval(1000 * 60 * 2); // 2minutes
|
||||||
|
|
||||||
connect(&mTimeout, &QTimer::timeout, [this]() {
|
connect(&mTimeout, &QTimer::timeout, [this]() {
|
||||||
|
|
@ -189,10 +209,34 @@ OIDCModel::OIDCModel(const std::shared_ptr<linphone::AuthInfo> &authInfo, QObjec
|
||||||
|
|
||||||
connect(this, &OIDCModel::authenticated, this, &OIDCModel::setBearers);
|
connect(this, &OIDCModel::authenticated, this, &OIDCModel::setBearers);
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
|
||||||
|
// Connect the signal to the tokensReceived handler to get id_token
|
||||||
|
connect(mOidc.replyHandler(), &QOAuthHttpServerReplyHandler::tokensReceived, this,
|
||||||
|
[this](const QVariantMap &tokens) {
|
||||||
|
// for (auto it = tokens.cbegin(); it != tokens.cend(); ++it) {
|
||||||
|
// qDebug() << "Token key:" << it.key() << ", value:" << it.value().toString();
|
||||||
|
// }
|
||||||
|
if (tokens.contains("id_token") &&
|
||||||
|
CoreModel::getInstance()->getCore()->getConfig()->getBool("app", "oidc_use_id_token", false)) {
|
||||||
|
auto idToken = tokens["id_token"].toString();
|
||||||
|
qDebug() << "ID Token received:" << idToken.left(3) + "..." + idToken.right(3);
|
||||||
|
mIdToken = idToken;
|
||||||
|
} else if (tokens.contains("access_token")) {
|
||||||
|
auto accessToken = tokens["access_token"].toString();
|
||||||
|
qDebug() << "Access Token received:" << accessToken.left(3) + "..." + accessToken.right(3);
|
||||||
|
mIdToken = accessToken;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
mIdToken.clear();
|
||||||
|
qWarning() << "No ID Token or Access Token found in the tokens.";
|
||||||
|
emit requestFailed(tr("oidc_authentication_no_token_found_error"));
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
#endif
|
||||||
// in case we want to add parameters. Needed to override redirect_url
|
// in case we want to add parameters. Needed to override redirect_url
|
||||||
mOidc.setModifyParametersFunction([&, username = Utils::coreStringToAppString(authInfo->getUsername())](
|
mOidc.setModifyParametersFunction([&, username = Utils::coreStringToAppString(authInfo->getUsername())](
|
||||||
QAbstractOAuth::Stage stage, QMultiMap<QString, QVariant> *parameters) {
|
QAbstractOAuth::Stage stage, QMultiMap<QString, QVariant> *parameters) {
|
||||||
parameters->insert("login_hint", username);
|
|
||||||
parameters->replace("application_type", "native");
|
parameters->replace("application_type", "native");
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case QAbstractOAuth::Stage::RequestingAccessToken: {
|
case QAbstractOAuth::Stage::RequestingAccessToken: {
|
||||||
|
|
@ -244,7 +288,11 @@ void OIDCModel::openIdConfigReceived() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (rootArray.contains("token_endpoint")) {
|
if (rootArray.contains("token_endpoint")) {
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||||
|
mOidc.setTokenUrl(QUrl(rootArray["token_endpoint"].toString()));
|
||||||
|
#else
|
||||||
mOidc.setAccessTokenUrl(QUrl(rootArray["token_endpoint"].toString()));
|
mOidc.setAccessTokenUrl(QUrl(rootArray["token_endpoint"].toString()));
|
||||||
|
#endif
|
||||||
mAuthInfo->setTokenEndpointUri(
|
mAuthInfo->setTokenEndpointUri(
|
||||||
Utils::appStringToCoreString(QUrl(rootArray["token_endpoint"].toString()).toString()));
|
Utils::appStringToCoreString(QUrl(rootArray["token_endpoint"].toString()).toString()));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -262,13 +310,35 @@ void OIDCModel::setBearers() {
|
||||||
auto expiration = QDateTime::currentDateTime().secsTo(mOidc.expirationAt());
|
auto expiration = QDateTime::currentDateTime().secsTo(mOidc.expirationAt());
|
||||||
auto timeT = mOidc.expirationAt().toSecsSinceEpoch();
|
auto timeT = mOidc.expirationAt().toSecsSinceEpoch();
|
||||||
qDebug() << "Authenticated for " << expiration << "s";
|
qDebug() << "Authenticated for " << expiration << "s";
|
||||||
auto refreshBearer =
|
|
||||||
linphone::Factory::get()->createBearerToken(Utils::appStringToCoreString(mOidc.refreshToken()), timeT);
|
|
||||||
|
|
||||||
auto accessBearer = linphone::Factory::get()->createBearerToken(Utils::appStringToCoreString(mOidc.token()), timeT);
|
auto accessBearer = linphone::Factory::get()->createBearerToken(Utils::appStringToCoreString(idToken()), timeT);
|
||||||
mAuthInfo->setRefreshToken(refreshBearer);
|
|
||||||
mAuthInfo->setAccessToken(accessBearer);
|
mAuthInfo->setAccessToken(accessBearer);
|
||||||
|
|
||||||
|
if (mOidc.refreshToken() != nullptr) {
|
||||||
|
|
||||||
|
auto refreshBearer =
|
||||||
|
linphone::Factory::get()->createBearerToken(Utils::appStringToCoreString(mOidc.refreshToken()), timeT);
|
||||||
|
mAuthInfo->setRefreshToken(refreshBearer);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
qWarning() << "No refresh token found";
|
||||||
|
}
|
||||||
CoreModel::getInstance()->getCore()->addAuthInfo(mAuthInfo);
|
CoreModel::getInstance()->getCore()->addAuthInfo(mAuthInfo);
|
||||||
emit CoreModel::getInstance()->bearerAccountAdded();
|
emit CoreModel::getInstance() -> bearerAccountAdded();
|
||||||
emit finished();
|
emit finished();
|
||||||
}
|
}
|
||||||
|
QString OIDCModel::idToken() const {
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||||
|
if (CoreModel::getInstance()->getCore()->getConfig()->getBool("app", "oidc_use_id_token", false)) {
|
||||||
|
if (!mOidc.idToken().isEmpty()) {
|
||||||
|
return mOidc.idToken();
|
||||||
|
} else {
|
||||||
|
return mOidc.token();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return mOidc.token();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return mIdToken;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
@ -44,11 +44,26 @@ signals:
|
||||||
void finished();
|
void finished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the ID token.
|
||||||
|
*
|
||||||
|
* This function returns the ID token as a QString. The ID token is typically
|
||||||
|
* used for authentication and authorization purposes in OpenID Connect (OIDC)
|
||||||
|
* workflows. Implementation is specific to QT version
|
||||||
|
*
|
||||||
|
* @return The ID token as a QString.
|
||||||
|
*/
|
||||||
|
QString idToken() const;
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
|
||||||
|
QString mIdToken;
|
||||||
|
#endif
|
||||||
QOAuth2AuthorizationCodeFlow mOidc;
|
QOAuth2AuthorizationCodeFlow mOidc;
|
||||||
std::shared_ptr<linphone::AuthInfo> mAuthInfo;
|
std::shared_ptr<linphone::AuthInfo> mAuthInfo;
|
||||||
QTimer mTimeout;
|
QTimer mTimeout;
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -116,8 +116,10 @@ void CallModel::terminateAllCalls() {
|
||||||
|
|
||||||
void CallModel::setMicrophoneMuted(bool isMuted) {
|
void CallModel::setMicrophoneMuted(bool isMuted) {
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
mMonitor->setMicrophoneMuted(isMuted);
|
if (mMonitor->getConference()) mMonitor->getConference()->setMicrophoneMuted(isMuted);
|
||||||
emit microphoneMutedChanged(isMuted);
|
else mMonitor->setMicrophoneMuted(isMuted);
|
||||||
|
emit microphoneMutedChanged(mMonitor->getConference() ? mMonitor->getConference()->getMicrophoneMuted()
|
||||||
|
: mMonitor->getMicrophoneMuted());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallModel::setSpeakerMuted(bool isMuted) {
|
void CallModel::setSpeakerMuted(bool isMuted) {
|
||||||
|
|
@ -411,7 +413,7 @@ void CallModel::onStateChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
emit localVideoEnabledChanged(videoDirection == linphone::MediaDirection::SendOnly ||
|
emit localVideoEnabledChanged(videoDirection == linphone::MediaDirection::SendOnly ||
|
||||||
videoDirection == linphone::MediaDirection::SendRecv);
|
videoDirection == linphone::MediaDirection::SendRecv);
|
||||||
emit remoteVideoEnabledChanged(remoteVideoDirection == linphone::MediaDirection::SendOnly ||
|
emit remoteVideoEnabledChanged(remoteVideoDirection == linphone::MediaDirection::SendOnly ||
|
||||||
remoteVideoDirection == linphone::MediaDirection::SendRecv);
|
remoteVideoDirection == linphone::MediaDirection::SendRecv);
|
||||||
updateConferenceVideoLayout();
|
updateConferenceVideoLayout();
|
||||||
} else if (state == linphone::Call::State::End || state == linphone::Call::State::Error) {
|
} else if (state == linphone::Call::State::End || state == linphone::Call::State::Error) {
|
||||||
mDurationTimer.stop();
|
mDurationTimer.stop();
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,12 @@
|
||||||
#include "model/tool/ToolModel.hpp"
|
#include "model/tool/ToolModel.hpp"
|
||||||
#include "tool/Utils.hpp"
|
#include "tool/Utils.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(CoreModel)
|
DEFINE_ABSTRACT_OBJECT(CoreModel)
|
||||||
|
|
||||||
|
|
@ -85,9 +91,9 @@ void CoreModel::start() {
|
||||||
// Useful if the app was built without video support.
|
// Useful if the app was built without video support.
|
||||||
// (The capture/display attributes are reset by the core in this case.)
|
// (The capture/display attributes are reset by the core in this case.)
|
||||||
auto config = mCore->getConfig();
|
auto config = mCore->getConfig();
|
||||||
if (mCore->videoSupported()) {
|
if (!mCore->videoSupported()) {
|
||||||
config->setInt("video", "capture", 1);
|
config->setInt("video", "capture", 0);
|
||||||
config->setInt("video", "display", 1);
|
config->setInt("video", "display", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : set the real transport type when sdk will be updated
|
// TODO : set the real transport type when sdk will be updated
|
||||||
|
|
@ -116,18 +122,27 @@ void CoreModel::start() {
|
||||||
mCore->enableFriendListSubscription(true);
|
mCore->enableFriendListSubscription(true);
|
||||||
if (mCore->getLogCollectionUploadServerUrl().empty())
|
if (mCore->getLogCollectionUploadServerUrl().empty())
|
||||||
mCore->setLogCollectionUploadServerUrl(Constants::DefaultUploadLogsServer);
|
mCore->setLogCollectionUploadServerUrl(Constants::DefaultUploadLogsServer);
|
||||||
|
|
||||||
|
/// These 2 API should not be used as they manage internal gains insterad of those of the soundcard.
|
||||||
|
// Use playback/capture gain from capture graph and call only
|
||||||
|
mCore->setMicGainDb(0.0);
|
||||||
|
mCore->setPlaybackGainDb(0.0);
|
||||||
mIterateTimer->start();
|
mIterateTimer->start();
|
||||||
|
|
||||||
auto linphoneSearch = mCore->createMagicSearch();
|
auto linphoneSearch = mCore->createMagicSearch();
|
||||||
linphoneSearch->setLimitedSearch(true);
|
linphoneSearch->setLimitedSearch(true);
|
||||||
mMagicSearch = Utils::makeQObject_ptr<MagicSearchModel>(linphoneSearch);
|
mMagicSearch = Utils::makeQObject_ptr<MagicSearchModel>(linphoneSearch);
|
||||||
mMagicSearch->setSelf(mMagicSearch);
|
mMagicSearch->setSelf(mMagicSearch);
|
||||||
connect(mMagicSearch.get(), &MagicSearchModel::searchResultsReceived, this, [this] {
|
connect(mMagicSearch.get(), &MagicSearchModel::searchResultsReceived, this,
|
||||||
emit magicSearchResultReceived(mMagicSearch->mLastSearch);
|
[this] { emit magicSearchResultReceived(mMagicSearch->mLastSearch); });
|
||||||
});
|
mStarted = true;
|
||||||
}
|
}
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CoreModel::isInitialized() const {
|
||||||
|
return mStarted;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<CoreModel> CoreModel::getInstance() {
|
std::shared_ptr<CoreModel> CoreModel::getInstance() {
|
||||||
return gCoreModel;
|
return gCoreModel;
|
||||||
}
|
}
|
||||||
|
|
@ -352,10 +367,11 @@ void CoreModel::migrate() {
|
||||||
config->setInt(SettingsModel::UiSection, Constants::RcVersionName, Constants::RcVersionCurrent);
|
config->setInt(SettingsModel::UiSection, Constants::RcVersionName, Constants::RcVersionCurrent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreModel::searchInMagicSearch(QString filter, int sourceFlags,
|
void CoreModel::searchInMagicSearch(QString filter,
|
||||||
LinphoneEnums::MagicSearchAggregation aggregation,
|
int sourceFlags,
|
||||||
int maxResults) {
|
LinphoneEnums::MagicSearchAggregation aggregation,
|
||||||
mMagicSearch->search(filter, sourceFlags, aggregation, maxResults);
|
int maxResults) {
|
||||||
|
mMagicSearch->search(filter, sourceFlags, aggregation, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -446,6 +462,8 @@ void CoreModel::onConferenceStateChanged(const std::shared_ptr<linphone::Core> &
|
||||||
void CoreModel::onConfiguringStatus(const std::shared_ptr<linphone::Core> &core,
|
void CoreModel::onConfiguringStatus(const std::shared_ptr<linphone::Core> &core,
|
||||||
linphone::ConfiguringState status,
|
linphone::ConfiguringState status,
|
||||||
const std::string &message) {
|
const std::string &message) {
|
||||||
|
mConfigStatus = status;
|
||||||
|
mConfigMessage = Utils::coreStringToAppString(message);
|
||||||
emit configuringStatus(core, status, message);
|
emit configuringStatus(core, status, message);
|
||||||
}
|
}
|
||||||
void CoreModel::onDefaultAccountChanged(const std::shared_ptr<linphone::Core> &core,
|
void CoreModel::onDefaultAccountChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <linphone++/linphone.hh>
|
#include <linphone++/linphone.hh>
|
||||||
|
|
@ -34,11 +35,14 @@
|
||||||
#include "model/cli/CliModel.hpp"
|
#include "model/cli/CliModel.hpp"
|
||||||
#include "model/listener/Listener.hpp"
|
#include "model/listener/Listener.hpp"
|
||||||
#include "model/logger/LoggerModel.hpp"
|
#include "model/logger/LoggerModel.hpp"
|
||||||
#include "tool/AbstractObject.hpp"
|
|
||||||
#include "model/search/MagicSearchModel.hpp"
|
#include "model/search/MagicSearchModel.hpp"
|
||||||
|
#include "tool/AbstractObject.hpp"
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
|
class AbstractEventCountNotifier;
|
||||||
|
class EventCountNotifier;
|
||||||
|
|
||||||
class CoreModel : public ::Listener<linphone::Core, linphone::CoreListener>,
|
class CoreModel : public ::Listener<linphone::Core, linphone::CoreListener>,
|
||||||
public linphone::CoreListener,
|
public linphone::CoreListener,
|
||||||
public AbstractObject {
|
public AbstractObject {
|
||||||
|
|
@ -52,6 +56,8 @@ public:
|
||||||
std::shared_ptr<linphone::Core> getCore();
|
std::shared_ptr<linphone::Core> getCore();
|
||||||
std::shared_ptr<LoggerModel> getLogger();
|
std::shared_ptr<LoggerModel> getLogger();
|
||||||
|
|
||||||
|
bool isInitialized() const;
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void setConfigPath(QString path);
|
void setConfigPath(QString path);
|
||||||
|
|
||||||
|
|
@ -61,11 +67,13 @@ public:
|
||||||
void migrate();
|
void migrate();
|
||||||
|
|
||||||
void searchInMagicSearch(QString filter,
|
void searchInMagicSearch(QString filter,
|
||||||
int sourceFlags,
|
int sourceFlags,
|
||||||
LinphoneEnums::MagicSearchAggregation aggregation,
|
LinphoneEnums::MagicSearchAggregation aggregation,
|
||||||
int maxResults);
|
int maxResults);
|
||||||
|
|
||||||
bool mEnd = false;
|
bool mEnd = false;
|
||||||
|
linphone::ConfiguringState mConfigStatus;
|
||||||
|
QString mConfigMessage;
|
||||||
|
|
||||||
std::shared_ptr<linphone::Core> mCore;
|
std::shared_ptr<linphone::Core> mCore;
|
||||||
std::shared_ptr<LoggerModel> mLogger;
|
std::shared_ptr<LoggerModel> mLogger;
|
||||||
|
|
@ -76,7 +84,6 @@ signals:
|
||||||
void friendRemoved(const std::shared_ptr<linphone::Friend> &f);
|
void friendRemoved(const std::shared_ptr<linphone::Friend> &f);
|
||||||
void friendUpdated(const std::shared_ptr<linphone::Friend> &f);
|
void friendUpdated(const std::shared_ptr<linphone::Friend> &f);
|
||||||
void bearerAccountAdded();
|
void bearerAccountAdded();
|
||||||
void conferenceInfoCreated(const std::shared_ptr<linphone::ConferenceInfo> &confInfo);
|
|
||||||
void unreadNotificationsChanged();
|
void unreadNotificationsChanged();
|
||||||
void requestFetchConfig(QString path);
|
void requestFetchConfig(QString path);
|
||||||
void requestRestart();
|
void requestRestart();
|
||||||
|
|
@ -88,6 +95,7 @@ private:
|
||||||
QTimer *mIterateTimer = nullptr;
|
QTimer *mIterateTimer = nullptr;
|
||||||
QMap<QString, OIDCModel *> mOpenIdConnections;
|
QMap<QString, OIDCModel *> mOpenIdConnections;
|
||||||
std::shared_ptr<MagicSearchModel> mMagicSearch;
|
std::shared_ptr<MagicSearchModel> mMagicSearch;
|
||||||
|
bool mStarted = false;
|
||||||
|
|
||||||
void setPathBeforeCreation();
|
void setPathBeforeCreation();
|
||||||
void setPathsAfterCreation();
|
void setPathsAfterCreation();
|
||||||
|
|
|
||||||
|
|
@ -83,14 +83,19 @@ void MagicSearchModel::onSearchResultsReceived(const std::shared_ptr<linphone::M
|
||||||
auto ldapFriends = ToolModel::getLdapFriendList();
|
auto ldapFriends = ToolModel::getLdapFriendList();
|
||||||
emit searchResultsReceived(results);
|
emit searchResultsReceived(results);
|
||||||
for (auto result : results) {
|
for (auto result : results) {
|
||||||
|
if (!result) continue;
|
||||||
auto f = result->getFriend();
|
auto f = result->getFriend();
|
||||||
auto friendsManager = FriendsManager::getInstance();
|
auto friendsManager = FriendsManager::getInstance();
|
||||||
if (f) {
|
if (f) {
|
||||||
qDebug() << "friend exists, append to unknown map";
|
qDebug() << "friend exists, append to unknown map";
|
||||||
auto friendAddress = f->getAddress();
|
auto friendAddress = f->getAddress() ? f->getAddress()->clone() : nullptr;
|
||||||
friendsManager->appendUnknownFriend(friendAddress->clone(), f);
|
if (friendAddress) {
|
||||||
if (friendsManager->isInOtherAddresses(Utils::coreStringToAppString(friendAddress->asStringUriOnly()))) {
|
friendAddress->clean();
|
||||||
friendsManager->removeOtherAddress(Utils::coreStringToAppString(friendAddress->asStringUriOnly()));
|
friendsManager->appendUnknownFriend(friendAddress, f);
|
||||||
|
if (friendsManager->isInOtherAddresses(
|
||||||
|
Utils::coreStringToAppString(friendAddress->asStringUriOnly()))) {
|
||||||
|
friendsManager->removeOtherAddress(Utils::coreStringToAppString(friendAddress->asStringUriOnly()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto fList = f ? f->getFriendList() : nullptr;
|
auto fList = f ? f->getFriendList() : nullptr;
|
||||||
|
|
@ -127,7 +132,7 @@ void MagicSearchModel::updateFriendListWithFriend(const std::shared_ptr<linphone
|
||||||
if (ToolModel::friendIsInFriendList(friendList, linphoneFriend))
|
if (ToolModel::friendIsInFriendList(friendList, linphoneFriend))
|
||||||
return; // Already exist. We don't need to manipulate list.
|
return; // Already exist. We don't need to manipulate list.
|
||||||
for (auto address : linphoneFriend->getAddresses()) {
|
for (auto address : linphoneFriend->getAddresses()) {
|
||||||
auto existingFriend = friendList->findFriendByAddress(address);
|
auto existingFriend = friendList ? friendList->findFriendByAddress(address) : nullptr;
|
||||||
if (existingFriend) {
|
if (existingFriend) {
|
||||||
friendList->removeFriend(existingFriend);
|
friendList->removeFriend(existingFriend);
|
||||||
friendList->addFriend(linphoneFriend);
|
friendList->addFriend(linphoneFriend);
|
||||||
|
|
@ -135,7 +140,7 @@ void MagicSearchModel::updateFriendListWithFriend(const std::shared_ptr<linphone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto number : linphoneFriend->getPhoneNumbers()) {
|
for (auto number : linphoneFriend->getPhoneNumbers()) {
|
||||||
auto existingFriend = friendList->findFriendByPhoneNumber(number);
|
auto existingFriend = friendList ? friendList->findFriendByPhoneNumber(number) : nullptr;
|
||||||
if (existingFriend) {
|
if (existingFriend) {
|
||||||
friendList->removeFriend(existingFriend);
|
friendList->removeFriend(existingFriend);
|
||||||
friendList->addFriend(linphoneFriend);
|
friendList->addFriend(linphoneFriend);
|
||||||
|
|
@ -143,6 +148,6 @@ void MagicSearchModel::updateFriendListWithFriend(const std::shared_ptr<linphone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qInfo() << log().arg("Adding Friend:") << linphoneFriend.get();
|
qInfo() << log().arg("Adding Friend:") << linphoneFriend.get();
|
||||||
friendList->addFriend(linphoneFriend);
|
if (friendList) friendList->addFriend(linphoneFriend);
|
||||||
emit CoreModel::getInstance()->friendCreated(linphoneFriend);
|
emit CoreModel::getInstance()->friendCreated(linphoneFriend);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,7 @@ void SettingsModel::stopCaptureGraph() {
|
||||||
void SettingsModel::accessCallSettings() {
|
void SettingsModel::accessCallSettings() {
|
||||||
// Audio
|
// Audio
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
startCaptureGraph();
|
||||||
CoreModel::getInstance()->getCore()->reloadSoundDevices();
|
CoreModel::getInstance()->getCore()->reloadSoundDevices();
|
||||||
emit captureDevicesChanged(getCaptureDevices());
|
emit captureDevicesChanged(getCaptureDevices());
|
||||||
emit playbackDevicesChanged(getPlaybackDevices());
|
emit playbackDevicesChanged(getPlaybackDevices());
|
||||||
|
|
@ -182,7 +183,6 @@ void SettingsModel::accessCallSettings() {
|
||||||
emit playbackGainChanged(getPlaybackGain());
|
emit playbackGainChanged(getPlaybackGain());
|
||||||
emit captureGainChanged(getCaptureGain());
|
emit captureGainChanged(getCaptureGain());
|
||||||
|
|
||||||
startCaptureGraph();
|
|
||||||
// Video
|
// Video
|
||||||
CoreModel::getInstance()->getCore()->reloadVideoDevices();
|
CoreModel::getInstance()->getCore()->reloadVideoDevices();
|
||||||
emit videoDevicesChanged(getVideoDevices());
|
emit videoDevicesChanged(getVideoDevices());
|
||||||
|
|
@ -202,13 +202,12 @@ bool SettingsModel::getCaptureGraphRunning() {
|
||||||
float SettingsModel::getMicVolume() {
|
float SettingsModel::getMicVolume() {
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
float v = 0.0;
|
float v = 0.0;
|
||||||
|
|
||||||
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
|
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
|
||||||
v = mSimpleCaptureGraph->getCaptureVolume();
|
v = mSimpleCaptureGraph->getCaptureVolume();
|
||||||
} else {
|
} else {
|
||||||
auto call = CoreModel::getInstance()->getCore()->getCurrentCall();
|
auto call = CoreModel::getInstance()->getCore()->getCurrentCall();
|
||||||
if (call) {
|
if (call) {
|
||||||
v = MediastreamerUtils::computeVu(call->getRecordVolume());
|
v = call->getRecordVolume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,33 +217,49 @@ float SettingsModel::getMicVolume() {
|
||||||
|
|
||||||
float SettingsModel::getPlaybackGain() const {
|
float SettingsModel::getPlaybackGain() const {
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
float dbGain = CoreModel::getInstance()->getCore()->getPlaybackGainDb();
|
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
|
||||||
return MediastreamerUtils::dbToLinear(dbGain);
|
return mSimpleCaptureGraph->getPlaybackGain();
|
||||||
|
} else {
|
||||||
|
auto call = CoreModel::getInstance()->getCore()->getCurrentCall();
|
||||||
|
if (call) return call->getSpeakerVolumeGain();
|
||||||
|
else return 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsModel::setPlaybackGain(float gain) {
|
void SettingsModel::setPlaybackGain(float gain) {
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
float oldGain = getPlaybackGain();
|
float oldGain = getPlaybackGain();
|
||||||
CoreModel::getInstance()->getCore()->setPlaybackGainDb(MediastreamerUtils::linearToDb(gain));
|
|
||||||
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
|
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
|
||||||
mSimpleCaptureGraph->setPlaybackGain(gain);
|
mSimpleCaptureGraph->setPlaybackGain(gain);
|
||||||
}
|
}
|
||||||
|
auto currentCall = CoreModel::getInstance()->getCore()->getCurrentCall();
|
||||||
|
if (currentCall) {
|
||||||
|
currentCall->setSpeakerVolumeGain(gain);
|
||||||
|
}
|
||||||
if ((int)(oldGain * 1000) != (int)(gain * 1000)) emit playbackGainChanged(gain);
|
if ((int)(oldGain * 1000) != (int)(gain * 1000)) emit playbackGainChanged(gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
float SettingsModel::getCaptureGain() const {
|
float SettingsModel::getCaptureGain() const {
|
||||||
mustBeInLinphoneThread(getClassName());
|
mustBeInLinphoneThread(getClassName());
|
||||||
float dbGain = CoreModel::getInstance()->getCore()->getMicGainDb();
|
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
|
||||||
return MediastreamerUtils::dbToLinear(dbGain);
|
return mSimpleCaptureGraph->getCaptureGain();
|
||||||
|
} else {
|
||||||
|
auto call = CoreModel::getInstance()->getCore()->getCurrentCall();
|
||||||
|
if (call) return call->getMicrophoneVolumeGain();
|
||||||
|
else return 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsModel::setCaptureGain(float gain) {
|
void SettingsModel::setCaptureGain(float gain) {
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
float oldGain = getCaptureGain();
|
float oldGain = getCaptureGain();
|
||||||
CoreModel::getInstance()->getCore()->setMicGainDb(MediastreamerUtils::linearToDb(gain));
|
|
||||||
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
|
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
|
||||||
mSimpleCaptureGraph->setCaptureGain(gain);
|
mSimpleCaptureGraph->setCaptureGain(gain);
|
||||||
}
|
}
|
||||||
|
auto currentCall = CoreModel::getInstance()->getCore()->getCurrentCall();
|
||||||
|
if (currentCall) {
|
||||||
|
currentCall->setMicrophoneVolumeGain(gain);
|
||||||
|
}
|
||||||
if ((int)(oldGain * 1000) != (int)(gain * 1000)) emit captureGainChanged(gain);
|
if ((int)(oldGain * 1000) != (int)(gain * 1000)) emit captureGainChanged(gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -256,6 +271,8 @@ QVariantList SettingsModel::getCaptureDevices() const {
|
||||||
for (const auto &device : core->getExtendedAudioDevices()) {
|
for (const auto &device : core->getExtendedAudioDevices()) {
|
||||||
if (device->hasCapability(linphone::AudioDevice::Capabilities::CapabilityRecord)) {
|
if (device->hasCapability(linphone::AudioDevice::Capabilities::CapabilityRecord)) {
|
||||||
list << ToolModel::createVariant(device);
|
list << ToolModel::createVariant(device);
|
||||||
|
} else if (device->hasCapability(linphone::AudioDevice::Capabilities::CapabilityAll)) {
|
||||||
|
list << ToolModel::createVariant(device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
|
|
@ -267,8 +284,11 @@ QVariantList SettingsModel::getPlaybackDevices() const {
|
||||||
QVariantList list;
|
QVariantList list;
|
||||||
|
|
||||||
for (const auto &device : core->getExtendedAudioDevices()) {
|
for (const auto &device : core->getExtendedAudioDevices()) {
|
||||||
if (device->hasCapability(linphone::AudioDevice::Capabilities::CapabilityPlay))
|
if (device->hasCapability(linphone::AudioDevice::Capabilities::CapabilityPlay)) {
|
||||||
list << ToolModel::createVariant(device);
|
list << ToolModel::createVariant(device);
|
||||||
|
} else if (device->hasCapability(linphone::AudioDevice::Capabilities::CapabilityAll)) {
|
||||||
|
list << ToolModel::createVariant(device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
|
|
@ -706,6 +726,20 @@ QString SettingsModel::getDefaultDomain() const {
|
||||||
mConfig->getString(SettingsModel::AppSection, "default_domain", "sip.linphone.org"));
|
mConfig->getString(SettingsModel::AppSection, "default_domain", "sip.linphone.org"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SettingsModel::isSystrayNotificationBlinkEnabled() const {
|
||||||
|
return !!mConfig->getInt(UiSection, "systray_notification_blink", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SettingsModel::isSystrayNotificationGlobal() const {
|
||||||
|
return !!mConfig->getInt(UiSection, "systray_notification_global", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SettingsModel::isSystrayNotificationFiltered() const {
|
||||||
|
return !!mConfig->getInt(UiSection, "systray_notification_filtered", 0);
|
||||||
|
}
|
||||||
|
bool SettingsModel::getLimeIsSupported() const {
|
||||||
|
return CoreModel::getInstance()->getCore()->limeX3DhAvailable();
|
||||||
|
}
|
||||||
// clang-format off
|
// clang-format off
|
||||||
void SettingsModel::notifyConfigReady(){
|
void SettingsModel::notifyConfigReady(){
|
||||||
DEFINE_NOTIFY_CONFIG_READY(disableChatFeature, DisableChatFeature)
|
DEFINE_NOTIFY_CONFIG_READY(disableChatFeature, DisableChatFeature)
|
||||||
|
|
@ -717,7 +751,7 @@ void SettingsModel::notifyConfigReady(){
|
||||||
DEFINE_NOTIFY_CONFIG_READY(assistantHideCreateAccount, AssistantHideCreateAccount)
|
DEFINE_NOTIFY_CONFIG_READY(assistantHideCreateAccount, AssistantHideCreateAccount)
|
||||||
DEFINE_NOTIFY_CONFIG_READY(assistantDisableQrCode, AssistantDisableQrCode)
|
DEFINE_NOTIFY_CONFIG_READY(assistantDisableQrCode, AssistantDisableQrCode)
|
||||||
DEFINE_NOTIFY_CONFIG_READY(assistantHideThirdPartyAccount, AssistantHideThirdPartyAccount)
|
DEFINE_NOTIFY_CONFIG_READY(assistantHideThirdPartyAccount, AssistantHideThirdPartyAccount)
|
||||||
DEFINE_NOTIFY_CONFIG_READY(onlyDisplaySipUriUsername, OnlyDisplaySipUriUsername)
|
DEFINE_NOTIFY_CONFIG_READY(hideSipAddresses, HideSipAddresses)
|
||||||
DEFINE_NOTIFY_CONFIG_READY(darkModeAllowed, DarkModeAllowed)
|
DEFINE_NOTIFY_CONFIG_READY(darkModeAllowed, DarkModeAllowed)
|
||||||
DEFINE_NOTIFY_CONFIG_READY(assistantGoDirectlyToThirdPartySipAccountLogin,
|
DEFINE_NOTIFY_CONFIG_READY(assistantGoDirectlyToThirdPartySipAccountLogin,
|
||||||
AssistantGoDirectlyToThirdPartySipAccountLogin)
|
AssistantGoDirectlyToThirdPartySipAccountLogin)
|
||||||
|
|
@ -779,9 +813,9 @@ DEFINE_GETSET_CONFIG(SettingsModel,
|
||||||
DEFINE_GETSET_CONFIG(SettingsModel,
|
DEFINE_GETSET_CONFIG(SettingsModel,
|
||||||
bool,
|
bool,
|
||||||
Bool,
|
Bool,
|
||||||
onlyDisplaySipUriUsername,
|
hideSipAddresses,
|
||||||
OnlyDisplaySipUriUsername,
|
HideSipAddresses,
|
||||||
"only_display_sip_uri_username",
|
"hide_sip_addresses",
|
||||||
false)
|
false)
|
||||||
DEFINE_GETSET_CONFIG(SettingsModel,
|
DEFINE_GETSET_CONFIG(SettingsModel,
|
||||||
bool,
|
bool,
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,11 @@ public:
|
||||||
|
|
||||||
static bool clearLocalLdapFriendsUponStartup(const std::shared_ptr<linphone::Config> &config);
|
static bool clearLocalLdapFriendsUponStartup(const std::shared_ptr<linphone::Config> &config);
|
||||||
|
|
||||||
|
bool isSystrayNotificationBlinkEnabled() const;
|
||||||
|
bool isSystrayNotificationGlobal() const;
|
||||||
|
bool isSystrayNotificationFiltered() const;
|
||||||
|
bool getLimeIsSupported() const;
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
DECLARE_GETSET(bool, disableChatFeature, DisableChatFeature)
|
DECLARE_GETSET(bool, disableChatFeature, DisableChatFeature)
|
||||||
DECLARE_GETSET(bool, disableMeetingsFeature, DisableMeetingsFeature)
|
DECLARE_GETSET(bool, disableMeetingsFeature, DisableMeetingsFeature)
|
||||||
|
|
@ -168,7 +173,7 @@ public:
|
||||||
DECLARE_GETSET(bool, assistantHideCreateAccount, AssistantHideCreateAccount)
|
DECLARE_GETSET(bool, assistantHideCreateAccount, AssistantHideCreateAccount)
|
||||||
DECLARE_GETSET(bool, assistantDisableQrCode, AssistantDisableQrCode)
|
DECLARE_GETSET(bool, assistantDisableQrCode, AssistantDisableQrCode)
|
||||||
DECLARE_GETSET(bool, assistantHideThirdPartyAccount, AssistantHideThirdPartyAccount)
|
DECLARE_GETSET(bool, assistantHideThirdPartyAccount, AssistantHideThirdPartyAccount)
|
||||||
DECLARE_GETSET(bool, onlyDisplaySipUriUsername, OnlyDisplaySipUriUsername)
|
DECLARE_GETSET(bool, hideSipAddresses, HideSipAddresses)
|
||||||
DECLARE_GETSET(bool, darkModeAllowed, DarkModeAllowed)
|
DECLARE_GETSET(bool, darkModeAllowed, DarkModeAllowed)
|
||||||
DECLARE_GETSET(int, maxAccount, MaxAccount)
|
DECLARE_GETSET(int, maxAccount, MaxAccount)
|
||||||
DECLARE_GETSET(bool, assistantGoDirectlyToThirdPartySipAccountLogin, AssistantGoDirectlyToThirdPartySipAccountLogin)
|
DECLARE_GETSET(bool, assistantGoDirectlyToThirdPartySipAccountLogin, AssistantGoDirectlyToThirdPartySipAccountLogin)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "ToolModel.hpp"
|
#include "ToolModel.hpp"
|
||||||
#include "core/App.hpp"
|
#include "core/App.hpp"
|
||||||
|
#include "core/conference/ConferenceInfoCore.hpp"
|
||||||
#include "core/path/Paths.hpp"
|
#include "core/path/Paths.hpp"
|
||||||
#include "model/core/CoreModel.hpp"
|
#include "model/core/CoreModel.hpp"
|
||||||
#include "model/friend/FriendsManager.hpp"
|
#include "model/friend/FriendsManager.hpp"
|
||||||
|
|
@ -120,20 +121,18 @@ std::shared_ptr<linphone::Friend> ToolModel::findFriendByAddress(const QString &
|
||||||
auto defaultFriendList = CoreModel::getInstance()->getCore()->getDefaultFriendList();
|
auto defaultFriendList = CoreModel::getInstance()->getCore()->getDefaultFriendList();
|
||||||
if (!defaultFriendList) return nullptr;
|
if (!defaultFriendList) return nullptr;
|
||||||
auto linphoneAddr = ToolModel::interpretUrl(address);
|
auto linphoneAddr = ToolModel::interpretUrl(address);
|
||||||
if (linphoneAddr)
|
if (linphoneAddr) return ToolModel::findFriendByAddress(linphoneAddr);
|
||||||
return ToolModel::findFriendByAddress(linphoneAddr);
|
else return nullptr;
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<linphone::Friend> ToolModel::findFriendByAddress(std::shared_ptr<linphone::Address> linphoneAddr) {
|
std::shared_ptr<linphone::Friend> ToolModel::findFriendByAddress(std::shared_ptr<linphone::Address> linphoneAddr) {
|
||||||
auto friendsManager = FriendsManager::getInstance();
|
auto friendsManager = FriendsManager::getInstance();
|
||||||
QString key = Utils::coreStringToAppString(linphoneAddr->asStringUriOnly());
|
QString key = Utils::coreStringToAppString(linphoneAddr->asStringUriOnly());
|
||||||
if (friendsManager->isInKnownFriends(key)) {
|
if (friendsManager->isInKnownFriends(key)) {
|
||||||
// qDebug() << key << "have been found in known friend, return it";
|
// qDebug() << key << "have been found in known friend, return it";
|
||||||
return friendsManager->getKnownFriendAtKey(key);
|
return friendsManager->getKnownFriendAtKey(key);
|
||||||
} else if (friendsManager->isInUnknownFriends(key)) {
|
} else if (friendsManager->isInUnknownFriends(key)) {
|
||||||
// qDebug() << key << "have been found in unknown friend, return it";
|
// qDebug() << key << "have been found in unknown friend, return it";
|
||||||
return friendsManager->getUnknownFriendAtKey(key);
|
return friendsManager->getUnknownFriendAtKey(key);
|
||||||
}
|
}
|
||||||
auto f = CoreModel::getInstance()->getCore()->findFriend(linphoneAddr);
|
auto f = CoreModel::getInstance()->getCore()->findFriend(linphoneAddr);
|
||||||
|
|
@ -141,20 +140,21 @@ std::shared_ptr<linphone::Friend> ToolModel::findFriendByAddress(std::shared_ptr
|
||||||
if (friendsManager->isInUnknownFriends(key)) {
|
if (friendsManager->isInUnknownFriends(key)) {
|
||||||
friendsManager->removeUnknownFriend(key);
|
friendsManager->removeUnknownFriend(key);
|
||||||
}
|
}
|
||||||
// qDebug() << "found friend, add to known map";
|
// qDebug() << "found friend, add to known map";
|
||||||
friendsManager->appendKnownFriend(linphoneAddr, f);
|
friendsManager->appendKnownFriend(linphoneAddr, f);
|
||||||
}
|
}
|
||||||
if (!f) {
|
if (!f) {
|
||||||
if (friendsManager->isInOtherAddresses(key)) {
|
if (friendsManager->isInOtherAddresses(key)) {
|
||||||
// qDebug() << "A magic search has already be done for address" << key << "and nothing was found, return";
|
// qDebug() << "A magic search has already be done for address" << key << "and nothing was found,
|
||||||
|
// return";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
friendsManager->appendOtherAddress(key);
|
friendsManager->appendOtherAddress(key);
|
||||||
// qDebug() << "Couldn't find friend" << linphoneAddr->asStringUriOnly() << "in core, use magic search";
|
// qDebug() << "Couldn't find friend" << linphoneAddr->asStringUriOnly() << "in core, use magic search";
|
||||||
CoreModel::getInstance()->searchInMagicSearch(Utils::coreStringToAppString(linphoneAddr->asStringUriOnly()),
|
CoreModel::getInstance()->searchInMagicSearch(Utils::coreStringToAppString(linphoneAddr->asStringUriOnly()),
|
||||||
(int)linphone::MagicSearch::Source::LdapServers
|
(int)linphone::MagicSearch::Source::LdapServers |
|
||||||
| (int)linphone::MagicSearch::Source::RemoteCardDAV
|
(int)linphone::MagicSearch::Source::RemoteCardDAV,
|
||||||
, LinphoneEnums::MagicSearchAggregation::Friend, 50);
|
LinphoneEnums::MagicSearchAggregation::Friend, 50);
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
@ -378,6 +378,7 @@ std::shared_ptr<linphone::FriendList> ToolModel::getLdapFriendList() {
|
||||||
|
|
||||||
bool ToolModel::friendIsInFriendList(const std::shared_ptr<linphone::FriendList> &friendList,
|
bool ToolModel::friendIsInFriendList(const std::shared_ptr<linphone::FriendList> &friendList,
|
||||||
const std::shared_ptr<linphone::Friend> &f) {
|
const std::shared_ptr<linphone::Friend> &f) {
|
||||||
|
if (!friendList) return false;
|
||||||
auto friends = friendList->getFriends();
|
auto friends = friendList->getFriends();
|
||||||
auto it = std::find_if(friends.begin(), friends.end(),
|
auto it = std::find_if(friends.begin(), friends.end(),
|
||||||
[f](std::shared_ptr<linphone::Friend> linFriend) { return linFriend == f; });
|
[f](std::shared_ptr<linphone::Friend> linFriend) { return linFriend == f; });
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,13 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
|
#include <QColor>
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
|
#include <QQmlComponent>
|
||||||
|
#include <QQmlProperty>
|
||||||
#include <QQuickWindow>
|
#include <QQuickWindow>
|
||||||
#include <QRandomGenerator>
|
#include <QRandomGenerator>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
@ -425,6 +428,25 @@ VariantObject *Utils::findFriendByAddress(const QString &address) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VariantObject *Utils::getFriendSecurityLevel(const QString &address) {
|
||||||
|
VariantObject *data = new VariantObject("getFriendAddressSecurityLevel");
|
||||||
|
if (!data) return nullptr;
|
||||||
|
data->makeRequest([address]() {
|
||||||
|
auto defaultFriendList = ToolModel::getAppFriendList();
|
||||||
|
if (!defaultFriendList) return QVariant();
|
||||||
|
auto linphoneAddr = ToolModel::interpretUrl(address);
|
||||||
|
auto linFriend = CoreModel::getInstance()->getCore()->findFriend(linphoneAddr);
|
||||||
|
if (!linFriend) return QVariant();
|
||||||
|
auto linAddr = ToolModel::interpretUrl(address);
|
||||||
|
if (!linAddr) return QVariant();
|
||||||
|
auto devices = linFriend->getDevicesForAddress(linphoneAddr);
|
||||||
|
int verified = 0;
|
||||||
|
return QVariant::fromValue(LinphoneEnums::fromLinphone(linFriend->getSecurityLevel()));
|
||||||
|
});
|
||||||
|
data->requestValue();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
VariantObject *Utils::getFriendAddressSecurityLevel(const QString &address) {
|
VariantObject *Utils::getFriendAddressSecurityLevel(const QString &address) {
|
||||||
VariantObject *data = new VariantObject("getFriendAddressSecurityLevel");
|
VariantObject *data = new VariantObject("getFriendAddressSecurityLevel");
|
||||||
if (!data) return nullptr;
|
if (!data) return nullptr;
|
||||||
|
|
@ -532,6 +554,16 @@ QString Utils::getOsProduct() {
|
||||||
return product + "/" + version;
|
return product + "/" + version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QColor Utils::getDefaultStyleColor(const QString &colorName) {
|
||||||
|
mustBeInMainThread(sLog().arg(Q_FUNC_INFO));
|
||||||
|
static QObject *defaultStyleSingleton = nullptr;
|
||||||
|
if (!defaultStyleSingleton) {
|
||||||
|
QQmlComponent component(App::getInstance()->mEngine, QUrl("qrc:/qt/qml/Linphone/view/Style/DefaultStyle.qml"));
|
||||||
|
defaultStyleSingleton = component.create();
|
||||||
|
}
|
||||||
|
return QQmlProperty::read(defaultStyleSingleton, colorName).value<QColor>();
|
||||||
|
}
|
||||||
|
|
||||||
QString Utils::getCountryName(const QLocale::Territory &p_country) {
|
QString Utils::getCountryName(const QLocale::Territory &p_country) {
|
||||||
QString countryName;
|
QString countryName;
|
||||||
switch (p_country) {
|
switch (p_country) {
|
||||||
|
|
@ -1440,7 +1472,7 @@ QList<QVariant> Utils::append(const QList<QVariant> a, const QList<QVariant> b)
|
||||||
|
|
||||||
QString Utils::getAddressToDisplay(QVariantList addressList, QString filter, QString defaultAddress) {
|
QString Utils::getAddressToDisplay(QVariantList addressList, QString filter, QString defaultAddress) {
|
||||||
if (filter.isEmpty()) return defaultAddress;
|
if (filter.isEmpty()) return defaultAddress;
|
||||||
for (auto& item: addressList) {
|
for (auto &item : addressList) {
|
||||||
QString address = item.toMap()["address"].toString();
|
QString address = item.toMap()["address"].toString();
|
||||||
if (address.contains(filter)) return address;
|
if (address.contains(filter)) return address;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@ public:
|
||||||
Q_INVOKABLE static VariantObject *findAvatarByAddress(const QString &address);
|
Q_INVOKABLE static VariantObject *findAvatarByAddress(const QString &address);
|
||||||
Q_INVOKABLE static VariantObject *findFriendByAddress(const QString &address);
|
Q_INVOKABLE static VariantObject *findFriendByAddress(const QString &address);
|
||||||
Q_INVOKABLE static VariantObject *getFriendAddressSecurityLevel(const QString &address);
|
Q_INVOKABLE static VariantObject *getFriendAddressSecurityLevel(const QString &address);
|
||||||
|
Q_INVOKABLE static VariantObject *getFriendSecurityLevel(const QString &address);
|
||||||
static QString generateSavedFilename(const QString &from, const QString &to);
|
static QString generateSavedFilename(const QString &from, const QString &to);
|
||||||
Q_INVOKABLE static VariantObject *isMe(const QString &address);
|
Q_INVOKABLE static VariantObject *isMe(const QString &address);
|
||||||
Q_INVOKABLE static VariantObject *isLocal(const QString &address);
|
Q_INVOKABLE static VariantObject *isLocal(const QString &address);
|
||||||
|
|
@ -145,6 +146,8 @@ public:
|
||||||
static QString getApplicationProduct();
|
static QString getApplicationProduct();
|
||||||
static QString getOsProduct();
|
static QString getOsProduct();
|
||||||
|
|
||||||
|
static QColor getDefaultStyleColor(const QString &colorName);
|
||||||
|
|
||||||
static QList<QSharedPointer<DownloadablePayloadTypeCore>> getDownloadableVideoPayloadTypes();
|
static QList<QSharedPointer<DownloadablePayloadTypeCore>> getDownloadableVideoPayloadTypes();
|
||||||
static void checkDownloadedCodecsUpdates();
|
static void checkDownloadedCodecsUpdates();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,10 @@ Button {
|
||||||
if (y < mainItem.height && y + popupHeight > 0) {
|
if (y < mainItem.height && y + popupHeight > 0) {
|
||||||
x += mainItem.width
|
x += mainItem.width
|
||||||
}
|
}
|
||||||
|
var globalPos = mapToItem(mainItem.Window.contentItem, x, y)
|
||||||
|
if (globalPos.x + popupWidth >= mainItem.Window.width) {
|
||||||
|
x = -popupWidth
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onHeightChanged: Qt.callLater(updatePosition)
|
onHeightChanged: Qt.callLater(updatePosition)
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
visible: mainItem.specificAddress != ""
|
visible: mainItem.specificAddress != ""
|
||||||
text: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(mainItem.specificAddress) : mainItem.specificAddress
|
text: SettingsCpp.hideSipAddresses ? UtilsCpp.getUsername(mainItem.specificAddress) : mainItem.specificAddress
|
||||||
elide: Text.ElideMiddle
|
elide: Text.ElideMiddle
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
font {
|
font {
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ Control.TabBar {
|
||||||
|
|
||||||
contentItem: Text {
|
contentItem: Text {
|
||||||
id: tabText
|
id: tabText
|
||||||
width: Math.min(implicitWidth, mainItem.width / mainItem.model.length)
|
width: implicitWidth
|
||||||
font.weight: mainItem.textWeight
|
font.weight: mainItem.textWeight
|
||||||
color: mainItem.currentIndex === index ? DefaultStyle.main2_600 : DefaultStyle.main2_400
|
color: mainItem.currentIndex === index ? DefaultStyle.main2_600 : DefaultStyle.main2_400
|
||||||
font.family: DefaultStyle.defaultFont
|
font.family: DefaultStyle.defaultFont
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ ListView {
|
||||||
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
||||||
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
||||||
_address: modelData.core.remoteAddress
|
_address: modelData.core.remoteAddress
|
||||||
|
secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||||
isConference: modelData.core.isConference
|
isConference: modelData.core.isConference
|
||||||
shadowEnabled: false
|
shadowEnabled: false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ Flickable {
|
||||||
flickableDirection: Flickable.VerticalFlick
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
|
||||||
property bool showInitials: true // Display Initials of Display name.
|
property bool showInitials: true // Display Initials of Display name.
|
||||||
property bool showDefaultAddress: true // Display address below display name.
|
|
||||||
property bool showActions: false // Display actions layout (call buttons)
|
property bool showActions: false // Display actions layout (call buttons)
|
||||||
property bool showContactMenu: true // Display the dot menu for contacts.
|
property bool showContactMenu: true // Display the dot menu for contacts.
|
||||||
property bool showFavorites: true // Display the favorites in the header
|
property bool showFavorites: true // Display the favorites in the header
|
||||||
|
|
@ -269,7 +268,7 @@ Flickable {
|
||||||
showActions: mainItem.showActions
|
showActions: mainItem.showActions
|
||||||
showInitials: mainItem.showInitials
|
showInitials: mainItem.showInitials
|
||||||
showContactMenu: mainItem.showContactMenu
|
showContactMenu: mainItem.showContactMenu
|
||||||
showDefaultAddress: mainItem.showDefaultAddress
|
showDefaultAddress: false
|
||||||
selectionEnabled: mainItem.selectionEnabled
|
selectionEnabled: mainItem.selectionEnabled
|
||||||
multiSelectionEnabled: mainItem.multiSelectionEnabled
|
multiSelectionEnabled: mainItem.multiSelectionEnabled
|
||||||
selectedContacts: mainItem.selectedContacts
|
selectedContacts: mainItem.selectedContacts
|
||||||
|
|
@ -315,7 +314,7 @@ Flickable {
|
||||||
showActions: mainItem.showActions
|
showActions: mainItem.showActions
|
||||||
showInitials: mainItem.showInitials
|
showInitials: mainItem.showInitials
|
||||||
showContactMenu: mainItem.showContactMenu
|
showContactMenu: mainItem.showContactMenu
|
||||||
showDefaultAddress: mainItem.showDefaultAddress
|
showDefaultAddress: false
|
||||||
selectionEnabled: mainItem.selectionEnabled
|
selectionEnabled: mainItem.selectionEnabled
|
||||||
multiSelectionEnabled: mainItem.multiSelectionEnabled
|
multiSelectionEnabled: mainItem.multiSelectionEnabled
|
||||||
selectedContacts: mainItem.selectedContacts
|
selectedContacts: mainItem.selectedContacts
|
||||||
|
|
@ -368,7 +367,8 @@ Flickable {
|
||||||
highlightText: mainItem.highlightText
|
highlightText: mainItem.highlightText
|
||||||
showActions: mainItem.showActions
|
showActions: mainItem.showActions
|
||||||
showContactMenu: mainItem.showContactMenu
|
showContactMenu: mainItem.showContactMenu
|
||||||
showDefaultAddress: mainItem.showDefaultAddress
|
showDefaultAddress: true
|
||||||
|
showDisplayName: false
|
||||||
selectionEnabled: mainItem.selectionEnabled
|
selectionEnabled: mainItem.selectionEnabled
|
||||||
multiSelectionEnabled: mainItem.multiSelectionEnabled
|
multiSelectionEnabled: mainItem.multiSelectionEnabled
|
||||||
selectedContacts: mainItem.selectedContacts
|
selectedContacts: mainItem.selectedContacts
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ Loader{
|
||||||
: contact
|
: contact
|
||||||
? contact.core.defaultAddress
|
? contact.core.defaultAddress
|
||||||
: ''
|
: ''
|
||||||
readonly property string address: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(_address) : _address
|
readonly property string address: SettingsCpp.hideSipAddresses ? UtilsCpp.getUsername(_address) : _address
|
||||||
property var displayNameObj: UtilsCpp.getDisplayName(_address)
|
property var displayNameObj: UtilsCpp.getDisplayName(_address)
|
||||||
property string displayNameVal: account && account.core.displayName
|
property string displayNameVal: account && account.core.displayName
|
||||||
? account.core.displayName
|
? account.core.displayName
|
||||||
|
|
@ -41,6 +41,11 @@ Loader{
|
||||||
property var avatarObj: UtilsCpp.findAvatarByAddress(_address)
|
property var avatarObj: UtilsCpp.findAvatarByAddress(_address)
|
||||||
property string computedAvatarUri: avatarObj ? avatarObj.value : ''
|
property string computedAvatarUri: avatarObj ? avatarObj.value : ''
|
||||||
|
|
||||||
|
// To get the secured property for a friend using an address to find it,
|
||||||
|
// override it as secured: friendSecurityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||||
|
property var friendSecurityLevelObj: UtilsCpp.getFriendSecurityLevel(_address)
|
||||||
|
property var friendSecurityLevel: friendSecurityLevelObj ? securityLevelObj.value : LinphoneEnums.SecurityLevel.None
|
||||||
|
|
||||||
// To get the secured property for a specific address,
|
// To get the secured property for a specific address,
|
||||||
// override it as secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
// override it as secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||||
property var securityLevelObj: UtilsCpp.getFriendAddressSecurityLevel(_address)
|
property var securityLevelObj: UtilsCpp.getFriendAddressSecurityLevel(_address)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ FocusScope {
|
||||||
property var searchResultItem
|
property var searchResultItem
|
||||||
property bool showInitials: true // Display Initials of Display name.
|
property bool showInitials: true // Display Initials of Display name.
|
||||||
property bool showDefaultAddress: true // Display address below display name.
|
property bool showDefaultAddress: true // Display address below display name.
|
||||||
|
property bool showDisplayName: true // Display name above address.
|
||||||
property bool showActions: false // Display actions layout (call buttons)
|
property bool showActions: false // Display actions layout (call buttons)
|
||||||
property bool showContactMenu: true // Display the dot menu for contacts.
|
property bool showContactMenu: true // Display the dot menu for contacts.
|
||||||
property string highlightText
|
property string highlightText
|
||||||
|
|
@ -34,8 +35,7 @@ FocusScope {
|
||||||
property real itemsRightMargin: Math.round(39 * DefaultStyle.dp)
|
property real itemsRightMargin: Math.round(39 * DefaultStyle.dp)
|
||||||
|
|
||||||
property var displayName: searchResultItem.core.fullName
|
property var displayName: searchResultItem.core.fullName
|
||||||
property string initial: displayName ? displayName[0].toLocaleLowerCase(
|
property var initial: displayName ? displayName[0].toLocaleLowerCase(ConstantsCpp.DefaultLocale) : ''
|
||||||
ConstantsCpp.DefaultLocale) : ''
|
|
||||||
|
|
||||||
signal clicked(var mouse)
|
signal clicked(var mouse)
|
||||||
signal contactDeletionRequested(FriendGui contact)
|
signal contactDeletionRequested(FriendGui contact)
|
||||||
|
|
@ -50,7 +50,7 @@ FocusScope {
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
width: Math.round(20 * DefaultStyle.dp)
|
width: Math.round(20 * DefaultStyle.dp)
|
||||||
opacity: previousInitial != mainItem.initial ? 1 : 0
|
opacity: previousInitial != mainItem.initial ? 1 : 0
|
||||||
text: mainItem.initial
|
text: mainItem.initial || ""
|
||||||
color: DefaultStyle.main2_400
|
color: DefaultStyle.main2_400
|
||||||
font {
|
font {
|
||||||
pixelSize: Math.round(20 * DefaultStyle.dp)
|
pixelSize: Math.round(20 * DefaultStyle.dp)
|
||||||
|
|
@ -77,6 +77,10 @@ FocusScope {
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: 0
|
spacing: 0
|
||||||
Text {
|
Text {
|
||||||
|
id: displayNameText
|
||||||
|
visible: mainItem.showDisplayName
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: visible ? implicitHeight: 0
|
||||||
text: UtilsCpp.boldTextPart(mainItem.displayName,
|
text: UtilsCpp.boldTextPart(mainItem.displayName,
|
||||||
mainItem.highlightText)
|
mainItem.highlightText)
|
||||||
font {
|
font {
|
||||||
|
|
@ -85,13 +89,13 @@ FocusScope {
|
||||||
weight: mainItem.showDefaultAddress ? Typography.h4.weight : Typography.p1.weight
|
weight: mainItem.showDefaultAddress ? Typography.h4.weight : Typography.p1.weight
|
||||||
}
|
}
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
Layout.topMargin: Math.round(2 * DefaultStyle.dp)
|
Layout.topMargin: displayNameText.visible ? Math.round(2 * DefaultStyle.dp) : 0
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: visible ? implicitHeight: 0
|
||||||
visible: mainItem.showDefaultAddress
|
visible: mainItem.showDefaultAddress
|
||||||
property string address: SettingsCpp.onlyDisplaySipUriUsername
|
property string address: SettingsCpp.hideSipAddresses
|
||||||
? UtilsCpp.getUsername(mainItem.addressFromFilter)
|
? UtilsCpp.getUsername(mainItem.addressFromFilter)
|
||||||
: mainItem.addressFromFilter
|
: mainItem.addressFromFilter
|
||||||
text: UtilsCpp.boldTextPart(address, mainItem.highlightText)
|
text: UtilsCpp.boldTextPart(address, mainItem.highlightText)
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ ListView {
|
||||||
property string title
|
property string title
|
||||||
property bool showInitials: true // Display Initials of Display name.
|
property bool showInitials: true // Display Initials of Display name.
|
||||||
property bool showDefaultAddress: true // Display address below display name.
|
property bool showDefaultAddress: true // Display address below display name.
|
||||||
|
property bool showDisplayName: true // Display name above address.
|
||||||
property bool showActions: false // Display actions layout (call buttons)
|
property bool showActions: false // Display actions layout (call buttons)
|
||||||
property bool showContactMenu: true // Display the dot menu for contacts.
|
property bool showContactMenu: true // Display the dot menu for contacts.
|
||||||
property bool showFavorites: true // Display the favorites in the header
|
property bool showFavorites: true // Display the favorites in the header
|
||||||
|
|
@ -195,6 +196,7 @@ ListView {
|
||||||
searchResultItem: $modelData
|
searchResultItem: $modelData
|
||||||
showInitials: mainItem.showInitials && isStored
|
showInitials: mainItem.showInitials && isStored
|
||||||
showDefaultAddress: mainItem.showDefaultAddress
|
showDefaultAddress: mainItem.showDefaultAddress
|
||||||
|
showDisplayName: mainItem.showDisplayName
|
||||||
showActions: mainItem.showActions
|
showActions: mainItem.showActions
|
||||||
showContactMenu: mainItem.showContactMenu && searchResultItem.core.isStored
|
showContactMenu: mainItem.showContactMenu && searchResultItem.core.isStored
|
||||||
highlightText: mainItem.highlightText
|
highlightText: mainItem.highlightText
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ Rectangle{
|
||||||
EffectImage {
|
EffectImage {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Math.round(1.5 * DefaultStyle.dp) * scaleFactor
|
anchors.margins: Math.round(1.5 * DefaultStyle.dp) * scaleFactor
|
||||||
imageSource: AppIcons.bellMwi
|
imageSource: AppIcons.bell
|
||||||
colorizationColor: DefaultStyle.grey_0
|
colorizationColor: DefaultStyle.grey_0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ ListView {
|
||||||
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
||||||
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
||||||
_address: modelData.core.address
|
_address: modelData.core.address
|
||||||
|
secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||||
shadowEnabled: false
|
shadowEnabled: false
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ ListView {
|
||||||
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
||||||
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
||||||
_address: modelData.core.sipAddress
|
_address: modelData.core.sipAddress
|
||||||
|
secured: friendSecurityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||||
shadowEnabled: false
|
shadowEnabled: false
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,10 @@ Item {
|
||||||
Text {
|
Text {
|
||||||
anchors.margins: 25
|
anchors.margins: 25
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: titleText
|
text: titleText
|
||||||
|
maximumLineCount: 1
|
||||||
font: Typography.h4
|
font: Typography.h4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ Item {
|
||||||
call: !mainItem.previewEnabled ? mainItem.call : null
|
call: !mainItem.previewEnabled ? mainItem.call : null
|
||||||
displayNameVal: mainItem.displayName
|
displayNameVal: mainItem.displayName
|
||||||
securityBreach: mainItem.securityBreach ? mainItem.securityBreach : securityLevel === LinphoneEnums.SecurityLevel.Unsafe
|
securityBreach: mainItem.securityBreach ? mainItem.securityBreach : securityLevel === LinphoneEnums.SecurityLevel.Unsafe
|
||||||
|
secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||||
}
|
}
|
||||||
ColumnLayout{
|
ColumnLayout{
|
||||||
id: joiningView
|
id: joiningView
|
||||||
|
|
@ -183,7 +184,7 @@ Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
property string _text: mainItem.call && mainItem.call.core.remoteAddress
|
property string _text: mainItem.call && mainItem.call.core.remoteAddress
|
||||||
text: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(_text) : _text
|
text: SettingsCpp.hideSipAddresses ? UtilsCpp.getUsername(_text) : _text
|
||||||
color: DefaultStyle.grey_0
|
color: DefaultStyle.grey_0
|
||||||
font {
|
font {
|
||||||
pixelSize: Math.round(14 * DefaultStyle.dp)
|
pixelSize: Math.round(14 * DefaultStyle.dp)
|
||||||
|
|
@ -260,7 +261,7 @@ Item {
|
||||||
: mainItem.account && mainItem.identityAddress
|
: mainItem.account && mainItem.identityAddress
|
||||||
? mainItem.identityAddress.value
|
? mainItem.identityAddress.value
|
||||||
: ""
|
: ""
|
||||||
text: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(_text) : _text
|
text: SettingsCpp.hideSipAddresses ? UtilsCpp.getUsername(_text) : _text
|
||||||
color: DefaultStyle.grey_0
|
color: DefaultStyle.grey_0
|
||||||
font {
|
font {
|
||||||
pixelSize: Math.round(14 * DefaultStyle.dp)
|
pixelSize: Math.round(14 * DefaultStyle.dp)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ Quick.Text {
|
||||||
family: DefaultStyle.defaultFont
|
family: DefaultStyle.defaultFont
|
||||||
pixelSize: Math.round(10 * DefaultStyle.dp)
|
pixelSize: Math.round(10 * DefaultStyle.dp)
|
||||||
weight: Typography.p1.weight
|
weight: Typography.p1.weight
|
||||||
bold: true
|
|
||||||
}
|
}
|
||||||
color: DefaultStyle.main2_600
|
color: DefaultStyle.main2_600
|
||||||
wrapMode: Quick.Text.Wrap
|
wrapMode: Quick.Text.Wrap
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,8 @@ import Qt.labs.platform
|
||||||
property bool isFrameLess : false;
|
property bool isFrameLess : false;
|
||||||
property bool showAsTool : false
|
property bool showAsTool : false
|
||||||
// Don't use Popup for flags : it could lead to error in geometry. On Mac, Using Tool ensure to have the Window on Top and fullscreen independant
|
// Don't use Popup for flags : it could lead to error in geometry. On Mac, Using Tool ensure to have the Window on Top and fullscreen independant
|
||||||
flags: Qt.BypassWindowManagerHint | (showAsTool?Qt.Tool:Qt.WindowStaysOnTopHint) | Qt.Window | Qt.FramelessWindowHint;
|
// flags: Qt.WindowDoesNotAcceptFocus | Qt.BypassWindowManagerHint | (showAsTool?Qt.Tool:Qt.WindowStaysOnTopHint) | Qt.Window | Qt.FramelessWindowHint;
|
||||||
|
flags: Qt.Popup | Qt.Dialog | Qt.WindowDoesNotAcceptFocus | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
|
||||||
opacity: 1.0
|
opacity: 1.0
|
||||||
height: _content[0] != null ? _content[0].height : 0
|
height: _content[0] != null ? _content[0].height : 0
|
||||||
width: _content[0] != null ? _content[0].width : 0
|
width: _content[0] != null ? _content[0].width : 0
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,6 @@ Dialog {
|
||||||
id: passwordEdit
|
id: passwordEdit
|
||||||
hidden: true
|
hidden: true
|
||||||
isError: passwordItem.errorTextVisible
|
isError: passwordItem.errorTextVisible
|
||||||
KeyNavigation.up: usernameEdit
|
|
||||||
KeyNavigation.down: cancelButton
|
KeyNavigation.down: cancelButton
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ Notification {
|
||||||
Layout.preferredHeight: Math.round(60 * DefaultStyle.dp)
|
Layout.preferredHeight: Math.round(60 * DefaultStyle.dp)
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
call: mainItem.call
|
call: mainItem.call
|
||||||
|
secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||||
isConference: mainItem.call && mainItem.call.core.isConference
|
isConference: mainItem.call && mainItem.call.core.isConference
|
||||||
}
|
}
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ ColumnLayout{
|
||||||
id: mainItem
|
id: mainItem
|
||||||
property AccountGui account: null
|
property AccountGui account: null
|
||||||
property string topText: account ? account.core.displayName : ""
|
property string topText: account ? account.core.displayName : ""
|
||||||
property string bottomText: account ? SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(account.core.identityAddress) : account.core.identityAddress : ""
|
property string bottomText: account ? SettingsCpp.hideSipAddresses ? UtilsCpp.getUsername(account.core.identityAddress) : account.core.identityAddress : ""
|
||||||
spacing: 0
|
spacing: 0
|
||||||
width: topTextItem.implicitWidth
|
width: topTextItem.implicitWidth
|
||||||
Text {
|
Text {
|
||||||
|
|
|
||||||
|
|
@ -305,7 +305,7 @@ MainRightPanel {
|
||||||
if (text.length != 0) mainItem.contact.core.setAddressAt(index, label, text)
|
if (text.length != 0) mainItem.contact.core.setAddressAt(index, label, text)
|
||||||
}
|
}
|
||||||
property string _initialText: modelData.address
|
property string _initialText: modelData.address
|
||||||
initialText: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(_initialText) : _initialText
|
initialText: SettingsCpp.hideSipAddresses ? UtilsCpp.getUsername(_initialText) : _initialText
|
||||||
backgroundColor: DefaultStyle.grey_0
|
backgroundColor: DefaultStyle.grey_0
|
||||||
focus: true
|
focus: true
|
||||||
KeyNavigation.right: removeAddressButton
|
KeyNavigation.right: removeAddressButton
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ FocusScope{
|
||||||
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
||||||
_address: modelData
|
_address: modelData
|
||||||
shadowEnabled: false
|
shadowEnabled: false
|
||||||
|
secured: friendSecurityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
|
||||||
|
|
@ -288,6 +288,7 @@ FocusScope {
|
||||||
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
||||||
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
||||||
_address: modelData.address
|
_address: modelData.address
|
||||||
|
secured: friendSecurityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||||
shadowEnabled: false
|
shadowEnabled: false
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ AbstractMainPage {
|
||||||
text: titleText
|
text: titleText
|
||||||
color: DefaultStyle.main2_700
|
color: DefaultStyle.main2_700
|
||||||
font: Typography.h3
|
font: Typography.h3
|
||||||
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
Item {
|
Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
@ -67,6 +68,7 @@ AbstractMainPage {
|
||||||
|
|
||||||
delegate: SettingsMenuItem {
|
delegate: SettingsMenuItem {
|
||||||
titleText: modelData.title
|
titleText: modelData.title
|
||||||
|
width: familiesList.width
|
||||||
visible: modelData.visible != undefined ? modelData.visible : true
|
visible: modelData.visible != undefined ? modelData.visible : true
|
||||||
isSelected: familiesList.selectedIndex == index
|
isSelected: familiesList.selectedIndex == index
|
||||||
focus: index == 0
|
focus: index == 0
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,10 @@ AbstractSettingsMenu {
|
||||||
{title: qsTr("settings_contacts_title"), layout: "ContactsSettingsLayout"},
|
{title: qsTr("settings_contacts_title"), layout: "ContactsSettingsLayout"},
|
||||||
//: "Réunions"
|
//: "Réunions"
|
||||||
{title: qsTr("settings_meetings_title"), layout: "MeetingsSettingsLayout", visible: !SettingsCpp.disableMeetingsFeature},
|
{title: qsTr("settings_meetings_title"), layout: "MeetingsSettingsLayout", visible: !SettingsCpp.disableMeetingsFeature},
|
||||||
//: "Affichage"
|
////: "Affichage"
|
||||||
//{title: qsTr("settings_user_interface_title"), layout: "DisplaySettingsLayout"},
|
//{title: qsTr("settings_user_interface_title"), layout: "DisplaySettingsLayout"},
|
||||||
|
//: "Security"
|
||||||
|
{title: qsTr("settings_security_title"), layout: "SecuritySettingsLayout"},
|
||||||
//: "Réseau"
|
//: "Réseau"
|
||||||
{title: qsTr("settings_network_title"), layout: "NetworkSettingsLayout"},
|
{title: qsTr("settings_network_title"), layout: "NetworkSettingsLayout"},
|
||||||
//: "Paramètres avancés"
|
//: "Paramètres avancés"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Qml template used for welcome and login/register pages
|
|
||||||
**/
|
|
||||||
import QtCore
|
import QtCore
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
|
@ -99,10 +94,16 @@ Item {
|
||||||
x: mainItem.width / 2 - width / 2
|
x: mainItem.width / 2 - width / 2
|
||||||
y: contentItem.height / 2
|
y: contentItem.height / 2
|
||||||
property var currentCall: callsModel.currentCall ? callsModel.currentCall : null
|
property var currentCall: callsModel.currentCall ? callsModel.currentCall : null
|
||||||
|
property var conference: currentCall ? currentCall.core.conference : null
|
||||||
property string remoteName: currentCall ? currentCall.core.remoteName : ""
|
property string remoteName: currentCall ? currentCall.core.remoteName : ""
|
||||||
|
property string subject: conference ? conference.core.subject : ''
|
||||||
contentItem: MediumButton {
|
contentItem: MediumButton {
|
||||||
style: ButtonStyle.toast
|
style: ButtonStyle.toast
|
||||||
text: currentCallNotif.currentCall ? currentCallNotif.currentCall.core.conference ? ("Réunion en cours : ") + currentCallNotif.currentCall.core.conference.core.subject : (("Appel en cours : ") + currentCallNotif.remoteName) : "appel en cours"
|
text: currentCallNotif.currentCall
|
||||||
|
? currentCallNotif.conference
|
||||||
|
? ("Réunion en cours : ") + currentCallNotif.subject
|
||||||
|
: (("Appel en cours : ") + currentCallNotif.remoteName)
|
||||||
|
: "appel en cours"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var callsWindow = UtilsCpp.getCallsWindow(
|
var callsWindow = UtilsCpp.getCallsWindow(
|
||||||
currentCallNotif.currentCall)
|
currentCallNotif.currentCall)
|
||||||
|
|
@ -178,6 +179,7 @@ Item {
|
||||||
}
|
}
|
||||||
initButtons()
|
initButtons()
|
||||||
currentIndex = SettingsCpp.getLastActiveTabIndex()
|
currentIndex = SettingsCpp.getLastActiveTabIndex()
|
||||||
|
if (currentIndex === -1) currentIndex = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
|
@ -267,7 +269,6 @@ Item {
|
||||||
showActions: true
|
showActions: true
|
||||||
showFavorites: false
|
showFavorites: false
|
||||||
selectionEnabled: false
|
selectionEnabled: false
|
||||||
showDefaultAddress: true
|
|
||||||
searchOnEmpty: false
|
searchOnEmpty: false
|
||||||
|
|
||||||
sectionsPixelSize: Typography.p2.pixelSize
|
sectionsPixelSize: Typography.p2.pixelSize
|
||||||
|
|
@ -459,8 +460,7 @@ Item {
|
||||||
icon.height: Math.round(32 * DefaultStyle.dp)
|
icon.height: Math.round(32 * DefaultStyle.dp)
|
||||||
text: qsTr("settings_title")
|
text: qsTr("settings_title")
|
||||||
icon.source: AppIcons.settings
|
icon.source: AppIcons.settings
|
||||||
onClicked: openContextualMenuComponent(
|
onClicked: openContextualMenuComponent(settingsPageComponent)
|
||||||
settingsPageComponent)
|
|
||||||
KeyNavigation.up: visibleChildren.length
|
KeyNavigation.up: visibleChildren.length
|
||||||
!= 0 ? settingsMenuButton.getPreviousItem(
|
!= 0 ? settingsMenuButton.getPreviousItem(
|
||||||
2) : null
|
2) : null
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import QtQuick.Layouts
|
||||||
import QtQuick.Controls.Basic as Control
|
import QtQuick.Controls.Basic as Control
|
||||||
import SettingsCpp 1.0
|
import SettingsCpp 1.0
|
||||||
import Linphone
|
import Linphone
|
||||||
import UtilsCpp
|
|
||||||
|
|
||||||
AbstractSettingsLayout {
|
AbstractSettingsLayout {
|
||||||
width: parent?.width
|
width: parent?.width
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,6 @@ FriendGui{
|
||||||
Layout.rightMargin: Math.round(8 * DefaultStyle.dp)
|
Layout.rightMargin: Math.round(8 * DefaultStyle.dp)
|
||||||
searchBarText: searchBar.text
|
searchBarText: searchBar.text
|
||||||
hideSuggestions: true
|
hideSuggestions: true
|
||||||
showDefaultAddress: false
|
|
||||||
sourceFlags: LinphoneEnums.MagicSearchSource.Friends
|
sourceFlags: LinphoneEnums.MagicSearchSource.Friends
|
||||||
| LinphoneEnums.MagicSearchSource.FavoriteFriends
|
| LinphoneEnums.MagicSearchSource.FavoriteFriends
|
||||||
| LinphoneEnums.MagicSearchSource.LdapServers
|
| LinphoneEnums.MagicSearchSource.LdapServers
|
||||||
|
|
@ -536,7 +535,7 @@ FriendGui{
|
||||||
Text {
|
Text {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
property string _text: listViewModelData.address
|
property string _text: listViewModelData.address
|
||||||
text: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(_text) : _text
|
text: SettingsCpp.hideSipAddresses ? UtilsCpp.getUsername(_text) : _text
|
||||||
font {
|
font {
|
||||||
pixelSize: Typography.p1.pixelSize
|
pixelSize: Typography.p1.pixelSize
|
||||||
weight: Typography.p1.weight
|
weight: Typography.p1.weight
|
||||||
|
|
|
||||||
|
|
@ -764,6 +764,7 @@ AbstractMainPage {
|
||||||
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
||||||
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
||||||
_address: mainItem.selectedConference && mainItem.selectedConference.core ? mainItem.selectedConference.core.organizerAddress : ""
|
_address: mainItem.selectedConference && mainItem.selectedConference.core ? mainItem.selectedConference.core.organizerAddress : ""
|
||||||
|
secured: friendSecurityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: mainItem.selectedConference && mainItem.selectedConference.core ? mainItem.selectedConference.core.organizerName : ""
|
text: mainItem.selectedConference && mainItem.selectedConference.core ? mainItem.selectedConference.core.organizerName : ""
|
||||||
|
|
@ -801,6 +802,7 @@ AbstractMainPage {
|
||||||
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
||||||
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
||||||
_address: modelData.address
|
_address: modelData.address
|
||||||
|
secured: friendSecurityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||||
shadowEnabled: false
|
shadowEnabled: false
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
Layout.leftMargin: Math.round(5 * DefaultStyle.dp)
|
Layout.leftMargin: Math.round(5 * DefaultStyle.dp)
|
||||||
text: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(modelData.address) : modelData.address
|
text: SettingsCpp.hideSipAddresses ? UtilsCpp.getUsername(modelData.address) : modelData.address
|
||||||
font {
|
font {
|
||||||
pixelSize: Typography.p1.pixelSize
|
pixelSize: Typography.p1.pixelSize
|
||||||
weight: Typography.p1.weight
|
weight: Typography.p1.weight
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,6 @@ QtObject {
|
||||||
property string mediaEncryptionZrtpPq: "image://internal/media_encryption_zrtp_pq.svg"
|
property string mediaEncryptionZrtpPq: "image://internal/media_encryption_zrtp_pq.svg"
|
||||||
property string pencil: "image://internal/pencil-simple.svg"
|
property string pencil: "image://internal/pencil-simple.svg"
|
||||||
property string shareNetwork: "image://internal/share-network.svg"
|
property string shareNetwork: "image://internal/share-network.svg"
|
||||||
property string bell: "image://internal/bell-simple.svg"
|
|
||||||
property string bellSlash: "image://internal/bell-slash.svg"
|
|
||||||
property string question: "image://internal/question.svg"
|
property string question: "image://internal/question.svg"
|
||||||
property string settings: "image://internal/gear.svg"
|
property string settings: "image://internal/gear.svg"
|
||||||
property string clock: "image://internal/clock.svg"
|
property string clock: "image://internal/clock.svg"
|
||||||
|
|
@ -117,11 +115,12 @@ QtObject {
|
||||||
property string mobile: "image://internal/device-mobile-camera.svg"
|
property string mobile: "image://internal/device-mobile-camera.svg"
|
||||||
property string desktop: "image://internal/desktop.svg"
|
property string desktop: "image://internal/desktop.svg"
|
||||||
property string calendar: "image://internal/calendar-blank.svg"
|
property string calendar: "image://internal/calendar-blank.svg"
|
||||||
|
property string bell: "image://internal/bell.svg"
|
||||||
|
property string bellSlash: "image://internal/bell-slash.svg"
|
||||||
property string bellDnd: "image://internal/bell-dnd.svg"
|
property string bellDnd: "image://internal/bell-dnd.svg"
|
||||||
property string bellRinger: "image://internal/bell-ringer.svg"
|
property string bellRinger: "image://internal/bell-ringing.svg"
|
||||||
property string voicemail: "image://internal/voicemail.svg"
|
property string voicemail: "image://internal/voicemail.svg"
|
||||||
property string power: "image://internal/power.svg"
|
property string power: "image://internal/power.svg"
|
||||||
property string resourcePackage: "image://internal/package.svg"
|
property string resourcePackage: "image://internal/package.svg"
|
||||||
property string appWindow: "image://internal/app-window.svg"
|
property string appWindow: "image://internal/app-window.svg"
|
||||||
property string bellMwi: "image://internal/bell-simple.svg"
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ else
|
||||||
if [ -f "${WORK_DIR}/AppBin/appimagetool-x86_64.AppImage" ]; then
|
if [ -f "${WORK_DIR}/AppBin/appimagetool-x86_64.AppImage" ]; then
|
||||||
echo "appimagetool-x86_64.AppImage exists"
|
echo "appimagetool-x86_64.AppImage exists"
|
||||||
else
|
else
|
||||||
wget -P "${WORK_DIR}/AppBin" https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
wget -P "${WORK_DIR}/AppBin" https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||||
chmod +x "${WORK_DIR}/AppBin/appimagetool-x86_64.AppImage"
|
chmod +x "${WORK_DIR}/AppBin/appimagetool-x86_64.AppImage"
|
||||||
fi
|
fi
|
||||||
./${WORK_DIR}/AppBin/linuxdeploy-x86_64.AppImage --appimage-extract-and-run --appdir=${WORK_DIR}/AppDir -e ${WORK_DIR}/AppDir/usr/bin/${APP_NAME} --desktop-file=${WORK_DIR}/AppDir/usr/share/applications/${APP_NAME}.desktop -i ${WORK_DIR}/AppDir/usr/share/icons/hicolor/scalable/apps/${APP_NAME}.svg --plugin qt
|
./${WORK_DIR}/AppBin/linuxdeploy-x86_64.AppImage --appimage-extract-and-run --appdir=${WORK_DIR}/AppDir -e ${WORK_DIR}/AppDir/usr/bin/${APP_NAME} --desktop-file=${WORK_DIR}/AppDir/usr/share/applications/${APP_NAME}.desktop -i ${WORK_DIR}/AppDir/usr/share/icons/hicolor/scalable/apps/${APP_NAME}.svg --plugin qt
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ ARG QT6_VERSION=6.8.0
|
||||||
#Do not use it. It seems that it cannot be used from python command.
|
#Do not use it. It seems that it cannot be used from python command.
|
||||||
#ARG QT_MODULES=qtnetworkauth qtquick3d qtmultimedia
|
#ARG QT_MODULES=qtnetworkauth qtquick3d qtmultimedia
|
||||||
|
|
||||||
MAINTAINER Gaelle Braud <gaelle.braud@belledonne-communications.com>
|
LABEL Gaelle Braud <gaelle.braud@belledonne-communications.com>
|
||||||
|
|
||||||
# Use a Swiss mirror
|
# Use a Swiss mirror
|
||||||
RUN sed -i -E 's/(archive|security)\.ubuntu\.com/ch.archive.ubuntu.com/' /etc/apt/sources.list
|
RUN sed -i -E 's/(archive|security)\.ubuntu\.com/ch.archive.ubuntu.com/' /etc/apt/sources.list
|
||||||
|
|
|
||||||
100
docker-files/bc-dev-ubuntu-22-04-lts
Normal file
100
docker-files/bc-dev-ubuntu-22-04-lts
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
###############################################################################
|
||||||
|
# Dockerfile used to make gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-ubuntu-20-04-lts:20231024_add_multimedia
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
FROM ubuntu:22.04
|
||||||
|
|
||||||
|
# Qt on Ubuntu 22.04 is too old. Use a downloader.
|
||||||
|
ARG QT_VERSION=5.15.2
|
||||||
|
ARG QT6_VERSION=6.9.1
|
||||||
|
#Do not use it. It seems that it cannot be used from python command.
|
||||||
|
#ARG QT_MODULES=qtnetworkauth qtquick3d qtmultimedia qt5compat qtshadertools
|
||||||
|
|
||||||
|
LABEL Gaelle Braud <gaelle.braud@belledonne-communications.com>
|
||||||
|
|
||||||
|
# Use a Swiss mirror
|
||||||
|
RUN sed -i -E 's/(archive|security)\.ubuntu\.com/ch.archive.ubuntu.com/' /etc/apt/sources.list
|
||||||
|
|
||||||
|
# add fallbacks for timeout connections.
|
||||||
|
|
||||||
|
#France
|
||||||
|
RUN echo "deb http://fr.archive.ubuntu.com/ubuntu/ jammy main restricted" >> /etc/apt/sources.list
|
||||||
|
RUN echo "deb http://security.ubuntu.com/ubuntu jammy-security main restricted" >> /etc/apt/sources.list
|
||||||
|
RUN echo "deb http://ch.archive.ubuntu.com/ubuntu/ jammy-updates main restricted" >> /etc/apt/sources.list
|
||||||
|
#Belgium
|
||||||
|
RUN echo "deb http://be.archive.ubuntu.com/ubuntu/ jammy main restricted" >> /etc/apt/sources.list
|
||||||
|
RUN echo "deb http://security.ubuntu.com/ubuntu jammy-security main restricted" >> /etc/apt/sources.list
|
||||||
|
RUN echo "deb http://be.archive.ubuntu.com/ubuntu/ jammy-updates main restricted" >> /etc/apt/sources.list
|
||||||
|
#International
|
||||||
|
RUN echo "deb http://archive.ubuntu.com/ubuntu/ jammy main restricted" >> /etc/apt/sources.list
|
||||||
|
RUN echo "deb http://security.ubuntu.com/ubuntu jammy-security main restricted" >> /etc/apt/sources.list
|
||||||
|
RUN echo "deb http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted" >> /etc/apt/sources.list
|
||||||
|
|
||||||
|
# Configure locale
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y locales && \
|
||||||
|
apt-get clean && \
|
||||||
|
echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \
|
||||||
|
locale-gen
|
||||||
|
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8'
|
||||||
|
ENV TZ=Europe/Paris
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
ENV SHELL=/bin/bash
|
||||||
|
#ENV PS1='\[\e[33m\]\u@bc-dev-ubuntu-20-04>\[\e[0m\] '
|
||||||
|
|
||||||
|
# Install common general tools
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y nano sudo vim && \
|
||||||
|
apt-get clean
|
||||||
|
|
||||||
|
# Install development tools
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y alien at autoconf bison ccache clang doxygen elfutils g++ gdb git graphviz intltool libtool lsb-release make ninja-build openssh-client patch perl python3-pip python3-pystache python3-six python3-jsonschema python3-jinja2 meson yasm && \
|
||||||
|
apt-get clean
|
||||||
|
|
||||||
|
# Install linphone & flexisip dependencies development packages
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y libasound2-dev libavcodec-dev libavutil-dev libbsd-dev libegl1-mesa-dev libglew-dev libgsm1-dev libjansson-dev libmariadb-dev-compat libmbedtls-dev libopus-dev libpq-dev libprotobuf-dev libpulse-dev libqt5svg5-dev libsnmp-dev libspeex-dev libspeexdsp-dev libsqlite3-dev libsrtp2-dev libssl-dev libswscale-dev libturbojpeg0-dev libv4l-dev libvpx-dev libxerces-c-dev libxml2-dev libxv-dev libxinerama-dev protobuf-compiler qttools5-dev qttools5-dev-tools xsdcxx cmake nasm && \
|
||||||
|
apt-get clean
|
||||||
|
|
||||||
|
# Install signing tools
|
||||||
|
RUN sudo apt-get install -y gnupg2
|
||||||
|
|
||||||
|
# Install configuration tools
|
||||||
|
RUN sudo apt-get install -y wget
|
||||||
|
|
||||||
|
# Configure user bc
|
||||||
|
RUN useradd -ms /bin/bash bc && \
|
||||||
|
echo 'bc:cotcot' | chpasswd && \
|
||||||
|
echo 'bc ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
|
||||||
|
|
||||||
|
########### QT
|
||||||
|
|
||||||
|
RUN sudo apt-get update && sudo apt-get install -y libxkbcommon* flite1-dev libspeechd-dev speech-dispatcher libfontconfig1-dev libfreetype6-dev libx11-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libx11-xcb* libxcb* qdbus-qt5 libqt5dbus5 libdbus-1-dev libdbus-glib-1-dev libatspi2.0-0 libatspi2.0-dev
|
||||||
|
RUN sudo apt-get update && sudo apt-get install -y libxcb-keysyms1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev
|
||||||
|
|
||||||
|
USER bc
|
||||||
|
WORKDIR /home/bc
|
||||||
|
|
||||||
|
# RUN sudo apt install python3-pip --upgrade -y
|
||||||
|
RUN sudo apt install --upgrade -y python3-importlib-metadata
|
||||||
|
RUN sudo apt install --upgrade -y python3-setuptools
|
||||||
|
# RUN sudo apt install python3-ez_setup
|
||||||
|
|
||||||
|
## Install Qt download tool
|
||||||
|
# installation is split because there is a way where some modules are not downloaded in the first attempt.
|
||||||
|
RUN sudo apt install -y python3-py7zr
|
||||||
|
RUN sudo pip3 install --upgrade aqtinstall
|
||||||
|
RUN sudo python3 -m aqt install-qt linux desktop $QT_VERSION -O /opt/Qt
|
||||||
|
RUN sudo python3 -m aqt install-qt linux desktop $QT_VERSION -O /opt/Qt --noarchives -m qtnetworkauth qtquick3d
|
||||||
|
RUN sudo python3 -m aqt install-qt linux desktop $QT6_VERSION -O /opt/Qt
|
||||||
|
RUN sudo python3 -m aqt install-qt linux desktop $QT6_VERSION -O /opt/Qt --noarchives -m qtnetworkauth qtquick3d qtmultimedia qt5compat qtshadertools
|
||||||
|
|
||||||
|
RUN sudo chown -R bc:bc /opt/Qt/
|
||||||
|
|
||||||
|
RUN qtchooser -install $QT_VERSION /opt/Qt/$QT_VERSION/gcc_64/bin/qmake
|
||||||
|
RUN qtchooser -install $QT6_VERSION /opt/Qt/$QT6_VERSION/gcc_64/bin/qmake
|
||||||
|
|
||||||
|
CMD bash
|
||||||
2
external/linphone-sdk
vendored
2
external/linphone-sdk
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 96a6385bfdb3e6c0ed85df42bda99467e8f6fc5f
|
Subproject commit 52fa0abf7e60d1f7614b8ee8e8dbbee52f3f5f88
|
||||||
Loading…
Add table
Reference in a new issue