This commit is contained in:
Christophe Deschamps 2024-09-04 09:04:17 +02:00
parent 13d2fefcd1
commit 6f7ebb1f9f
11 changed files with 165 additions and 7 deletions

View file

@ -52,10 +52,7 @@ AccountCore::AccountCore(const std::shared_ptr<linphone::Account> &account) : QO
mRegisterEnabled = params->registerEnabled();
mMwiServerAddress =
params->getMwiServerAddress() ? Utils::coreStringToAppString(params->getMwiServerAddress()->asString()) : "";
mTransports << "TCP"
<< "UDP"
<< "TLS"
<< "DTLS";
mTransports << "TCP" << "UDP" << "TLS" << "DTLS";
mTransport = LinphoneEnums::toString(LinphoneEnums::fromLinphone(params->getTransport()));
mServerAddress =
params->getServerAddress() ? Utils::coreStringToAppString(params->getServerAddress()->asString()) : "";
@ -87,6 +84,8 @@ AccountCore::AccountCore(const std::shared_ptr<linphone::Account> &account) : QO
mDialPlan = mAccountModel->dialPlanAsString(dialPlan);
}
}
INIT_CORE_MEMBER(VoicemailCount, mAccountModel)
}
AccountCore::~AccountCore() {
@ -255,6 +254,9 @@ void AccountCore::setSelf(QSharedPointer<AccountCore> me) {
mAccountModelConnection->makeConnectToCore(&AccountCore::lSetLimeServerUrl, [this](QString value) {
mAccountModelConnection->invokeToModel([this, value]() { mAccountModel->setLimeServerUrl(value); });
});
DEFINE_CORE_GET_CONNECT(mAccountModelConnection, AccountCore, AccountModel, mAccountModel, int, voicemailCount,
VoicemailCount)
}
const std::shared_ptr<AccountModel> &AccountCore::getModel() const {

View file

@ -71,6 +71,7 @@ class AccountCore : public QObject, public AbstractObject {
Q_PROPERTY(QString audioVideoConferenceFactoryAddress READ getAudioVideoConferenceFactoryAddress WRITE
lSetAudioVideoConferenceFactoryAddress NOTIFY audioVideoConferenceFactoryAddressChanged)
Q_PROPERTY(QString limeServerUrl READ getLimeServerUrl WRITE lSetLimeServerUrl NOTIFY limeServerUrlChanged)
DECLARE_CORE_GET(int, voicemailCount, VoicemailCount)
public:
static QSharedPointer<AccountCore> create(const std::shared_ptr<linphone::Account> &account);

View file

@ -0,0 +1,3 @@
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18.75 7.25C17.7075 7.25096 16.6889 7.56228 15.824 8.14427C14.959 8.72626 14.287 9.55258 13.8934 10.5179C13.4998 11.4833 13.4025 12.544 13.614 13.5648C13.8254 14.5856 14.336 15.5204 15.0806 16.25H8.91936C9.78874 15.3982 10.3351 14.2708 10.4651 13.0606C10.5951 11.8505 10.3005 10.6327 9.63187 9.61574C8.9632 8.59874 7.96195 7.84568 6.79939 7.48535C5.63683 7.12502 4.38518 7.17982 3.25856 7.64037C2.13194 8.10092 1.20033 8.93861 0.623101 10.0101C0.04587 11.0817 -0.141122 12.3205 0.0941104 13.5147C0.329343 14.7088 0.972184 15.7842 1.91267 16.5568C2.85316 17.3293 4.03287 17.7511 5.24999 17.75H18.75C20.1424 17.75 21.4777 17.1969 22.4623 16.2123C23.4469 15.2277 24 13.8924 24 12.5C24 11.1076 23.4469 9.77226 22.4623 8.78769C21.4777 7.80312 20.1424 7.25 18.75 7.25ZM1.49999 12.5C1.49999 11.7583 1.71992 11.0333 2.13198 10.4166C2.54403 9.79993 3.1297 9.31928 3.81492 9.03545C4.50015 8.75162 5.25415 8.67736 5.98158 8.82205C6.709 8.96675 7.37719 9.3239 7.90164 9.84835C8.42608 10.3728 8.78324 11.041 8.92793 11.7684C9.07263 12.4958 8.99836 13.2498 8.71454 13.9351C8.43071 14.6203 7.95006 15.206 7.33338 15.618C6.71669 16.0301 5.99167 16.25 5.24999 16.25C4.25543 16.25 3.3016 15.8549 2.59834 15.1517C1.89508 14.4484 1.49999 13.4946 1.49999 12.5ZM18.75 16.25C18.0083 16.25 17.2833 16.0301 16.6666 15.618C16.0499 15.206 15.5693 14.6203 15.2854 13.9351C15.0016 13.2498 14.9273 12.4958 15.072 11.7684C15.2167 11.041 15.5739 10.3728 16.0983 9.84835C16.6228 9.3239 17.291 8.96675 18.0184 8.82205C18.7458 8.67736 19.4998 8.75162 20.1851 9.03545C20.8703 9.31928 21.4559 9.79993 21.868 10.4166C22.2801 11.0333 22.5 11.7583 22.5 12.5C22.5 13.4946 22.1049 14.4484 21.4016 15.1517C20.6984 15.8549 19.7446 16.25 18.75 16.25Z" fill="#4E6074"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -55,6 +55,20 @@ void AccountModel::onRegistrationStateChanged(const std::shared_ptr<linphone::Ac
emit registrationStateChanged(account, state, message);
}
void AccountModel::onMessageWaitingIndicationChanged(
const std::shared_ptr<linphone::Account> &account,
const std::shared_ptr<const linphone::MessageWaitingIndication> &mwi) {
for (auto summary : mwi->getSummaries()) {
qInfo() << "[MWI] new" << summary->getNbNew() << "new+urgent" << summary->getNbNewUrgent() << "old"
<< summary->getNbOld() << "old+urgent" << summary->getNbOldUrgent();
auto userData = getUserData(account);
if (!userData) userData = std::make_shared<AccountUserData>();
userData->voicemailCount = summary->getNbNew();
setUserData(account, userData);
emit voicemailCountChanged(summary->getNbNew());
}
}
void AccountModel::setPictureUri(QString uri) {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
auto params = mMonitor->getParams()->clone();
@ -71,8 +85,8 @@ void AccountModel::setPictureUri(QString uri) {
mMonitor->setParams(params);
// Hack because Account doesn't provide callbacks on updated data
// emit pictureUriChanged(uri);
emit CoreModel::getInstance()->defaultAccountChanged(CoreModel::getInstance()->getCore(),
CoreModel::getInstance()->getCore()->getDefaultAccount());
auto core = CoreModel::getInstance()->getCore();
emit CoreModel::getInstance()->defaultAccountChanged(core, core->getDefaultAccount());
}
void AccountModel::onDefaultAccountChanged() {
@ -88,6 +102,7 @@ void AccountModel::setDefault() {
void AccountModel::removeAccount() {
CoreModel::getInstance()->getCore()->removeAccount(mMonitor);
removeUserData(mMonitor);
emit removed();
}
@ -283,3 +298,28 @@ QString AccountModel::dialPlanAsString(const std::shared_ptr<linphone::DialPlan>
return Utils::coreStringToAppString(dialPlan->getFlag() + " " + dialPlan->getCountry() + " | +" +
dialPlan->getCountryCallingCode());
}
int AccountModel::getVoicemailCount() {
auto userData = getUserData(mMonitor);
if (userData) return userData->voicemailCount;
else return 0;
}
// UserData (see hpp for explanations)
static QMap<const std::shared_ptr<linphone::Account>, std::shared_ptr<AccountUserData>> userDataMap;
void AccountModel::setUserData(const std::shared_ptr<linphone::Account> &account,
std::shared_ptr<AccountUserData> &data) {
mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO));
userDataMap[account] = data;
}
std::shared_ptr<AccountUserData> AccountModel::getUserData(const std::shared_ptr<linphone::Account> &account) {
mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO));
if (userDataMap.contains(account)) return userDataMap.value(account);
else return nullptr;
}
void AccountModel::removeUserData(const std::shared_ptr<linphone::Account> &account) {
mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO));
userDataMap.remove(account);
}

