Fix crashes on SafeConnection.
Display missed notifications and fit text size from content. Add account from profile menu and display Login Page with back button. Default account selection and change avatar from accounts list. Remove deprecated function on Friends DB. Return username by default on display name computation. Update SDK.
This commit is contained in:
parent
4ea1b96246
commit
a43430fa34
35 changed files with 313 additions and 234 deletions
|
|
@ -46,6 +46,8 @@ AccountCore::AccountCore(const std::shared_ptr<linphone::Account> &account) : QO
|
||||||
mPictureUri = Utils::coreStringToAppString(params->getPictureUri());
|
mPictureUri = Utils::coreStringToAppString(params->getPictureUri());
|
||||||
mRegistrationState = LinphoneEnums::fromLinphone(account->getState());
|
mRegistrationState = LinphoneEnums::fromLinphone(account->getState());
|
||||||
mIsDefaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount() == account;
|
mIsDefaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount() == account;
|
||||||
|
// mUnreadNotifications = account->getUnreadChatMessageCount() + account->getMissedCallsCount(); // TODO
|
||||||
|
mUnreadNotifications = account->getMissedCallsCount();
|
||||||
|
|
||||||
// Add listener
|
// Add listener
|
||||||
mAccountModel = Utils::makeQObject_ptr<AccountModel>(account); // OK
|
mAccountModel = Utils::makeQObject_ptr<AccountModel>(account); // OK
|
||||||
|
|
@ -58,30 +60,34 @@ AccountCore::~AccountCore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountCore::setSelf(QSharedPointer<AccountCore> me) {
|
void AccountCore::setSelf(QSharedPointer<AccountCore> me) {
|
||||||
mAccountModelConnection = QSharedPointer<SafeConnection>(
|
mAccountModelConnection = QSharedPointer<SafeConnection<AccountCore, AccountModel>>(
|
||||||
new SafeConnection(me.objectCast<QObject>(), std::dynamic_pointer_cast<QObject>(mAccountModel)));
|
new SafeConnection<AccountCore, AccountModel>(me, mAccountModel));
|
||||||
mAccountModelConnection->makeConnect(mAccountModel.get(), &AccountModel::registrationStateChanged,
|
mAccountModelConnection->makeConnectToModel(
|
||||||
[this](const std::shared_ptr<linphone::Account> &account,
|
&AccountModel::registrationStateChanged, [this](const std::shared_ptr<linphone::Account> &account,
|
||||||
linphone::RegistrationState state, const std::string &message) {
|
linphone::RegistrationState state, const std::string &message) {
|
||||||
mAccountModelConnection->invokeToCore([this, account, state, message]() {
|
mAccountModelConnection->invokeToCore(
|
||||||
this->onRegistrationStateChanged(account, state, message);
|
[this, account, state, message]() { this->onRegistrationStateChanged(account, state, message); });
|
||||||
});
|
|
||||||
});
|
|
||||||
// From Model
|
|
||||||
mAccountModelConnection->makeConnect(
|
|
||||||
mAccountModel.get(), &AccountModel::defaultAccountChanged, [this](bool isDefault) {
|
|
||||||
mAccountModelConnection->invokeToCore([this, isDefault]() { this->onDefaultAccountChanged(isDefault); });
|
|
||||||
});
|
});
|
||||||
|
// From Model
|
||||||
|
mAccountModelConnection->makeConnectToModel(&AccountModel::defaultAccountChanged, [this](bool isDefault) {
|
||||||
|
mAccountModelConnection->invokeToCore([this, isDefault]() { this->onDefaultAccountChanged(isDefault); });
|
||||||
|
});
|
||||||
|
|
||||||
mAccountModelConnection->makeConnect(mAccountModel.get(), &AccountModel::pictureUriChanged, [this](QString uri) {
|
mAccountModelConnection->makeConnectToModel(&AccountModel::pictureUriChanged, [this](QString uri) {
|
||||||
mAccountModelConnection->invokeToCore([this, uri]() { this->onPictureUriChanged(uri); });
|
mAccountModelConnection->invokeToCore([this, uri]() { this->onPictureUriChanged(uri); });
|
||||||
});
|
});
|
||||||
|
mAccountModelConnection->makeConnectToModel(
|
||||||
|
&AccountModel::unreadNotificationsChanged, [this](int unreadMessagesCount, int unreadCallsCount) {
|
||||||
|
mAccountModelConnection->invokeToCore([this, unreadMessagesCount, unreadCallsCount]() {
|
||||||
|
this->setUnreadNotifications(unreadMessagesCount + unreadCallsCount);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// From GUI
|
// From GUI
|
||||||
mAccountModelConnection->makeConnect(this, &AccountCore::lSetPictureUri, [this](QString uri) {
|
mAccountModelConnection->makeConnectToCore(&AccountCore::lSetPictureUri, [this](QString uri) {
|
||||||
mAccountModelConnection->invokeToModel([this, uri]() { mAccountModel->setPictureUri(uri); });
|
mAccountModelConnection->invokeToModel([this, uri]() { mAccountModel->setPictureUri(uri); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnect(this, &AccountCore::lSetDefaultAccount, [this]() {
|
mAccountModelConnection->makeConnectToCore(&AccountCore::lSetDefaultAccount, [this]() {
|
||||||
mAccountModelConnection->invokeToModel([this]() { mAccountModel->setDefault(); });
|
mAccountModelConnection->invokeToModel([this]() { mAccountModel->setDefault(); });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -106,6 +112,16 @@ bool AccountCore::getIsDefaultAccount() const {
|
||||||
return mIsDefaultAccount;
|
return mIsDefaultAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AccountCore::getUnreadNotifications() const {
|
||||||
|
return mUnreadNotifications;
|
||||||
|
}
|
||||||
|
void AccountCore::setUnreadNotifications(int unread) {
|
||||||
|
if (mUnreadNotifications != unread) {
|
||||||
|
mUnreadNotifications = unread;
|
||||||
|
emit unreadNotificationsChanged(unread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AccountCore::onRegistrationStateChanged(const std::shared_ptr<linphone::Account> &account,
|
void AccountCore::onRegistrationStateChanged(const std::shared_ptr<linphone::Account> &account,
|
||||||
linphone::RegistrationState state,
|
linphone::RegistrationState state,
|
||||||
const std::string &message) {
|
const std::string &message) {
|
||||||
|
|
@ -124,3 +140,7 @@ void AccountCore::onPictureUriChanged(QString uri) {
|
||||||
mPictureUri = uri;
|
mPictureUri = uri;
|
||||||
emit pictureUriChanged();
|
emit pictureUriChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AccountCore::removeAccount() {
|
||||||
|
mAccountModelConnection->invokeToModel([this]() { mAccountModel->removeAccount(); });
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ class AccountCore : public QObject, public AbstractObject {
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(
|
||||||
LinphoneEnums::RegistrationState registrationState READ getRegistrationState NOTIFY registrationStateChanged)
|
LinphoneEnums::RegistrationState registrationState READ getRegistrationState NOTIFY registrationStateChanged)
|
||||||
Q_PROPERTY(bool isDefaultAccount READ getIsDefaultAccount NOTIFY defaultAccountChanged)
|
Q_PROPERTY(bool isDefaultAccount READ getIsDefaultAccount NOTIFY defaultAccountChanged)
|
||||||
|
Q_PROPERTY(int unreadNotifications READ getUnreadNotifications NOTIFY unreadNotificationsChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static QSharedPointer<AccountCore> create(const std::shared_ptr<linphone::Account> &account);
|
static QSharedPointer<AccountCore> create(const std::shared_ptr<linphone::Account> &account);
|
||||||
|
|
@ -50,6 +51,8 @@ public:
|
||||||
QString getPictureUri() const;
|
QString getPictureUri() const;
|
||||||
LinphoneEnums::RegistrationState getRegistrationState() const;
|
LinphoneEnums::RegistrationState getRegistrationState() const;
|
||||||
bool getIsDefaultAccount() const;
|
bool getIsDefaultAccount() const;
|
||||||
|
int getUnreadNotifications() const;
|
||||||
|
void setUnreadNotifications(int unread);
|
||||||
|
|
||||||
void onPictureUriChanged(QString uri);
|
void onPictureUriChanged(QString uri);
|
||||||
void onRegistrationStateChanged(const std::shared_ptr<linphone::Account> &account,
|
void onRegistrationStateChanged(const std::shared_ptr<linphone::Account> &account,
|
||||||
|
|
@ -57,11 +60,13 @@ public:
|
||||||
const std::string &message);
|
const std::string &message);
|
||||||
|
|
||||||
void onDefaultAccountChanged(bool isDefault);
|
void onDefaultAccountChanged(bool isDefault);
|
||||||
|
Q_INVOKABLE void removeAccount();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void pictureUriChanged();
|
void pictureUriChanged();
|
||||||
void registrationStateChanged(const QString &message);
|
void registrationStateChanged(const QString &message);
|
||||||
void defaultAccountChanged(bool isDefault);
|
void defaultAccountChanged(bool isDefault);
|
||||||
|
void unreadNotificationsChanged(int unreadNotifications);
|
||||||
|
|
||||||
// Account requests
|
// Account requests
|
||||||
void lSetPictureUri(QString pictureUri);
|
void lSetPictureUri(QString pictureUri);
|
||||||
|
|
@ -73,8 +78,9 @@ private:
|
||||||
QString mPictureUri;
|
QString mPictureUri;
|
||||||
bool mIsDefaultAccount = false;
|
bool mIsDefaultAccount = false;
|
||||||
LinphoneEnums::RegistrationState mRegistrationState;
|
LinphoneEnums::RegistrationState mRegistrationState;
|
||||||
|
int mUnreadNotifications = 0;
|
||||||
std::shared_ptr<AccountModel> mAccountModel;
|
std::shared_ptr<AccountModel> mAccountModel;
|
||||||
QSharedPointer<SafeConnection> mAccountModelConnection;
|
QSharedPointer<SafeConnection<AccountCore, AccountModel>> mAccountModelConnection;
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
DEFINE_ABSTRACT_OBJECT(AccountGui)
|
DEFINE_ABSTRACT_OBJECT(AccountGui)
|
||||||
|
|
||||||
AccountGui::AccountGui(QSharedPointer<AccountCore> core) {
|
AccountGui::AccountGui(QSharedPointer<AccountCore> core) {
|
||||||
qDebug() << "[AccountGui] new" << this;
|
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
|
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
|
||||||
mCore = core;
|
mCore = core;
|
||||||
if (isInLinphoneThread()) moveToThread(App::getInstance()->thread());
|
if (isInLinphoneThread()) moveToThread(App::getInstance()->thread());
|
||||||
|
|
@ -32,7 +31,6 @@ AccountGui::AccountGui(QSharedPointer<AccountCore> core) {
|
||||||
|
|
||||||
AccountGui::~AccountGui() {
|
AccountGui::~AccountGui() {
|
||||||
mustBeInMainThread("~" + getClassName());
|
mustBeInMainThread("~" + getClassName());
|
||||||
qDebug() << "[AccountGui] delete" << this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AccountCore *AccountGui::getCore() const {
|
AccountCore *AccountGui::getCore() const {
|
||||||
|
|
|
||||||
|
|
@ -37,51 +37,54 @@ QSharedPointer<AccountList> AccountList::create() {
|
||||||
}
|
}
|
||||||
|
|
||||||
AccountList::AccountList(QObject *parent) : ListProxy(parent) {
|
AccountList::AccountList(QObject *parent) : ListProxy(parent) {
|
||||||
qDebug() << "[AccountList] new" << this;
|
|
||||||
mustBeInMainThread(getClassName());
|
mustBeInMainThread(getClassName());
|
||||||
connect(CoreModel::getInstance().get(), &CoreModel::accountAdded, this, &AccountList::lUpdate);
|
connect(CoreModel::getInstance().get(), &CoreModel::accountAdded, this, &AccountList::lUpdate);
|
||||||
connect(CoreModel::getInstance().get(), &CoreModel::accountRemoved, this, &AccountList::lUpdate);
|
connect(CoreModel::getInstance().get(), &CoreModel::accountRemoved, this, &AccountList::lUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
AccountList::~AccountList() {
|
AccountList::~AccountList() {
|
||||||
qDebug() << "[AccountList] delete" << this;
|
|
||||||
mustBeInMainThread("~" + getClassName());
|
mustBeInMainThread("~" + getClassName());
|
||||||
|
mModelConnection = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountList::setSelf(QSharedPointer<AccountList> me) {
|
void AccountList::setSelf(QSharedPointer<AccountList> me) {
|
||||||
mModelConnection = QSharedPointer<SafeConnection>(
|
mModelConnection = QSharedPointer<SafeConnection<AccountList, CoreModel>>(
|
||||||
new SafeConnection(me.objectCast<QObject>(), std::dynamic_pointer_cast<QObject>(CoreModel::getInstance())),
|
new SafeConnection<AccountList, CoreModel>(me, CoreModel::getInstance()), &QObject::deleteLater);
|
||||||
&QObject::deleteLater);
|
|
||||||
mModelConnection->makeConnect(this, &AccountList::lUpdate, [this]() {
|
mModelConnection->makeConnectToCore(&AccountList::lUpdate, [this]() {
|
||||||
mModelConnection->invokeToModel([this]() {
|
mModelConnection->invokeToModel([this]() {
|
||||||
|
// Avoid copy to lambdas
|
||||||
QList<QSharedPointer<AccountCore>> *accounts = new QList<QSharedPointer<AccountCore>>();
|
QList<QSharedPointer<AccountCore>> *accounts = new QList<QSharedPointer<AccountCore>>();
|
||||||
// Model thread.
|
|
||||||
mustBeInLinphoneThread(getClassName());
|
mustBeInLinphoneThread(getClassName());
|
||||||
auto linphoneAccounts = CoreModel::getInstance()->getCore()->getAccountList();
|
auto linphoneAccounts = CoreModel::getInstance()->getCore()->getAccountList();
|
||||||
|
auto defaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
|
||||||
|
QSharedPointer<AccountCore> defaultAccountCore;
|
||||||
for (auto it : linphoneAccounts) {
|
for (auto it : linphoneAccounts) {
|
||||||
auto model = AccountCore::create(it);
|
auto model = AccountCore::create(it);
|
||||||
|
if (it == defaultAccount) defaultAccountCore = AccountCore::create(defaultAccount);
|
||||||
accounts->push_back(model);
|
accounts->push_back(model);
|
||||||
}
|
}
|
||||||
mModelConnection->invokeToCore([this, accounts]() {
|
mModelConnection->invokeToCore([this, accounts, defaultAccountCore]() {
|
||||||
mustBeInMainThread(getClassName());
|
mustBeInMainThread(getClassName());
|
||||||
resetData();
|
resetData();
|
||||||
add(*accounts);
|
add(*accounts);
|
||||||
setHaveAccount(accounts->size() > 0);
|
setHaveAccount(accounts->size() > 0);
|
||||||
|
setDefaultAccount(defaultAccountCore);
|
||||||
delete accounts;
|
delete accounts;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
mModelConnection->makeConnect(CoreModel::getInstance().get(), &CoreModel::defaultAccountChanged,
|
mModelConnection->makeConnectToModel(
|
||||||
[this]() { mModelConnection->invokeToCore([this]() { defaultAccountChanged(); }); });
|
&CoreModel::defaultAccountChanged,
|
||||||
|
[this](const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::Account> &account) {
|
||||||
|
auto model = AccountCore::create(account);
|
||||||
|
mModelConnection->invokeToCore([this, model]() { setDefaultAccount(model); });
|
||||||
|
});
|
||||||
lUpdate();
|
lUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<AccountCore> AccountList::getDefaultAccountCore() const {
|
QSharedPointer<AccountCore> AccountList::getDefaultAccountCore() const {
|
||||||
for (auto it : mList) {
|
return mDefaultAccount;
|
||||||
auto account = it.objectCast<AccountCore>();
|
|
||||||
if (account->getIsDefaultAccount()) return account;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AccountGui *AccountList::getDefaultAccount() const {
|
AccountGui *AccountList::getDefaultAccount() const {
|
||||||
|
|
@ -89,6 +92,13 @@ AccountGui *AccountList::getDefaultAccount() const {
|
||||||
if (account) return new AccountGui(account);
|
if (account) return new AccountGui(account);
|
||||||
else return nullptr;
|
else return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AccountList::setDefaultAccount(QSharedPointer<AccountCore> account) {
|
||||||
|
if (mDefaultAccount != account) {
|
||||||
|
mDefaultAccount = account;
|
||||||
|
emit defaultAccountChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
bool AccountList::getHaveAccount() const {
|
bool AccountList::getHaveAccount() const {
|
||||||
return mHaveAccount;
|
return mHaveAccount;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
class AccountGui;
|
class AccountGui;
|
||||||
class AccountCore;
|
class AccountCore;
|
||||||
|
class CoreModel;
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
class AccountList : public ListProxy, public AbstractObject {
|
class AccountList : public ListProxy, public AbstractObject {
|
||||||
|
|
@ -41,6 +42,7 @@ public:
|
||||||
|
|
||||||
AccountGui *getDefaultAccount() const;
|
AccountGui *getDefaultAccount() const;
|
||||||
QSharedPointer<AccountCore> getDefaultAccountCore() const;
|
QSharedPointer<AccountCore> getDefaultAccountCore() const;
|
||||||
|
void setDefaultAccount(QSharedPointer<AccountCore> account);
|
||||||
|
|
||||||
bool getHaveAccount() const;
|
bool getHaveAccount() const;
|
||||||
void setHaveAccount(bool haveAccount);
|
void setHaveAccount(bool haveAccount);
|
||||||
|
|
@ -53,7 +55,8 @@ signals:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mHaveAccount = false;
|
bool mHaveAccount = false;
|
||||||
QSharedPointer<SafeConnection> mModelConnection;
|
QSharedPointer<AccountCore> mDefaultAccount;
|
||||||
|
QSharedPointer<SafeConnection<AccountList, CoreModel>> mModelConnection;
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
#include "AccountList.hpp"
|
#include "AccountList.hpp"
|
||||||
|
|
||||||
AccountProxy::AccountProxy(QObject *parent) : SortFilterProxy(parent) {
|
AccountProxy::AccountProxy(QObject *parent) : SortFilterProxy(parent) {
|
||||||
qDebug() << "[AccountProxy] new" << this;
|
|
||||||
mList = AccountList::create();
|
mList = AccountList::create();
|
||||||
connect(mList.get(), &AccountList::countChanged, this, &AccountProxy::resetDefaultAccount);
|
connect(mList.get(), &AccountList::countChanged, this, &AccountProxy::resetDefaultAccount);
|
||||||
connect(mList.get(), &AccountList::defaultAccountChanged, this, &AccountProxy::resetDefaultAccount);
|
connect(mList.get(), &AccountList::defaultAccountChanged, this, &AccountProxy::resetDefaultAccount);
|
||||||
|
|
@ -33,7 +32,7 @@ AccountProxy::AccountProxy(QObject *parent) : SortFilterProxy(parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
AccountProxy::~AccountProxy() {
|
AccountProxy::~AccountProxy() {
|
||||||
qDebug() << "[AccountProxy] delete" << this;
|
setSourceModel(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AccountProxy::getFilterText() const {
|
QString AccountProxy::getFilterText() const {
|
||||||
|
|
@ -59,7 +58,7 @@ void AccountProxy::setDefaultAccount(AccountGui *account) {
|
||||||
// Reset the default account to let UI build its new object if needed.
|
// Reset the default account to let UI build its new object if needed.
|
||||||
void AccountProxy::resetDefaultAccount() {
|
void AccountProxy::resetDefaultAccount() {
|
||||||
mDefaultAccount = nullptr;
|
mDefaultAccount = nullptr;
|
||||||
this->defaultAccountChanged(); // Warn the UI
|
emit this->defaultAccountChanged(); // Warn the UI
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AccountProxy::getHaveAccount() const {
|
bool AccountProxy::getHaveAccount() const {
|
||||||
|
|
|
||||||
|
|
@ -67,13 +67,12 @@ CallCore::~CallCore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
mAccountModelConnection = QSharedPointer<SafeConnection>(
|
mAccountModelConnection = QSharedPointer<SafeConnection<CallCore, CallModel>>(
|
||||||
new SafeConnection(me.objectCast<QObject>(), std::dynamic_pointer_cast<QObject>(mCallModel)),
|
new SafeConnection<CallCore, CallModel>(me, mCallModel), &QObject::deleteLater);
|
||||||
&QObject::deleteLater);
|
mAccountModelConnection->makeConnectToCore(&CallCore::lSetMicrophoneMuted, [this](bool isMuted) {
|
||||||
mAccountModelConnection->makeConnect(this, &CallCore::lSetMicrophoneMuted, [this](bool isMuted) {
|
|
||||||
mAccountModelConnection->invokeToModel([this, isMuted]() { mCallModel->setMicrophoneMuted(isMuted); });
|
mAccountModelConnection->invokeToModel([this, isMuted]() { mCallModel->setMicrophoneMuted(isMuted); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnect(mCallModel.get(), &CallModel::microphoneMutedChanged, [this](bool isMuted) {
|
mAccountModelConnection->makeConnectToModel(&CallModel::microphoneMutedChanged, [this](bool isMuted) {
|
||||||
mAccountModelConnection->invokeToCore([this, isMuted]() { setMicrophoneMuted(isMuted); });
|
mAccountModelConnection->invokeToCore([this, isMuted]() { setMicrophoneMuted(isMuted); });
|
||||||
});
|
});
|
||||||
// mAccountModelConnection->makeConnect(this, &CallCore::lSetSpeakerMuted, [this](bool isMuted) {
|
// mAccountModelConnection->makeConnect(this, &CallCore::lSetSpeakerMuted, [this](bool isMuted) {
|
||||||
|
|
@ -82,37 +81,37 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
// mAccountModelConnection->makeConnect(mCallModel.get(), &CallModel::speakerMutedChanged, [this](bool isMuted) {
|
// mAccountModelConnection->makeConnect(mCallModel.get(), &CallModel::speakerMutedChanged, [this](bool isMuted) {
|
||||||
// mAccountModelConnection->invokeToCore([this, isMuted]() { setSpeakerMuted(isMuted); });
|
// mAccountModelConnection->invokeToCore([this, isMuted]() { setSpeakerMuted(isMuted); });
|
||||||
// });
|
// });
|
||||||
mAccountModelConnection->makeConnect(this, &CallCore::lSetCameraEnabled, [this](bool enabled) {
|
mAccountModelConnection->makeConnectToCore(&CallCore::lSetCameraEnabled, [this](bool enabled) {
|
||||||
mAccountModelConnection->invokeToModel([this, enabled]() { mCallModel->setCameraEnabled(enabled); });
|
mAccountModelConnection->invokeToModel([this, enabled]() { mCallModel->setCameraEnabled(enabled); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnect(mCallModel.get(), &CallModel::cameraEnabledChanged, [this](bool enabled) {
|
mAccountModelConnection->makeConnectToModel(&CallModel::cameraEnabledChanged, [this](bool enabled) {
|
||||||
mAccountModelConnection->invokeToCore([this, enabled]() { setCameraEnabled(enabled); });
|
mAccountModelConnection->invokeToCore([this, enabled]() { setCameraEnabled(enabled); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnect(mCallModel.get(), &CallModel::durationChanged, [this](int duration) {
|
mAccountModelConnection->makeConnectToModel(&CallModel::durationChanged, [this](int duration) {
|
||||||
mAccountModelConnection->invokeToCore([this, duration]() { setDuration(duration); });
|
mAccountModelConnection->invokeToCore([this, duration]() { setDuration(duration); });
|
||||||
});
|
});
|
||||||
connect(mCallModel.get(), &CallModel::stateChanged, this,
|
mAccountModelConnection->makeConnectToModel(
|
||||||
[this](linphone::Call::State state, const std::string &message) {
|
&CallModel::stateChanged, [this](linphone::Call::State state, const std::string &message) {
|
||||||
mAccountModelConnection->invokeToCore([this, state, message]() {
|
mAccountModelConnection->invokeToCore([this, state, message]() {
|
||||||
setState(LinphoneEnums::fromLinphone(state), Utils::coreStringToAppString(message));
|
setState(LinphoneEnums::fromLinphone(state), Utils::coreStringToAppString(message));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
connect(mCallModel.get(), &CallModel::statusChanged, this, [this](linphone::Call::Status status) {
|
mAccountModelConnection->makeConnectToModel(&CallModel::statusChanged, [this](linphone::Call::Status status) {
|
||||||
mAccountModelConnection->invokeToCore([this, status]() { setStatus(LinphoneEnums::fromLinphone(status)); });
|
mAccountModelConnection->invokeToCore([this, status]() { setStatus(LinphoneEnums::fromLinphone(status)); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnect(this, &CallCore::lSetPaused, [this](bool paused) {
|
mAccountModelConnection->makeConnectToCore(&CallCore::lSetPaused, [this](bool paused) {
|
||||||
mAccountModelConnection->invokeToModel([this, paused]() { mCallModel->setPaused(paused); });
|
mAccountModelConnection->invokeToModel([this, paused]() { mCallModel->setPaused(paused); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnect(mCallModel.get(), &CallModel::pausedChanged, [this](bool paused) {
|
mAccountModelConnection->makeConnectToModel(&CallModel::pausedChanged, [this](bool paused) {
|
||||||
mAccountModelConnection->invokeToCore([this, paused]() { setPaused(paused); });
|
mAccountModelConnection->invokeToCore([this, paused]() { setPaused(paused); });
|
||||||
});
|
});
|
||||||
|
|
||||||
mAccountModelConnection->makeConnect(this, &CallCore::lTransferCall, [this](const QString &address) {
|
mAccountModelConnection->makeConnectToCore(&CallCore::lTransferCall, [this](const QString &address) {
|
||||||
mAccountModelConnection->invokeToModel(
|
mAccountModelConnection->invokeToModel(
|
||||||
[this, address]() { mCallModel->transferTo(ToolModel::interpretUrl(address)); });
|
[this, address]() { mCallModel->transferTo(ToolModel::interpretUrl(address)); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnect(
|
mAccountModelConnection->makeConnectToModel(
|
||||||
mCallModel.get(), &CallModel::transferStateChanged,
|
&CallModel::transferStateChanged,
|
||||||
[this](const std::shared_ptr<linphone::Call> &call, linphone::Call::State state) {
|
[this](const std::shared_ptr<linphone::Call> &call, linphone::Call::State state) {
|
||||||
mAccountModelConnection->invokeToCore([this, state]() {
|
mAccountModelConnection->invokeToCore([this, state]() {
|
||||||
QString message;
|
QString message;
|
||||||
|
|
@ -122,8 +121,8 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
setTransferState(LinphoneEnums::fromLinphone(state), message);
|
setTransferState(LinphoneEnums::fromLinphone(state), message);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnect(
|
mAccountModelConnection->makeConnectToModel(
|
||||||
mCallModel.get(), &CallModel::encryptionChanged,
|
&CallModel::encryptionChanged,
|
||||||
[this](const std::shared_ptr<linphone::Call> &call, bool on, const std::string &authenticationToken) {
|
[this](const std::shared_ptr<linphone::Call> &call, bool on, const std::string &authenticationToken) {
|
||||||
auto encryption = LinphoneEnums::fromLinphone(call->getCurrentParams()->getMediaEncryption());
|
auto encryption = LinphoneEnums::fromLinphone(call->getCurrentParams()->getMediaEncryption());
|
||||||
auto tokenVerified = mCallModel->getAuthenticationTokenVerified();
|
auto tokenVerified = mCallModel->getAuthenticationTokenVerified();
|
||||||
|
|
@ -133,13 +132,12 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
encryption == LinphoneEnums::MediaEncryption::Dtls);
|
encryption == LinphoneEnums::MediaEncryption::Dtls);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnect(this, &CallCore::lAccept, [this](bool withVideo) {
|
mAccountModelConnection->makeConnectToCore(&CallCore::lAccept, [this](bool withVideo) {
|
||||||
mAccountModelConnection->invokeToModel([this, withVideo]() { mCallModel->accept(withVideo); });
|
mAccountModelConnection->invokeToModel([this, withVideo]() { mCallModel->accept(withVideo); });
|
||||||
});
|
});
|
||||||
mAccountModelConnection->makeConnect(this, &CallCore::lDecline, [this]() {
|
mAccountModelConnection->makeConnectToCore(
|
||||||
mAccountModelConnection->invokeToModel([this]() { mCallModel->decline(); });
|
&CallCore::lDecline, [this]() { mAccountModelConnection->invokeToModel([this]() { mCallModel->decline(); }); });
|
||||||
});
|
mAccountModelConnection->makeConnectToCore(&CallCore::lTerminate, [this]() {
|
||||||
mAccountModelConnection->makeConnect(this, &CallCore::lTerminate, [this]() {
|
|
||||||
mAccountModelConnection->invokeToModel([this]() { mCallModel->terminate(); });
|
mAccountModelConnection->invokeToModel([this]() { mCallModel->terminate(); });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,11 @@
|
||||||
|
|
||||||
#include "model/call/CallModel.hpp"
|
#include "model/call/CallModel.hpp"
|
||||||
#include "tool/LinphoneEnums.hpp"
|
#include "tool/LinphoneEnums.hpp"
|
||||||
|
#include "tool/thread/SafeConnection.hpp"
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <linphone++/linphone.hh>
|
#include <linphone++/linphone.hh>
|
||||||
|
|
||||||
class SafeConnection;
|
|
||||||
|
|
||||||
class CallCore : public QObject, public AbstractObject {
|
class CallCore : public QObject, public AbstractObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|
@ -138,7 +137,7 @@ private:
|
||||||
bool mMicrophoneMuted;
|
bool mMicrophoneMuted;
|
||||||
bool mCameraEnabled;
|
bool mCameraEnabled;
|
||||||
bool mPaused = false;
|
bool mPaused = false;
|
||||||
QSharedPointer<SafeConnection> mAccountModelConnection;
|
QSharedPointer<SafeConnection<CallCore, CallModel>> mAccountModelConnection;
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -56,35 +56,36 @@ FriendCore::FriendCore(const FriendCore &friendCore) {
|
||||||
FriendCore::~FriendCore() {
|
FriendCore::~FriendCore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FriendCore::setSelf(QSharedPointer<FriendCore> me) {
|
void FriendCore::setSelf(SafeSharedPointer<FriendCore> me) {
|
||||||
setSelf(me.objectCast<QObject>());
|
setSelf(me.mQDataWeak.lock());
|
||||||
}
|
}
|
||||||
|
void FriendCore::setSelf(QSharedPointer<FriendCore> me) {
|
||||||
void FriendCore::setSelf(SafeSharedPointer<QObject> me) {
|
if (me) {
|
||||||
if (mFriendModel) {
|
if (mFriendModel) {
|
||||||
mFriendModelConnection = QSharedPointer<SafeConnection>(
|
mCoreModelConnection = nullptr; // No more needed
|
||||||
new SafeConnection(me, std::dynamic_pointer_cast<QObject>(mFriendModel)), &QObject::deleteLater);
|
mFriendModelConnection = QSharedPointer<SafeConnection<FriendCore, FriendModel>>(
|
||||||
mFriendModelConnection->makeConnect(
|
new SafeConnection<FriendCore, FriendModel>(me, mFriendModel), &QObject::deleteLater);
|
||||||
mFriendModel.get(), &FriendModel::presenceReceived,
|
mFriendModelConnection->makeConnectToModel(
|
||||||
[this](LinphoneEnums::ConsolidatedPresence consolidatedPresence, QDateTime presenceTimestamp) {
|
&FriendModel::presenceReceived,
|
||||||
mFriendModelConnection->invokeToCore([this, consolidatedPresence, presenceTimestamp]() {
|
[this](LinphoneEnums::ConsolidatedPresence consolidatedPresence, QDateTime presenceTimestamp) {
|
||||||
setConsolidatedPresence(consolidatedPresence);
|
mFriendModelConnection->invokeToCore([this, consolidatedPresence, presenceTimestamp]() {
|
||||||
setPresenceTimestamp(presenceTimestamp);
|
setConsolidatedPresence(consolidatedPresence);
|
||||||
|
setPresenceTimestamp(presenceTimestamp);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
mFriendModelConnection->makeConnectToModel(&FriendModel::pictureUriChanged, [this](QString uri) {
|
||||||
mFriendModelConnection->makeConnect(mFriendModel.get(), &FriendModel::pictureUriChanged, [this](QString uri) {
|
mFriendModelConnection->invokeToCore([this, uri]() { this->onPictureUriChanged(uri); });
|
||||||
mFriendModelConnection->invokeToCore([this, uri]() { this->onPictureUriChanged(uri); });
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// From GUI
|
// From GUI
|
||||||
mFriendModelConnection->makeConnect(this, &FriendCore::lSetPictureUri, [this](QString uri) {
|
mFriendModelConnection->makeConnectToCore(&FriendCore::lSetPictureUri, [this](QString uri) {
|
||||||
mFriendModelConnection->invokeToModel([this, uri]() { mFriendModel->setPictureUri(uri); });
|
mFriendModelConnection->invokeToModel([this, uri]() { mFriendModel->setPictureUri(uri); });
|
||||||
});
|
});
|
||||||
|
|
||||||
} else { // Create
|
} else { // Create
|
||||||
mFriendModelConnection = QSharedPointer<SafeConnection>(
|
mCoreModelConnection = QSharedPointer<SafeConnection<FriendCore, CoreModel>>(
|
||||||
new SafeConnection(me, std::dynamic_pointer_cast<QObject>(CoreModel::getInstance())),
|
new SafeConnection<FriendCore, CoreModel>(me, CoreModel::getInstance()), &QObject::deleteLater);
|
||||||
&QObject::deleteLater);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,7 +201,7 @@ void FriendCore::save() { // Save Value
|
||||||
mFriendModelConnection->invokeToCore([this]() { saved(); });
|
mFriendModelConnection->invokeToCore([this]() { saved(); });
|
||||||
});
|
});
|
||||||
} else { // Creation
|
} else { // Creation
|
||||||
mFriendModelConnection->invokeToModel([this, thisCopy]() {
|
mCoreModelConnection->invokeToModel([this, thisCopy]() {
|
||||||
auto core = CoreModel::getInstance()->getCore();
|
auto core = CoreModel::getInstance()->getCore();
|
||||||
auto contact = core->createFriend();
|
auto contact = core->createFriend();
|
||||||
thisCopy->writeInto(contact);
|
thisCopy->writeInto(contact);
|
||||||
|
|
@ -212,8 +213,8 @@ void FriendCore::save() { // Save Value
|
||||||
core->getDefaultFriendList()->updateSubscriptions();
|
core->getDefaultFriendList()->updateSubscriptions();
|
||||||
}
|
}
|
||||||
emit CoreModel::getInstance()->friendAdded();
|
emit CoreModel::getInstance()->friendAdded();
|
||||||
mFriendModelConnection->invokeToCore([this, created]() {
|
mCoreModelConnection->invokeToCore([this, created]() {
|
||||||
if (created) setSelf(mFriendModelConnection->mCore);
|
if (created) setSelf(mCoreModelConnection->mCore);
|
||||||
setIsSaved(created);
|
setIsSaved(created);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -23,18 +23,19 @@
|
||||||
|
|
||||||
#include "model/friend/FriendModel.hpp"
|
#include "model/friend/FriendModel.hpp"
|
||||||
#include "tool/LinphoneEnums.hpp"
|
#include "tool/LinphoneEnums.hpp"
|
||||||
|
#include "tool/thread/SafeConnection.hpp"
|
||||||
#include "tool/thread/SafeSharedPointer.hpp"
|
#include "tool/thread/SafeSharedPointer.hpp"
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <linphone++/linphone.hh>
|
#include <linphone++/linphone.hh>
|
||||||
|
|
||||||
class SafeConnection;
|
|
||||||
|
|
||||||
// This object is defferent from usual Core. It set internal data from directly from GUI.
|
// This object is defferent from usual Core. It set internal data from directly from GUI.
|
||||||
// Values are saved on request.
|
// Values are saved on request.
|
||||||
// This allow revert feature.
|
// This allow revert feature.
|
||||||
|
|
||||||
|
class CoreModel;
|
||||||
|
|
||||||
class FriendCore : public QObject, public AbstractObject {
|
class FriendCore : public QObject, public AbstractObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|
@ -53,7 +54,7 @@ public:
|
||||||
FriendCore(const FriendCore &friendCore);
|
FriendCore(const FriendCore &friendCore);
|
||||||
~FriendCore();
|
~FriendCore();
|
||||||
void setSelf(QSharedPointer<FriendCore> me);
|
void setSelf(QSharedPointer<FriendCore> me);
|
||||||
void setSelf(SafeSharedPointer<QObject> me);
|
void setSelf(SafeSharedPointer<FriendCore> me);
|
||||||
void reset(const FriendCore &contact);
|
void reset(const FriendCore &contact);
|
||||||
|
|
||||||
QString getName() const;
|
QString getName() const;
|
||||||
|
|
@ -106,7 +107,8 @@ protected:
|
||||||
QString mPictureUri;
|
QString mPictureUri;
|
||||||
bool mIsSaved;
|
bool mIsSaved;
|
||||||
std::shared_ptr<FriendModel> mFriendModel;
|
std::shared_ptr<FriendModel> mFriendModel;
|
||||||
QSharedPointer<SafeConnection> mFriendModelConnection;
|
QSharedPointer<SafeConnection<FriendCore, FriendModel>> mFriendModelConnection;
|
||||||
|
QSharedPointer<SafeConnection<FriendCore, CoreModel>> mCoreModelConnection;
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -162,10 +162,6 @@ static inline QString getAppRootCaFilePath() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QString getAppFriendsFilePath() {
|
|
||||||
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + Constants::PathFriendsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline QString getAppMessageHistoryFilePath() {
|
static inline QString getAppMessageHistoryFilePath() {
|
||||||
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + Constants::PathMessageHistoryList;
|
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + Constants::PathMessageHistoryList;
|
||||||
}
|
}
|
||||||
|
|
@ -243,10 +239,6 @@ QString Paths::getFactoryConfigFilePath() {
|
||||||
return getReadableFilePath(getAppFactoryConfigFilePath());
|
return getReadableFilePath(getAppFactoryConfigFilePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Paths::getFriendsListFilePath() {
|
|
||||||
return getWritableFilePath(getAppFriendsFilePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Paths::getDownloadDirPath() {
|
QString Paths::getDownloadDirPath() {
|
||||||
return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + QDir::separator());
|
return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + QDir::separator());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@ QString getConfigFilePath(const QString &configPath = QString(), bool writable =
|
||||||
QString getDatabaseFilePath();
|
QString getDatabaseFilePath();
|
||||||
QString getDownloadDirPath();
|
QString getDownloadDirPath();
|
||||||
QString getFactoryConfigFilePath();
|
QString getFactoryConfigFilePath();
|
||||||
QString getFriendsListFilePath();
|
|
||||||
QString getLimeDatabasePath();
|
QString getLimeDatabasePath();
|
||||||
QString getLogsDirPath();
|
QString getLogsDirPath();
|
||||||
QString getMessageHistoryFilePath();
|
QString getMessageHistoryFilePath();
|
||||||
|
|
|
||||||
|
|
@ -57,38 +57,37 @@ MagicSearchList::~MagicSearchList() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagicSearchList::setSelf(QSharedPointer<MagicSearchList> me) {
|
void MagicSearchList::setSelf(QSharedPointer<MagicSearchList> me) {
|
||||||
mModelConnection = QSharedPointer<SafeConnection>(
|
mModelConnection = QSharedPointer<SafeConnection<MagicSearchList, MagicSearchModel>>(
|
||||||
new SafeConnection(me.objectCast<QObject>(), std::dynamic_pointer_cast<QObject>(mMagicSearch)),
|
new SafeConnection<MagicSearchList, MagicSearchModel>(me, mMagicSearch), &QObject::deleteLater);
|
||||||
&QObject::deleteLater);
|
mModelConnection->makeConnectToCore(&MagicSearchList::lSearch, [this](QString filter) {
|
||||||
mModelConnection->makeConnect(this, &MagicSearchList::lSearch, [this](QString filter) {
|
|
||||||
mModelConnection->invokeToModel([this, filter]() { mMagicSearch->search(filter); });
|
mModelConnection->invokeToModel([this, filter]() { mMagicSearch->search(filter); });
|
||||||
});
|
});
|
||||||
mModelConnection->makeConnect(this, &MagicSearchList::lSetSourceFlags, [this](int flags) {
|
mModelConnection->makeConnectToCore(&MagicSearchList::lSetSourceFlags, [this](int flags) {
|
||||||
mModelConnection->invokeToModel([this, flags]() { mMagicSearch->setSourceFlags(flags); });
|
mModelConnection->invokeToModel([this, flags]() { mMagicSearch->setSourceFlags(flags); });
|
||||||
});
|
});
|
||||||
mModelConnection->makeConnect(mMagicSearch.get(), &MagicSearchModel::sourceFlagsChanged, [this](int flags) {
|
mModelConnection->makeConnectToModel(&MagicSearchModel::sourceFlagsChanged, [this](int flags) {
|
||||||
mModelConnection->invokeToCore([this, flags]() { setSourceFlags(flags); });
|
mModelConnection->invokeToCore([this, flags]() { setSourceFlags(flags); });
|
||||||
});
|
});
|
||||||
mModelConnection->makeConnect(mMagicSearch.get(), &MagicSearchModel::aggregationFlagChanged,
|
mModelConnection->makeConnectToModel(
|
||||||
[this](LinphoneEnums::MagicSearchAggregation flag) {
|
&MagicSearchModel::aggregationFlagChanged, [this](LinphoneEnums::MagicSearchAggregation flag) {
|
||||||
mModelConnection->invokeToCore([this, flag]() { setAggregationFlag(flag); });
|
mModelConnection->invokeToCore([this, flag]() { setAggregationFlag(flag); });
|
||||||
});
|
});
|
||||||
|
|
||||||
mModelConnection->makeConnect(mMagicSearch.get(), &MagicSearchModel::searchResultsReceived,
|
mModelConnection->makeConnectToModel(&MagicSearchModel::searchResultsReceived,
|
||||||
[this](const std::list<std::shared_ptr<linphone::SearchResult>> &results) {
|
[this](const std::list<std::shared_ptr<linphone::SearchResult>> &results) {
|
||||||
auto *contacts = new QList<QSharedPointer<FriendCore>>();
|
auto *contacts = new QList<QSharedPointer<FriendCore>>();
|
||||||
for (auto it : results) {
|
for (auto it : results) {
|
||||||
QSharedPointer<FriendCore> contact;
|
QSharedPointer<FriendCore> contact;
|
||||||
if (it->getFriend()) {
|
if (it->getFriend()) {
|
||||||
contact = FriendCore::create(it->getFriend());
|
contact = FriendCore::create(it->getFriend());
|
||||||
contacts->append(contact);
|
contacts->append(contact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mModelConnection->invokeToCore([this, contacts]() {
|
mModelConnection->invokeToCore([this, contacts]() {
|
||||||
setResults(*contacts);
|
setResults(*contacts);
|
||||||
delete contacts;
|
delete contacts;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagicSearchList::setResults(const QList<QSharedPointer<FriendCore>> &contacts) {
|
void MagicSearchList::setResults(const QList<QSharedPointer<FriendCore>> &contacts) {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
|
|
||||||
class FriendCore;
|
class FriendCore;
|
||||||
|
class CoreModel;
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
// Return FriendGui list to Ui
|
// Return FriendGui list to Ui
|
||||||
|
|
@ -63,8 +64,8 @@ private:
|
||||||
LinphoneEnums::MagicSearchAggregation mAggregationFlag;
|
LinphoneEnums::MagicSearchAggregation mAggregationFlag;
|
||||||
|
|
||||||
std::shared_ptr<MagicSearchModel> mMagicSearch;
|
std::shared_ptr<MagicSearchModel> mMagicSearch;
|
||||||
QSharedPointer<SafeConnection> mModelConnection;
|
QSharedPointer<SafeConnection<MagicSearchList, MagicSearchModel>> mModelConnection;
|
||||||
QSharedPointer<SafeConnection> mCoreModelConnection;
|
QSharedPointer<SafeConnection<MagicSearchList, CoreModel>> mCoreModelConnection;
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,11 @@ AccountModel::AccountModel(const std::shared_ptr<linphone::Account> &account, QO
|
||||||
// Hack because Account doesn't provide callbacks on updated data
|
// Hack because Account doesn't provide callbacks on updated data
|
||||||
connect(this, &AccountModel::defaultAccountChanged, this,
|
connect(this, &AccountModel::defaultAccountChanged, this,
|
||||||
[this]() { emit pictureUriChanged(Utils::coreStringToAppString(mMonitor->getParams()->getPictureUri())); });
|
[this]() { emit pictureUriChanged(Utils::coreStringToAppString(mMonitor->getParams()->getPictureUri())); });
|
||||||
|
|
||||||
|
connect(CoreModel::getInstance().get(), &CoreModel::unreadNotificationsChanged, this, [this]() {
|
||||||
|
emit unreadNotificationsChanged(0 /*mMonitor->getUnreadChatMessageCount()*/,
|
||||||
|
mMonitor->getMissedCallsCount()); // TODO
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
AccountModel::~AccountModel() {
|
AccountModel::~AccountModel() {
|
||||||
|
|
@ -80,3 +85,7 @@ void AccountModel::setDefault() {
|
||||||
auto core = CoreModel::getInstance()->getCore();
|
auto core = CoreModel::getInstance()->getCore();
|
||||||
core->setDefaultAccount(mMonitor);
|
core->setDefaultAccount(mMonitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AccountModel::removeAccount() {
|
||||||
|
CoreModel::getInstance()->getCore()->removeAccount(mMonitor);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ public:
|
||||||
|
|
||||||
void setPictureUri(QString uri);
|
void setPictureUri(QString uri);
|
||||||
void setDefault();
|
void setDefault();
|
||||||
|
void removeAccount();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void registrationStateChanged(const std::shared_ptr<linphone::Account> &account,
|
void registrationStateChanged(const std::shared_ptr<linphone::Account> &account,
|
||||||
|
|
@ -50,6 +51,7 @@ signals:
|
||||||
void defaultAccountChanged(bool isDefault);
|
void defaultAccountChanged(bool isDefault);
|
||||||
|
|
||||||
void pictureUriChanged(QString uri);
|
void pictureUriChanged(QString uri);
|
||||||
|
void unreadNotificationsChanged(int unreadMessagesCount, int unreadCallsCount);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -63,18 +63,23 @@ std::shared_ptr<CoreModel> CoreModel::create(const QString &configPath, QThread
|
||||||
void CoreModel::start() {
|
void CoreModel::start() {
|
||||||
mIterateTimer = new QTimer(this);
|
mIterateTimer = new QTimer(this);
|
||||||
mIterateTimer->setInterval(30);
|
mIterateTimer->setInterval(30);
|
||||||
connect(mIterateTimer, &QTimer::timeout, [this]() { mCore->iterate(); });
|
connect(mIterateTimer, &QTimer::timeout, [this]() {
|
||||||
|
static int iterateCount = 0;
|
||||||
|
if (iterateCount != 0) qCritical() << log().arg("Multi Iterate ! ");
|
||||||
|
++iterateCount;
|
||||||
|
mCore->iterate();
|
||||||
|
--iterateCount;
|
||||||
|
});
|
||||||
setPathBeforeCreation();
|
setPathBeforeCreation();
|
||||||
mCore =
|
mCore =
|
||||||
linphone::Factory::get()->createCore(Utils::appStringToCoreString(Paths::getConfigFilePath(mConfigPath)),
|
linphone::Factory::get()->createCore(Utils::appStringToCoreString(Paths::getConfigFilePath(mConfigPath)),
|
||||||
Utils::appStringToCoreString(Paths::getFactoryConfigFilePath()), nullptr);
|
Utils::appStringToCoreString(Paths::getFactoryConfigFilePath()), nullptr);
|
||||||
setMonitor(mCore);
|
setMonitor(mCore);
|
||||||
setPathsAfterCreation();
|
setPathsAfterCreation();
|
||||||
mCore->start();
|
|
||||||
setPathAfterStart();
|
|
||||||
mCore->enableFriendListSubscription(true);
|
mCore->enableFriendListSubscription(true);
|
||||||
mCore->enableRecordAware(true);
|
mCore->enableRecordAware(true);
|
||||||
mCore->getCallsNb();
|
mCore->start();
|
||||||
|
setPathAfterStart();
|
||||||
mIterateTimer->start();
|
mIterateTimer->start();
|
||||||
}
|
}
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
@ -92,7 +97,7 @@ void CoreModel::setConfigPath(QString path) {
|
||||||
if (mConfigPath != path) {
|
if (mConfigPath != path) {
|
||||||
mConfigPath = path;
|
mConfigPath = path;
|
||||||
if (!mCore) {
|
if (!mCore) {
|
||||||
qWarning() << "[CoreModel] Setting config path after core creation is not yet supported";
|
qWarning() << log().arg("Setting config path after core creation is not yet supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -118,9 +123,6 @@ void CoreModel::setPathBeforeCreation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreModel::setPathsAfterCreation() {
|
void CoreModel::setPathsAfterCreation() {
|
||||||
QString friendsDb = Paths::getFriendsListFilePath();
|
|
||||||
qInfo() << QStringLiteral("[CoreModel] Set Database `Friends` path: `%1`").arg(friendsDb);
|
|
||||||
mCore->setFriendsDatabasePath(Utils::appStringToCoreString(friendsDb));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreModel::setPathAfterStart() {
|
void CoreModel::setPathAfterStart() {
|
||||||
|
|
@ -169,6 +171,7 @@ void CoreModel::onCallEncryptionChanged(const std::shared_ptr<linphone::Core> &c
|
||||||
}
|
}
|
||||||
void CoreModel::onCallLogUpdated(const std::shared_ptr<linphone::Core> &core,
|
void CoreModel::onCallLogUpdated(const std::shared_ptr<linphone::Core> &core,
|
||||||
const std::shared_ptr<linphone::CallLog> &callLog) {
|
const std::shared_ptr<linphone::CallLog> &callLog) {
|
||||||
|
if (callLog && callLog->getStatus() == linphone::Call::Status::Missed) emit unreadNotificationsChanged();
|
||||||
emit callLogUpdated(core, callLog);
|
emit callLogUpdated(core, callLog);
|
||||||
}
|
}
|
||||||
void CoreModel::onCallStateChanged(const std::shared_ptr<linphone::Core> &core,
|
void CoreModel::onCallStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
|
@ -242,11 +245,13 @@ void CoreModel::onLogCollectionUploadProgressIndication(const std::shared_ptr<li
|
||||||
void CoreModel::onMessageReceived(const std::shared_ptr<linphone::Core> &core,
|
void CoreModel::onMessageReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
const std::shared_ptr<linphone::ChatRoom> &room,
|
||||||
const std::shared_ptr<linphone::ChatMessage> &message) {
|
const std::shared_ptr<linphone::ChatMessage> &message) {
|
||||||
|
emit unreadNotificationsChanged();
|
||||||
emit messageReceived(core, room, message);
|
emit messageReceived(core, room, message);
|
||||||
}
|
}
|
||||||
void CoreModel::onMessagesReceived(const std::shared_ptr<linphone::Core> &core,
|
void CoreModel::onMessagesReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
const std::shared_ptr<linphone::ChatRoom> &room,
|
||||||
const std::list<std::shared_ptr<linphone::ChatMessage>> &messages) {
|
const std::list<std::shared_ptr<linphone::ChatMessage>> &messages) {
|
||||||
|
emit unreadNotificationsChanged();
|
||||||
emit messagesReceived(core, room, messages);
|
emit messagesReceived(core, room, messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ signals:
|
||||||
void loggerInitialized();
|
void loggerInitialized();
|
||||||
void friendAdded();
|
void friendAdded();
|
||||||
void friendRemoved();
|
void friendRemoved();
|
||||||
|
void unreadNotificationsChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString mConfigPath;
|
QString mConfigPath;
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ public:
|
||||||
setMonitor(monitor);
|
setMonitor(monitor);
|
||||||
}
|
}
|
||||||
~Listener() {
|
~Listener() {
|
||||||
qDebug() << "Destroying Listener";
|
|
||||||
setSelf(nullptr);
|
setSelf(nullptr);
|
||||||
}
|
}
|
||||||
virtual void onRemoveListener() {
|
virtual void onRemoveListener() {
|
||||||
|
|
|
||||||
|
|
@ -33,17 +33,16 @@ VariantObject::VariantObject(QVariant defaultValue, QObject *parent) {
|
||||||
mModelObject = QSharedPointer<SafeObject>::create();
|
mModelObject = QSharedPointer<SafeObject>::create();
|
||||||
mModelObject->moveToThread(CoreModel::getInstance()->thread());
|
mModelObject->moveToThread(CoreModel::getInstance()->thread());
|
||||||
|
|
||||||
mConnection = QSharedPointer<SafeConnection>(
|
mConnection = QSharedPointer<SafeConnection<SafeObject, SafeObject>>(
|
||||||
new SafeConnection(mCoreObject.objectCast<QObject>(), mModelObject.objectCast<QObject>()),
|
new SafeConnection<SafeObject, SafeObject>(mCoreObject, mModelObject), &QObject::deleteLater);
|
||||||
&QObject::deleteLater);
|
|
||||||
|
|
||||||
mConnection->makeConnect(mCoreObject.get(), &SafeObject::setValue, [this](QVariant value) {
|
mConnection->makeConnectToCore(&SafeObject::setValue, [this](QVariant value) {
|
||||||
mConnection->invokeToModel([this, value]() { mModelObject->onSetValue(value); });
|
mConnection->invokeToModel([this, value]() { mModelObject->onSetValue(value); });
|
||||||
});
|
});
|
||||||
mConnection->makeConnect(mModelObject.get(), &SafeObject::setValue, [this](QVariant value) {
|
mConnection->makeConnectToModel(&SafeObject::setValue, [this](QVariant value) {
|
||||||
mConnection->invokeToCore([this, value]() { mCoreObject->onSetValue(value); });
|
mConnection->invokeToCore([this, value]() { mCoreObject->onSetValue(value); });
|
||||||
});
|
});
|
||||||
mConnection->makeConnect(mModelObject.get(), &SafeObject::valueChanged, [this](QVariant value) {
|
mConnection->makeConnectToModel(&SafeObject::valueChanged, [this](QVariant value) {
|
||||||
mConnection->invokeToCore([this, value]() { mCoreObject->valueChanged(value); });
|
mConnection->invokeToCore([this, value]() { mCoreObject->valueChanged(value); });
|
||||||
});
|
});
|
||||||
connect(mCoreObject.get(), &SafeObject::valueChanged, this, &VariantObject::valueChanged);
|
connect(mCoreObject.get(), &SafeObject::valueChanged, this, &VariantObject::valueChanged);
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@
|
||||||
#include "SafeObject.hpp"
|
#include "SafeObject.hpp"
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
#include "tool/thread/SafeConnection.hpp"
|
||||||
|
|
||||||
|
class CoreModel;
|
||||||
|
|
||||||
class VariantObject : public QObject, public AbstractObject {
|
class VariantObject : public QObject, public AbstractObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QVariant value READ getValue NOTIFY valueChanged)
|
Q_PROPERTY(QVariant value READ getValue NOTIFY valueChanged)
|
||||||
|
|
@ -40,21 +42,21 @@ public:
|
||||||
|
|
||||||
template <typename Func, typename... Args>
|
template <typename Func, typename... Args>
|
||||||
void makeRequest(Func &&callable, Args &&...args) {
|
void makeRequest(Func &&callable, Args &&...args) {
|
||||||
mConnection->makeConnect(mCoreObject.get(), &SafeObject::requestValue, [this, callable, args...]() {
|
mConnection->makeConnectToCore(&SafeObject::requestValue, [this, callable, args...]() {
|
||||||
mConnection->invokeToModel([this, callable, args...]() { mModelObject->setValue(callable(args...)); });
|
mConnection->invokeToModel([this, callable, args...]() { mModelObject->setValue(callable(args...)); });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
template <typename SenderClass>
|
template <typename Sender, typename SenderClass>
|
||||||
void makeUpdate(const typename QtPrivate::FunctionPointer<SenderClass>::Object *sender, SenderClass signal) {
|
void makeUpdate(Sender sender, SenderClass signal) {
|
||||||
mConnection->makeConnect(sender, signal,
|
mConnection->makeConnectToModel(
|
||||||
[this]() { mConnection->invokeToCore([this]() { mCoreObject->requestValue(); }); });
|
sender, signal, [this]() { mConnection->invokeToCore([this]() { mCoreObject->requestValue(); }); });
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant getValue() const;
|
QVariant getValue() const;
|
||||||
void requestValue();
|
void requestValue();
|
||||||
|
|
||||||
QSharedPointer<SafeObject> mCoreObject, mModelObject;
|
QSharedPointer<SafeObject> mCoreObject, mModelObject;
|
||||||
QSharedPointer<SafeConnection> mConnection;
|
QSharedPointer<SafeConnection<SafeObject, SafeObject>> mConnection;
|
||||||
signals:
|
signals:
|
||||||
void valueChanged(QVariant value);
|
void valueChanged(QVariant value);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ list(APPEND _LINPHONEAPP_SOURCES
|
||||||
|
|
||||||
tool/LinphoneEnums.cpp
|
tool/LinphoneEnums.cpp
|
||||||
tool/thread/SafeSharedPointer.hpp
|
tool/thread/SafeSharedPointer.hpp
|
||||||
tool/thread/SafeConnection.cpp
|
tool/thread/SafeConnection.hpp
|
||||||
tool/thread/Thread.cpp
|
tool/thread/Thread.cpp
|
||||||
tool/providers/AvatarProvider.cpp
|
tool/providers/AvatarProvider.cpp
|
||||||
tool/providers/ImageProvider.cpp
|
tool/providers/ImageProvider.cpp
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,6 @@ constexpr char Constants::PathConfig[];
|
||||||
constexpr char Constants::PathDatabase[];
|
constexpr char Constants::PathDatabase[];
|
||||||
constexpr char Constants::PathFactoryConfig[];
|
constexpr char Constants::PathFactoryConfig[];
|
||||||
constexpr char Constants::PathRootCa[];
|
constexpr char Constants::PathRootCa[];
|
||||||
constexpr char Constants::PathFriendsList[];
|
|
||||||
constexpr char Constants::PathLimeDatabase[];
|
constexpr char Constants::PathLimeDatabase[];
|
||||||
constexpr char Constants::PathMessageHistoryList[];
|
constexpr char Constants::PathMessageHistoryList[];
|
||||||
constexpr char Constants::PathZrtpSecrets[];
|
constexpr char Constants::PathZrtpSecrets[];
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,6 @@ public:
|
||||||
static constexpr char PathDatabase[] = "/linphone.db";
|
static constexpr char PathDatabase[] = "/linphone.db";
|
||||||
static constexpr char PathFactoryConfig[] = "/" EXECUTABLE_NAME "/linphonerc-factory";
|
static constexpr char PathFactoryConfig[] = "/" EXECUTABLE_NAME "/linphonerc-factory";
|
||||||
static constexpr char PathRootCa[] = "/" EXECUTABLE_NAME "/rootca.pem";
|
static constexpr char PathRootCa[] = "/" EXECUTABLE_NAME "/rootca.pem";
|
||||||
static constexpr char PathFriendsList[] = "/friends.db";
|
|
||||||
static constexpr char PathLimeDatabase[] = "/x3dh.c25519.sqlite3";
|
static constexpr char PathLimeDatabase[] = "/x3dh.c25519.sqlite3";
|
||||||
static constexpr char PathMessageHistoryList[] = "/message-history.db";
|
static constexpr char PathMessageHistoryList[] = "/message-history.db";
|
||||||
static constexpr char PathZrtpSecrets[] = "/zidcache";
|
static constexpr char PathZrtpSecrets[] = "/zidcache";
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,9 @@ char *Utils::rstrstr(const char *a, const char *b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantObject *Utils::getDisplayName(const QString &address) {
|
VariantObject *Utils::getDisplayName(const QString &address) {
|
||||||
VariantObject *data = new VariantObject(address); // Scope : GUI
|
QStringList splitted = address.split(":");
|
||||||
|
if (splitted.size() > 0 && splitted[0] == "sip") splitted.removeFirst();
|
||||||
|
VariantObject *data = new VariantObject(splitted.first().split("@").first()); // Scope : GUI
|
||||||
data->makeRequest([address]() {
|
data->makeRequest([address]() {
|
||||||
QString displayName = ToolModel::getDisplayName(address);
|
QString displayName = ToolModel::getDisplayName(address);
|
||||||
return displayName;
|
return displayName;
|
||||||
|
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "SafeConnection.hpp"
|
|
||||||
|
|
||||||
SafeConnection::SafeConnection(SafeSharedPointer<QObject> core, SafeSharedPointer<QObject> model)
|
|
||||||
: mCore(core), mModel(model) {
|
|
||||||
}
|
|
||||||
SafeConnection::~SafeConnection() {
|
|
||||||
mLocker.lock();
|
|
||||||
if (mCore.mCountRef != 0 || mModel.mCountRef != 0)
|
|
||||||
qCritical() << "[SafeConnection] Destruction while still having references. CoreRef=" << mCore.mCountRef
|
|
||||||
<< "ModelRef=" << mModel.mCountRef;
|
|
||||||
mLocker.unlock();
|
|
||||||
}
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#define SAFE_CONNECTION_H_
|
#define SAFE_CONNECTION_H_
|
||||||
|
|
||||||
#include "SafeSharedPointer.hpp"
|
#include "SafeSharedPointer.hpp"
|
||||||
|
#include "model/core/CoreModel.hpp"
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
|
@ -60,19 +61,40 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
template <class A, class B>
|
||||||
class SafeConnection : public QObject {
|
class SafeConnection : public QObject {
|
||||||
public:
|
public:
|
||||||
SafeConnection(SafeSharedPointer<QObject> a, SafeSharedPointer<QObject> b);
|
// SafeConnection(SafeSharedPointer<QObject> a, SafeSharedPointer<QObject> b);
|
||||||
~SafeConnection();
|
SafeConnection(QSharedPointer<A> a, std::shared_ptr<B> b)
|
||||||
SafeSharedPointer<QObject> mCore, mModel;
|
: mCore(a), mModel(b), mCoreObject(a.get()), mModelObject(b.get()) {
|
||||||
|
}
|
||||||
|
SafeConnection(QSharedPointer<A> a, QSharedPointer<B> b)
|
||||||
|
: mCore(a), mModel(b), mCoreObject(a.get()), mModelObject(b.get()) {
|
||||||
|
}
|
||||||
|
~SafeConnection() {
|
||||||
|
mLocker.lock();
|
||||||
|
if (mCore.mCountRef != 0 || mModel.mCountRef != 0)
|
||||||
|
qCritical() << "[SafeConnection] Destruction while still having references. CoreRef=" << mCore.mCountRef
|
||||||
|
<< "ModelRef=" << mModel.mCountRef;
|
||||||
|
mCore.reset();
|
||||||
|
mModel.reset();
|
||||||
|
mLocker.unlock();
|
||||||
|
}
|
||||||
|
SafeSharedPointer<A> mCore;
|
||||||
|
SafeSharedPointer<B> mModel;
|
||||||
QMutex mLocker;
|
QMutex mLocker;
|
||||||
|
|
||||||
template <typename Func1, typename Func2>
|
template <typename Func1, typename Func2>
|
||||||
static inline QMetaObject::Connection makeConnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender,
|
inline QMetaObject::Connection makeConnectToModel(Func1 signal, Func2 slot) {
|
||||||
Func1 signal,
|
return connect(mModelObject, signal, mCoreObject, slot, Qt::DirectConnection);
|
||||||
Func2 slot,
|
}
|
||||||
Qt::ConnectionType type = Qt::AutoConnection) {
|
template <typename Sender, typename Func1, typename Func2>
|
||||||
return connect(sender, signal, sender, slot, type);
|
inline QMetaObject::Connection makeConnectToModel(Sender sender, Func1 signal, Func2 slot) {
|
||||||
|
return connect(sender, signal, mCoreObject, slot, Qt::DirectConnection);
|
||||||
|
}
|
||||||
|
template <typename Func1, typename Func2>
|
||||||
|
inline QMetaObject::Connection makeConnectToCore(Func1 signal, Func2 slot) {
|
||||||
|
return connect(mCoreObject, signal, mModelObject, slot, Qt::DirectConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Func, typename... Args>
|
template <typename Func, typename... Args>
|
||||||
|
|
@ -112,6 +134,10 @@ public:
|
||||||
mModel.unlock();
|
mModel.unlock();
|
||||||
mLocker.unlock();
|
mLocker.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
A *mCoreObject = nullptr;
|
||||||
|
B *mModelObject = nullptr; // Use only for makeConnects
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ import UtilsCpp
|
||||||
Item {
|
Item {
|
||||||
id: mainItem
|
id: mainItem
|
||||||
|
|
||||||
|
signal addAccountRequest()
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
// spacing: 30
|
// spacing: 30
|
||||||
|
|
@ -79,6 +81,7 @@ Item {
|
||||||
contentHeight: accounts.height
|
contentHeight: accounts.height
|
||||||
Accounts{
|
Accounts{
|
||||||
id: accounts
|
id: accounts
|
||||||
|
onAddAccountRequest: mainItem.addAccountRequest()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ Window {
|
||||||
Component {
|
Component {
|
||||||
id: loginPage
|
id: loginPage
|
||||||
LoginPage {
|
LoginPage {
|
||||||
|
showBackButton: accountProxy.haveAccount
|
||||||
|
onGoBack: mainWindowStackView.replace(mainPage)
|
||||||
onUseSIPButtonClicked: mainWindowStackView.push(sipLoginPage)
|
onUseSIPButtonClicked: mainWindowStackView.push(sipLoginPage)
|
||||||
onGoToRegister: mainWindowStackView.replace(registerPage)
|
onGoToRegister: mainWindowStackView.replace(registerPage)
|
||||||
onConnectionSucceed: {
|
onConnectionSucceed: {
|
||||||
|
|
@ -50,7 +52,7 @@ Window {
|
||||||
Component {
|
Component {
|
||||||
id: sipLoginPage
|
id: sipLoginPage
|
||||||
SIPLoginPage {
|
SIPLoginPage {
|
||||||
onReturnToLogin: mainWindowStackView.pop()
|
onGoBack: mainWindowStackView.pop()
|
||||||
onGoToRegister: mainWindowStackView.replace(registerPage)
|
onGoToRegister: mainWindowStackView.replace(registerPage)
|
||||||
|
|
||||||
onConnectionSucceed: {
|
onConnectionSucceed: {
|
||||||
|
|
@ -90,6 +92,7 @@ Window {
|
||||||
Component {
|
Component {
|
||||||
id: mainPage
|
id: mainPage
|
||||||
MainLayout {
|
MainLayout {
|
||||||
|
onAddAccountRequest: mainWindowStackView.replace(loginPage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import QtQuick 2.15
|
import QtCore
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick
|
||||||
import QtQuick.Controls 2.2 as Control
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls as Control
|
||||||
|
import QtQuick.Dialogs
|
||||||
|
|
||||||
import Linphone
|
import Linphone
|
||||||
import UtilsCpp
|
import UtilsCpp
|
||||||
|
|
@ -13,6 +15,9 @@ Item {
|
||||||
readonly property int leftPadding: 32 * DefaultStyle.dp
|
readonly property int leftPadding: 32 * DefaultStyle.dp
|
||||||
readonly property int rightPadding: 32 * DefaultStyle.dp
|
readonly property int rightPadding: 32 * DefaultStyle.dp
|
||||||
readonly property int spacing: 16 * DefaultStyle.dp
|
readonly property int spacing: 16 * DefaultStyle.dp
|
||||||
|
|
||||||
|
signal addAccountRequest()
|
||||||
|
|
||||||
implicitHeight: list.contentHeight + topPadding + bottomPadding + 32 * DefaultStyle.dp + 1 + newAccountArea.height
|
implicitHeight: list.contentHeight + topPadding + bottomPadding + 32 * DefaultStyle.dp + 1 + newAccountArea.height
|
||||||
ColumnLayout{
|
ColumnLayout{
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
|
@ -28,8 +33,21 @@ Item {
|
||||||
spacing: mainItem.spacing
|
spacing: mainItem.spacing
|
||||||
model: AccountProxy{}
|
model: AccountProxy{}
|
||||||
delegate: Contact{
|
delegate: Contact{
|
||||||
|
id: contactItem
|
||||||
width: list.width
|
width: list.width
|
||||||
account: modelData
|
account: modelData
|
||||||
|
onAvatarClicked: fileDialog.open()
|
||||||
|
onBackgroundClicked: modelData.core.lSetDefaultAccount()
|
||||||
|
FileDialog {
|
||||||
|
id: fileDialog
|
||||||
|
currentFolder: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]
|
||||||
|
onAccepted: {
|
||||||
|
var avatarPath = UtilsCpp.createAvatar( selectedFile )
|
||||||
|
if(avatarPath){
|
||||||
|
modelData.core.pictureUri = avatarPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rectangle{
|
Rectangle{
|
||||||
|
|
@ -40,10 +58,10 @@ Item {
|
||||||
height: 1
|
height: 1
|
||||||
color: DefaultStyle.main2_300
|
color: DefaultStyle.main2_300
|
||||||
}
|
}
|
||||||
MouseArea{ // TODO
|
MouseArea{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: 32 * DefaultStyle.dp
|
Layout.preferredHeight: 32 * DefaultStyle.dp
|
||||||
onClicked: console.log('New!')
|
onClicked: mainItem.addAccountRequest()
|
||||||
RowLayout{
|
RowLayout{
|
||||||
id: newAccountArea
|
id: newAccountArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,11 @@ StackView{
|
||||||
id: mainItem
|
id: mainItem
|
||||||
property FriendGui contact
|
property FriendGui contact
|
||||||
property AccountGui account
|
property AccountGui account
|
||||||
onAccountChanged: if(account) replace(avatar, StackView.Immediate)
|
|
||||||
property string address: account ? account.core.identityAddress : ''
|
property string address: account ? account.core.identityAddress : ''
|
||||||
property var displayNameObj: UtilsCpp.getDisplayName(address)
|
property var displayNameObj: UtilsCpp.getDisplayName(address)
|
||||||
property bool haveAvatar: (account && account.core.pictureUri )
|
property bool haveAvatar: (account && account.core.pictureUri )
|
||||||
|| (contact && contact.core.pictureUri)
|
|| (contact && contact.core.pictureUri)
|
||||||
|
onHaveAvatarChanged: replace(haveAvatar ? avatar : initials, StackView.Immediate)
|
||||||
|
|
||||||
initialItem: haveAvatar ? avatar : initials
|
initialItem: haveAvatar ? avatar : initials
|
||||||
Component{
|
Component{
|
||||||
|
|
@ -25,12 +25,10 @@ StackView{
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: initialItem
|
id: initialItem
|
||||||
property string initials: UtilsCpp.getInitials(mainItem.displayNameObj.value)
|
property string initials: UtilsCpp.getInitials(mainItem.displayNameObj.value)
|
||||||
onInitialsChanged: console.log("newInit:"+initials)
|
|
||||||
radius: width / 2
|
radius: width / 2
|
||||||
color: DefaultStyle.main2_200
|
color: DefaultStyle.main2_200
|
||||||
height: mainItem.height
|
height: mainItem.height
|
||||||
width: height
|
width: height
|
||||||
Component.onCompleted: console.log("init:"+initials)
|
|
||||||
Text {
|
Text {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import QtCore
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
import QtQuick.Dialogs
|
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -11,7 +10,14 @@ import UtilsCpp
|
||||||
Rectangle{
|
Rectangle{
|
||||||
id: mainItem
|
id: mainItem
|
||||||
property AccountGui account
|
property AccountGui account
|
||||||
|
signal avatarClicked()
|
||||||
|
signal backgroundClicked()
|
||||||
|
|
||||||
height: 45 * DefaultStyle.dp
|
height: 45 * DefaultStyle.dp
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: mainItem.backgroundClicked()
|
||||||
|
}
|
||||||
RowLayout{
|
RowLayout{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
@ -22,17 +28,7 @@ Rectangle{
|
||||||
account: mainItem.account
|
account: mainItem.account
|
||||||
MouseArea{
|
MouseArea{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: fileDialog.open()
|
onClicked: mainItem.avatarClicked()
|
||||||
}
|
|
||||||
FileDialog {
|
|
||||||
id: fileDialog
|
|
||||||
currentFolder: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]
|
|
||||||
onAccepted: {
|
|
||||||
var avatarPath = UtilsCpp.createAvatar( selectedFile )
|
|
||||||
if(avatarPath){
|
|
||||||
mainItem.account.core.pictureUri = avatarPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ContactDescription{
|
ContactDescription{
|
||||||
|
|
@ -95,7 +91,7 @@ Rectangle{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item{ // TODO
|
Item{
|
||||||
Layout.preferredWidth: 100 * DefaultStyle.dp
|
Layout.preferredWidth: 100 * DefaultStyle.dp
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Rectangle{
|
Rectangle{
|
||||||
|
|
@ -103,6 +99,7 @@ Rectangle{
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: 10 * DefaultStyle.dp
|
anchors.leftMargin: 10 * DefaultStyle.dp
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
visible: unreadCount.text > 0
|
||||||
width: 22 * DefaultStyle.dp
|
width: 22 * DefaultStyle.dp
|
||||||
height: 22 * DefaultStyle.dp
|
height: 22 * DefaultStyle.dp
|
||||||
radius: width/2
|
radius: width/2
|
||||||
|
|
@ -112,10 +109,15 @@ Rectangle{
|
||||||
Text{
|
Text{
|
||||||
id: unreadCount
|
id: unreadCount
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
anchors.margins: 2 * DefaultStyle.dp
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
color: DefaultStyle.grey_0
|
color: DefaultStyle.grey_0
|
||||||
text: '2'
|
minimumPixelSize: 5
|
||||||
|
fontSizeMode: Text.Fit
|
||||||
|
font.pixelSize: 20 * DefaultStyle.dp
|
||||||
|
property var unread: mainItem.account.core.unreadNotifications
|
||||||
|
text: unread > 100 ? '+' : unread
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +132,7 @@ Rectangle{
|
||||||
colorizationColor: DefaultStyle.main2_500main
|
colorizationColor: DefaultStyle.main2_500main
|
||||||
MouseArea{ // TODO
|
MouseArea{ // TODO
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: console.log('Manage!')
|
onClicked: console.log('TODO: Manage!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,28 @@ import Linphone
|
||||||
|
|
||||||
LoginLayout {
|
LoginLayout {
|
||||||
id: mainItem
|
id: mainItem
|
||||||
|
property bool showBackButton: false
|
||||||
|
signal goBack()
|
||||||
signal useSIPButtonClicked()
|
signal useSIPButtonClicked()
|
||||||
signal goToRegister()
|
signal goToRegister()
|
||||||
signal connectionSucceed()
|
signal connectionSucceed()
|
||||||
|
|
||||||
titleContent: RowLayout {
|
titleContent: RowLayout {
|
||||||
|
Control.Button {
|
||||||
|
Layout.preferredHeight: 40 * DefaultStyle.dp
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
visible: mainItem.showBackButton
|
||||||
|
icon.width: width
|
||||||
|
icon.height: height
|
||||||
|
icon.source: AppIcons.returnArrow
|
||||||
|
background: Rectangle {
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
console.debug("[LoginLayout] User: return")
|
||||||
|
mainItem.goBack()
|
||||||
|
}
|
||||||
|
}
|
||||||
Image {
|
Image {
|
||||||
fillMode: Image.PreserveAspectFit
|
fillMode: Image.PreserveAspectFit
|
||||||
source: AppIcons.profile
|
source: AppIcons.profile
|
||||||
|
|
@ -24,7 +41,7 @@ LoginLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
Layout.rightMargin: 15
|
Layout.rightMargin: 15 * DefaultStyle.dp
|
||||||
text: "No account yet ?"
|
text: "No account yet ?"
|
||||||
font.pointSize: DefaultStyle.indicatorMessageTextSize
|
font.pointSize: DefaultStyle.indicatorMessageTextSize
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +64,7 @@ LoginLayout {
|
||||||
onConnectionSucceed: mainItem.connectionSucceed()
|
onConnectionSucceed: mainItem.connectionSucceed()
|
||||||
}
|
}
|
||||||
Button {
|
Button {
|
||||||
Layout.topMargin: 40
|
Layout.topMargin: 40 * DefaultStyle.dp
|
||||||
inversedColors: true
|
inversedColors: true
|
||||||
text: "Use SIP Account"
|
text: "Use SIP Account"
|
||||||
onClicked: {mainItem.useSIPButtonClicked()}
|
onClicked: {mainItem.useSIPButtonClicked()}
|
||||||
|
|
@ -57,8 +74,8 @@ LoginLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
Image {
|
Image {
|
||||||
Layout.rightMargin: 40
|
Layout.rightMargin: 40 * DefaultStyle.dp
|
||||||
Layout.preferredWidth: 300
|
Layout.preferredWidth: 300 * DefaultStyle.dp
|
||||||
fillMode: Image.PreserveAspectFit
|
fillMode: Image.PreserveAspectFit
|
||||||
source: AppIcons.loginImage
|
source: AppIcons.loginImage
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import ConstantsCpp 1.0
|
||||||
|
|
||||||
LoginLayout {
|
LoginLayout {
|
||||||
id: mainItem
|
id: mainItem
|
||||||
signal returnToLogin()
|
signal goBack()
|
||||||
signal goToRegister()
|
signal goToRegister()
|
||||||
signal connectionSucceed()
|
signal connectionSucceed()
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ LoginLayout {
|
||||||
}
|
}
|
||||||
onClicked: {
|
onClicked: {
|
||||||
console.debug("[SIPLoginPage] User: return")
|
console.debug("[SIPLoginPage] User: return")
|
||||||
mainItem.returnToLogin()
|
mainItem.goBack()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Image {
|
Image {
|
||||||
|
|
|
||||||
2
external/linphone-sdk
vendored
2
external/linphone-sdk
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit bf9106ee57b8a32aea2693f0fc69c2397a66d570
|
Subproject commit d07e85507cb6ddba7fe397f5fc699835516945aa
|
||||||
Loading…
Reference in a new issue