View file

@ -27,6 +27,8 @@
#include <QObject>
#include <linphone++/linphone.hh>
struct AccountUserData;
class AccountModel : public ::Listener<linphone::Account, linphone::AccountListener>,
public linphone::AccountListener,
public AbstractObject {
@ -38,6 +40,10 @@ public:
virtual void onRegistrationStateChanged(const std::shared_ptr<linphone::Account> &account,
linphone::RegistrationState state,
const std::string &message) override;
virtual void
onMessageWaitingIndicationChanged(const std::shared_ptr<linphone::Account> &account,
const std::shared_ptr<const linphone::MessageWaitingIndication> &mwi) override;
void onDefaultAccountChanged();
std::string getConfigAccountUiSection();
@ -67,6 +73,7 @@ public:
void setAudioVideoConferenceFactoryAddress(QString value);
void setLimeServerUrl(QString value);
QString dialPlanAsString(const std::shared_ptr<linphone::DialPlan> &dialPlan);
int getVoicemailCount();
signals:
void registrationStateChanged(const std::shared_ptr<linphone::Account> &account,
@ -93,9 +100,24 @@ signals:
void audioVideoConferenceFactoryAddressChanged(QString value);
void limeServerUrlChanged(QString value);
void removed();
void voicemailCountChanged(int count);
private:
// UserData
static void setUserData(const std::shared_ptr<linphone::Account> &account, std::shared_ptr<AccountUserData> &data);
static std::shared_ptr<AccountUserData> getUserData(const std::shared_ptr<linphone::Account> &account);
static void removeUserData(const std::shared_ptr<linphone::Account> &account);
DECLARE_ABSTRACT_OBJECT
};
// UserData : user data storage for linphone account information, that cannot be retrieved from Linphone account object
// through API, but received through listeners (example MWI/Voicemail count). Usually this is done using (s/g)etUserData
// on Linphone Objects on other wrappers, but not available in C++ Wrapper.
struct AccountUserData {
int voicemailCount;
// ..
};
#endif

View file

@ -67,6 +67,11 @@ public:
Q_SIGNAL void x##Changed(); \
type m##X;
#define DECLARE_CORE_GET(type, x, X) \
Q_PROPERTY(type x MEMBER m##X NOTIFY x##Changed) \
Q_SIGNAL void x##Changed(); \
type m##X;
#define DECLARE_GETSET(type, x, X) \
type get##X() const; \
void set##X(type data); \
@ -86,6 +91,14 @@ public:
}); \
});
#define DEFINE_CORE_GET_CONNECT(safe, CoreClass, ModelClass, model, type, x, X) \
safe->makeConnectToModel(&ModelClass::x##Changed, [this](type data) { \
safe->invokeToCore([this, data]() { \
m##X = data; \
emit x##Changed(); \
}); \
});
#define DEFINE_GETSET_CONFIG(Class, type, Type, x, X, key, def) \
type Class::get##X() const { \
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); \

View file

@ -406,6 +406,30 @@ Item {
}
}
}
Voicemail {
id: voicemail
Layout.preferredWidth: 27 * DefaultStyle.dp
Layout.preferredHeight: 28 * DefaultStyle.dp
function cumulatedVoicemailCount() {
var count = 0
for (var i=0 ; i < accountProxy.count ; i++ )
count += accountProxy.getAt(i).core.voicemailCount
return count
}
voicemailCount: cumulatedVoicemailCount()
onClicked: {
if (accountProxy.count > 1) {
avatarButton.popup.open()
} else {
if (accountProxy.defaultAccount.core.mwiServerAddress.length > 0)
UtilsCpp.createCall(accountProxy.defaultAccount.core.mwiServerAddress)
else
UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("L'adresse de la messagerie vocale n'est pas définie."), false)
}
}
}
PopupButton {
id: avatarButton
Layout.preferredWidth: 54 * DefaultStyle.dp

View file

@ -52,6 +52,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
view/Item/Contact/ContactEdition.qml
view/Item/Contact/ContactsList.qml
view/Item/Contact/Sticker.qml
view/Item/Contact/Voicemail.qml
view/Item/Meeting/MeetingList.qml
view/Item/Meeting/MeetingSetUp.qml

View file

@ -106,7 +106,7 @@ Rectangle{
Layout.preferredHeight: 26 * DefaultStyle.dp
Layout.fillHeight: true
Layout.leftMargin: 40 * DefaultStyle.dp
visible: mainItem.account.core.unreadCallNotifications > 0
visible: true // mainItem.account.core.unreadCallNotifications > 0
Rectangle{
id: unreadNotifications
anchors.verticalCenter: parent.verticalCenter
@ -138,6 +138,19 @@ Rectangle{
shadowOpacity: 0.15
}
}
Voicemail {
Layout.leftMargin: 18 * DefaultStyle.dp
Layout.rightMargin: 20 * DefaultStyle.dp
Layout.preferredWidth: 27 * DefaultStyle.dp
Layout.preferredHeight: 28 * DefaultStyle.dp
voicemailCount: mainItem.account.core.voicemailCount >= 100 ? '99+' : mainItem.account.core.voicemailCount
onClicked: {
if (mainItem.account.core.mwiServerAddress.length > 0)
UtilsCpp.createCall(mainItem.account.core.mwiServerAddress)
else
UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("L'adresse de la messagerie vocale n'est pas définie."), false)
}
}
Item{Layout.fillWidth: true}
EffectImage {
id: manageAccount

View file

@ -0,0 +1,38 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Linphone
import UtilsCpp
import SettingsCpp
Rectangle{
id: mainItem
property int voicemailCount: 0
visible: voicemailCount > 0
width: 27 * DefaultStyle.dp
height: 28 * DefaultStyle.dp
signal clicked()
Button {
anchors.bottom: parent.bottom
anchors.left: parent.left
icon.source: AppIcons.voicemail
width: 24 * DefaultStyle.dp
height: 24 * DefaultStyle.dp
background: Item {
anchors.fill: parent
}
onClicked: {
mainItem.clicked()
}
}
Text {
anchors.top: parent.top
anchors.right: parent.right
font.weight: 700 * DefaultStyle.dp
font.pixelSize: 10 * DefaultStyle.dp
color: DefaultStyle.danger_500main
text: voicemailCount
maximumLineCount: 1
}
}

View file

@ -115,4 +115,5 @@ QtObject {
property string desktop: "image://internal/desktop.svg"
property string calendar: "image://internal/calendar.svg"
property string bellDnd: "image://internal/bell-dnd.svg"
property string voicemail: "image://internal/voicemail.svg"
}